* [Qemu-devel] [PATCH 001/147] s390x: fix -initrd in virtio machine
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 002/147] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
` (146 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
From: Alexander Graf <agraf@suse.de>
When using -initrd in the virtio machine, we need to indicate the initrd
start and size inside the kernel image. These parameters need to be stored
in native endianness.
Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Richard Henderson <rth@twiddle.net>
---
hw/s390-virtio.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 47eed35..12ae612 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -284,8 +284,8 @@ static void s390_init(ram_addr_t my_ram_size,
}
/* we have to overwrite values in the kernel image, which are "rom" */
- memcpy(rom_ptr(INITRD_PARM_START), &initrd_offset, 8);
- memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8);
+ stq_p(rom_ptr(INITRD_PARM_START), initrd_offset);
+ stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
}
if (rom_ptr(KERN_PARM_AREA)) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 002/147] tcg: Add TCGV_IS_UNUSED_*
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 001/147] s390x: fix -initrd in virtio machine Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 003/147] target-s390: Disassemble more z10 and z196 opcodes Richard Henderson
` (145 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: 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 562f0ad..88c1073 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -252,6 +252,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] 152+ messages in thread
* [Qemu-devel] [PATCH 003/147] target-s390: Disassemble more z10 and z196 opcodes
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 001/147] s390x: fix -initrd in virtio machine Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 002/147] tcg: Add TCGV_IS_UNUSED_* Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 004/147] target-s390: Fix disassembly of cpsdr Richard Henderson
` (144 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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] 152+ messages in thread
* [Qemu-devel] [PATCH 004/147] target-s390: Fix disassembly of cpsdr
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (2 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 003/147] target-s390: Disassemble more z10 and z196 opcodes Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 005/147] target-s390: Fix gdbstub Richard Henderson
` (143 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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] 152+ messages in thread
* [Qemu-devel] [PATCH 005/147] target-s390: Fix gdbstub
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (3 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 004/147] target-s390: Fix disassembly of cpsdr Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 006/147] target-s390: Add missing temp_free in gen_op_calc_cc Richard Henderson
` (142 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 d02ec75..8173dc5 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -40,6 +40,7 @@
#include "cpu.h"
#include "qemu_socket.h"
#include "kvm.h"
+#include "bitops.h"
#ifndef TARGET_CPU_MEMORY_RW_DEBUG
static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr,
@@ -1535,27 +1536,34 @@ 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:
+ cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
+ val = deposit64(env->psw.mask, 44, 2, cc_op);
+ 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;
@@ -1570,20 +1578,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 = extract64(tmpl, 44, 2);
+ 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] 152+ messages in thread
* [Qemu-devel] [PATCH 006/147] target-s390: Add missing temp_free in gen_op_calc_cc
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (4 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 005/147] target-s390: Fix gdbstub Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 007/147] target-s390: Use TCG registers for FPR Richard Henderson
` (141 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 db464cc..925fd5b 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] 152+ messages in thread
* [Qemu-devel] [PATCH 007/147] target-s390: Use TCG registers for FPR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (5 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 006/147] target-s390: Add missing temp_free in gen_op_calc_cc Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 008/147] target-s390: Register helpers Richard Henderson
` (140 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 925fd5b..e01ca1c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -97,7 +97,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 {
@@ -134,21 +134,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),
@@ -160,13 +161,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]);
}
}
@@ -180,14 +186,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;
}
@@ -212,39 +222,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)
@@ -255,7 +261,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] 152+ messages in thread
* [Qemu-devel] [PATCH 008/147] target-s390: Register helpers
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (6 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 007/147] target-s390: Use TCG registers for FPR Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 009/147] target-s390: Fix SACF exit Richard Henderson
` (139 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Which highlights a lot of cc helpers that no longer exist.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 23 ++++++-----------------
target-s390x/translate.c | 4 ++++
2 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5419f37..e72e16e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -7,21 +7,10 @@ DEF_HELPER_4(xc, i32, env, i32, i64, i64)
DEF_HELPER_4(mvc, void, env, i32, i64, i64)
DEF_HELPER_4(clc, i32, env, i32, i64, i64)
DEF_HELPER_3(mvcl, i32, env, i32, i32)
-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_3(mlg, void, env, i32, 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)
-DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
-DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
-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(clst, i32, env, i32, i32, i32)
DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
@@ -38,7 +27,6 @@ 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)
@@ -112,11 +100,15 @@ DEF_HELPER_3(sqdbr, void, env, i32, i32)
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)
+DEF_HELPER_3(cksm, void, env, i32, i32)
+
+DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
+ i32, env, i32, i64, i64, i64)
+#ifndef CONFIG_USER_ONLY
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)
@@ -144,9 +136,6 @@ 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_3(stura, void, env, i64, i32)
-DEF_HELPER_3(cksm, void, env, i32, i32)
-
-DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
- i32, env, i32, i64, i64, i64)
+#endif
#include "def-helper.h"
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e01ca1c..23e1042 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -174,6 +174,10 @@ void s390x_translate_init(void)
offsetof(CPUS390XState, fregs[i].d),
cpu_reg_names[i + 16]);
}
+
+ /* register helpers */
+#define GEN_HELPER 2
+#include "helper.h"
}
static inline TCGv_i64 load_reg(int reg)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 009/147] target-s390: Fix SACF exit
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (7 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 008/147] target-s390: Register helpers Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 010/147] target-s390: Fix BCR Richard Henderson
` (138 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
DISAS_EXCP is exit via exception; we wanted DISAS_JUMP.
This matters when we start cleaning up the TB exit paths.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 23e1042..f0fadf2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2933,7 +2933,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
tcg_temp_free_i64(tmp);
break;
case 0x79: /* SACF D2(B2) [S] */
- /* Store Clock Extended */
+ /* Set Address Space Control Fast */
check_privileged(env, s, ilc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -2943,7 +2943,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
/* addressing mode has changed, so end the block */
s->pc += ilc * 2;
update_psw_addr(s);
- s->is_jmp = DISAS_EXCP;
+ s->is_jmp = DISAS_JUMP;
break;
case 0x7d: /* STSI D2,(B2) [S] */
check_privileged(env, s, ilc);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 010/147] target-s390: Fix BCR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (8 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 009/147] target-s390: Fix SACF exit Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 011/147] target-s390: Tidy unconditional BRCL Richard Henderson
` (137 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
There were are two exit paths for which we forgot to
copy s->cc_op back to the tcg register.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f0fadf2..3caf386 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1212,6 +1212,7 @@ static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
if (mask == 0xf) {
/* unconditional */
+ gen_update_cc_op(s);
tcg_gen_mov_i64(psw_addr, target);
tcg_gen_exit_tb(0);
} else if (mask == 0) {
@@ -1223,6 +1224,7 @@ static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
tcg_gen_mov_i64(new_addr, target);
skip = gen_new_label();
gen_jcc(s, mask, skip);
+ gen_update_cc_op(s);
tcg_gen_mov_i64(psw_addr, new_addr);
tcg_temp_free_i64(new_addr);
tcg_gen_exit_tb(0);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 011/147] target-s390: Tidy unconditional BRCL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (9 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 010/147] target-s390: Fix BCR Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 012/147] target-s390: Fix PSW_MASK handling Richard Henderson
` (136 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Yes, we're about to rewrite all of this, but having this unconditional
jump recompute cc_op is a large source of "false diff errors" when
trying to examine before and after dumps.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3caf386..5a7612c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3706,6 +3706,11 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
tcg_temp_free_i64(tmp);
break;
case 0x4: /* BRCL M1,I2 [RIL] */
+ if (r1 == 15) { /* m1 == r1 */
+ gen_goto_tb(s, 0, target);
+ s->is_jmp = DISAS_TB_JUMP;
+ break;
+ }
/* m1 & (1 << (3 - cc)) */
tmp32_1 = tcg_const_i32(3);
tmp32_2 = tcg_const_i32(1);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 012/147] target-s390: Fix PSW_MASK handling
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (10 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 011/147] target-s390: Tidy unconditional BRCL Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 013/147] target-s390: Add format based disassassmbly infrastructure Richard Henderson
` (135 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
We were treating psw.mask as the 32-bit quantity it is in ESA mode.
In particular, the CC field was at the wrong place.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.c | 9 +++++----
target-s390x/translate.c | 2 ++
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 22256b0..27c3123 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -454,18 +454,19 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
env->psw.addr = addr;
env->psw.mask = mask;
- env->cc_op = (mask >> 13) & 3;
+ env->cc_op = (mask >> 44) & 3;
}
static uint64_t get_psw_mask(CPUS390XState *env)
{
- uint64_t r = env->psw.mask;
+ uint64_t r;
env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
- r &= ~(3ULL << 13);
+ r = env->psw.mask;
+ r &= ~PSW_MASK_CC;
assert(!(env->cc_op & ~3));
- r |= env->cc_op << 13;
+ r |= (uint64_t)env->cc_op << 44;
return r;
}
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5a7612c..e140c79 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4559,6 +4559,8 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
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));
+ /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
+ tcg_gen_shli_i64(tmp2, tmp2, 32);
gen_helper_load_psw(cpu_env, tmp2, tmp3);
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 013/147] target-s390: Add format based disassassmbly infrastructure
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (11 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 012/147] target-s390: Fix PSW_MASK handling Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 014/147] target-s390: Split out disas_jcc Richard Henderson
` (134 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 | 1114 ++++++++++++++++++++++++++++--------------
3 files changed, 859 insertions(+), 364 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 e140c79..02736e3 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
@@ -295,15 +303,12 @@ static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
{
- return (uint64_t)cpu_ldl_code(env, pc);
+ return (uint64_t)(uint32_t)cpu_ldl_code(env, pc);
}
static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc)
{
- uint64_t opc;
- opc = (uint64_t)cpu_lduw_code(env, pc) << 32;
- opc |= (uint64_t)(uint32_t)cpu_ldl_code(env, pc + 2);
- return opc;
+ return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
}
static inline int get_mem_index(DisasContext *s)
@@ -607,17 +612,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);
@@ -644,12 +638,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);
@@ -1535,72 +1523,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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));
@@ -1723,40 +1645,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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;
@@ -3350,68 +3238,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3469,29 +3295,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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;
@@ -3794,54 +3597,10 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
static void disas_c2(CPUS390XState *env, 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);
@@ -4059,42 +3818,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, 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(env, s->pc);
@@ -4380,51 +4103,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
@@ -5131,9 +4809,699 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
gen_illegal_opcode(env, 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(CPUS390XState *env, DisasContext *s,
+ DisasFields *f)
+{
+ uint64_t insn, pc = s->pc;
+ int op, op2;
+ const DisasInsn *info;
+
+ insn = ld_code2(env, pc);
+ op = (insn >> 8) & 0xff;
+ switch (get_ilc(op)) {
+ case 1:
+ insn = insn << 48;
+ break;
+ case 2:
+ insn = ld_code4(env, pc) << 32;
+ break;
+ case 3:
+ insn = (insn << 48) | (ld_code4(env, 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(CPUS390XState *env, DisasContext *s)
+{
+ const DisasInsn *insn;
+ ExitStatus ret = NO_EXIT;
+ DisasFields f;
+ DisasOps o;
+
+ insn = extract_insn(env, 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(env, 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,
@@ -5147,6 +5515,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;
@@ -5155,10 +5524,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;
@@ -5194,7 +5564,7 @@ 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();
}
@@ -5202,35 +5572,50 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
tcg_gen_debug_insn_start(dc.pc);
}
- disas_s390_insn(env, &dc);
-
- num_insns++;
- if (env->singlestep_enabled) {
- gen_debug(&dc);
+ status = translate_one(env, &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 (!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);
- }
+ } 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) {
@@ -5243,6 +5628,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
tb->size = dc.pc - pc_start;
tb->icount = num_insns;
}
+
#if defined(S390X_DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("IN: %s\n", lookup_symbol(pc_start));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 014/147] target-s390: Split out disas_jcc
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (12 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 013/147] target-s390: Add format based disassassmbly infrastructure Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 015/147] target-s390: Reorg exception handling Richard Henderson
` (133 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 02736e3..2dbb969 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);
@@ -840,357 +852,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] 152+ messages in thread
* [Qemu-devel] [PATCH 015/147] target-s390: Reorg exception handling
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (13 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 014/147] target-s390: Split out disas_jcc Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 016/147] target-s390: Convert ADD HALFWORD Richard Henderson
` (132 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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. Rename ILC to ILEN to make it clear that we
want to pass around a full instruction length, rather than a "code"
that happens to be stored one bit left in a larger field.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 140 +++++++++++++++++---------
linux-user/s390x/syscall.h | 2 +-
target-s390x/cpu.h | 49 +++++----
target-s390x/helper.c | 58 ++++++-----
target-s390x/mem_helper.c | 2 +-
target-s390x/misc_helper.c | 8 +-
target-s390x/translate.c | 242 +++++++++++++++++----------------------------
7 files changed, 241 insertions(+), 260 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 9f3476b..05011af 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2922,71 +2922,115 @@ 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_ilen;
+ 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_SPECIAL_OP:
+ case PGM_OPERAND:
+ do_sigill_opn:
+ 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_DATA:
+ n = (env->fpc >> 8) & 0xff;
+ if (n == 0xff) {
+ /* compare-and-trap */
+ goto do_sigill_opn;
+ } else {
+ /* An IEEE exception, simulated or otherwise. */
+ if (n & 0x80) {
+ n = TARGET_FPE_FLTINV;
+ } else if (n & 0x40) {
+ n = TARGET_FPE_FLTDIV;
+ } else if (n & 0x20) {
+ n = TARGET_FPE_FLTOVF;
+ } else if (n & 0x10) {
+ n = TARGET_FPE_FLTUND;
+ } else if (n & 0x08) {
+ n = TARGET_FPE_FLTRES;
+ } else {
+ /* ??? Quantum exception; BFP, DFP error. */
+ goto do_sigill_opn;
+ }
+ sig = SIGFPE;
+ 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/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index c2ea151..e4603b7 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -16,7 +16,7 @@ struct target_pt_regs {
target_psw_t psw;
abi_ulong gprs[TARGET_NUM_GPRS];
abi_ulong orig_gpr2;
- unsigned short ilc;
+ unsigned short ilen;
unsigned short trap;
};
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 471fb91..2c5a743 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -79,10 +79,10 @@ typedef struct CPUS390XState {
uint64_t psa;
uint32_t int_pgm_code;
- uint32_t int_pgm_ilc;
+ uint32_t int_pgm_ilen;
uint32_t int_svc_code;
- uint32_t int_svc_ilc;
+ uint32_t int_svc_ilen;
uint64_t cregs[16]; /* control registers */
@@ -253,25 +253,31 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
}
-static inline int get_ilc(uint8_t opc)
+/* While the PoO talks about ILC (a number between 1-3) what is actually
+ stored in LowCore is shifted left one bit (an even between 2-6). As
+ this is the actual length of the insn and therefore more useful, that
+ is what we want to pass around and manipulate. To make sure that we
+ have applied this distinction universally, rename the "ILC" to "ILEN". */
+static inline int get_ilen(uint8_t opc)
{
switch (opc >> 6) {
case 0:
- return 1;
+ return 2;
case 1:
case 2:
- return 2;
- case 3:
- return 3;
+ return 4;
+ default:
+ return 6;
}
-
- return 0;
}
-#define ILC_LATER 0x20
-#define ILC_LATER_INC 0x21
-#define ILC_LATER_INC_2 0x22
-
+#ifndef CONFIG_USER_ONLY
+/* In several cases of runtime exceptions, we havn't recorded the true
+ instruction length. Use these codes when raising exceptions in order
+ to re-compute the length by examining the insn in memory. */
+#define ILEN_LATER 0x20
+#define ILEN_LATER_INC 0x21
+#endif
S390CPU *cpu_s390x_init(const char *cpu_model);
void s390x_translate_init(void);
@@ -352,21 +358,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)
@@ -543,9 +538,9 @@ typedef struct LowCore
uint32_t ext_params; /* 0x080 */
uint16_t cpu_addr; /* 0x084 */
uint16_t ext_int_code; /* 0x086 */
- uint16_t svc_ilc; /* 0x088 */
+ uint16_t svc_ilen; /* 0x088 */
uint16_t svc_code; /* 0x08a */
- uint16_t pgm_ilc; /* 0x08c */
+ uint16_t pgm_ilen; /* 0x08c */
uint16_t pgm_code; /* 0x08e */
uint32_t data_exc_code; /* 0x090 */
uint16_t mon_class_num; /* 0x094 */
@@ -933,6 +928,6 @@ uint32_t set_cc_nz_f32(float32 v);
uint32_t set_cc_nz_f64(float64 v);
/* misc_helper.c */
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
#endif
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 27c3123..d813dad 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -99,10 +99,10 @@ 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_ADDRESSING;
+ /* On real machines this value is dropped into LowMem. Since this
+ is userland, simply put this someplace that cpu_loop can find it. */
env->__excp_addr = address;
return 1;
}
@@ -111,11 +111,11 @@ int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
/* Ensure to exit the TB after this call! */
static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
- uint32_t ilc)
+ uint32_t ilen)
{
env->exception_index = EXCP_PGM;
env->int_pgm_code = code;
- env->int_pgm_ilc = ilc;
+ env->int_pgm_ilen = ilen;
}
static int trans_bits(CPUS390XState *env, uint64_t mode)
@@ -143,30 +143,30 @@ static int trans_bits(CPUS390XState *env, uint64_t mode)
static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
uint64_t mode)
{
- int ilc = ILC_LATER_INC_2;
+ int ilen = ILEN_LATER_INC;
int bits = trans_bits(env, mode) | 4;
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
- trigger_pgm_exception(env, PGM_PROTECTION, ilc);
+ trigger_pgm_exception(env, PGM_PROTECTION, ilen);
}
static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
uint32_t type, uint64_t asc, int rw)
{
- int ilc = ILC_LATER;
+ int ilen = ILEN_LATER;
int bits = trans_bits(env, asc);
+ /* Code accesses have an undefined ilc. */
if (rw == 2) {
- /* code has is undefined ilc */
- ilc = 2;
+ ilen = 2;
}
DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
- trigger_pgm_exception(env, type, ilc);
+ trigger_pgm_exception(env, type, ilen);
}
static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
@@ -406,7 +406,7 @@ int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong orig_vaddr,
if (raddr > (ram_size + virtio_size)) {
DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
(uint64_t)aaddr, (uint64_t)ram_size);
- trigger_pgm_exception(env, PGM_ADDRESSING, ILC_LATER);
+ trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER);
return 1;
}
@@ -480,9 +480,9 @@ static void do_svc_interrupt(CPUS390XState *env)
lowcore = cpu_physical_memory_map(env->psa, &len, 1);
lowcore->svc_code = cpu_to_be16(env->int_svc_code);
- lowcore->svc_ilc = cpu_to_be16(env->int_svc_ilc);
+ lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
- lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + (env->int_svc_ilc));
+ lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
mask = be64_to_cpu(lowcore->svc_new_psw.mask);
addr = be64_to_cpu(lowcore->svc_new_psw.addr);
@@ -496,28 +496,26 @@ static void do_program_interrupt(CPUS390XState *env)
uint64_t mask, addr;
LowCore *lowcore;
target_phys_addr_t len = TARGET_PAGE_SIZE;
- int ilc = env->int_pgm_ilc;
+ int ilen = env->int_pgm_ilen;
- switch (ilc) {
- case ILC_LATER:
- ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
- break;
- case ILC_LATER_INC:
- ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
- env->psw.addr += ilc * 2;
+ switch (ilen) {
+ case ILEN_LATER:
+ ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
break;
- case ILC_LATER_INC_2:
- ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)) * 2;
- env->psw.addr += ilc;
+ case ILEN_LATER_INC:
+ ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
+ env->psw.addr += ilen;
break;
+ default:
+ assert(ilen == 2 || ilen == 4 || ilen == 6);
}
- qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilc=%d\n",
- __func__, env->int_pgm_code, ilc);
+ qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n",
+ __func__, env->int_pgm_code, ilen);
lowcore = cpu_physical_memory_map(env->psa, &len, 1);
- lowcore->pgm_ilc = cpu_to_be16(ilc);
+ lowcore->pgm_ilen = cpu_to_be16(ilen);
lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
@@ -527,7 +525,7 @@ static void do_program_interrupt(CPUS390XState *env)
cpu_physical_memory_unmap(lowcore, len, 1, len);
DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__,
- env->int_pgm_code, ilc, env->psw.mask,
+ env->int_pgm_code, ilen, env->psw.mask,
env->psw.addr);
load_psw(env, mask, addr);
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index b21b37c..0a06df8 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -600,7 +600,7 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
env->psw.addr = ret - 4;
env->int_svc_code = (insn | v1) & 0xff;
- env->int_svc_ilc = 4;
+ env->int_svc_ilen = 4;
helper_exception(env, EXCP_SVC);
} else if ((insn & 0xff00) == 0xbf00) {
uint32_t insn2, r1, r3, b2, d2;
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index e9b3cae..bd5fd20 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -42,7 +42,7 @@
#define HELPER_LOG(x...)
#endif
-/* raise an exception */
+/* Raise an exception statically from a TB. */
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
HELPER_LOG("%s: exception %d\n", __func__, excp);
@@ -51,7 +51,7 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp)
}
#ifndef CONFIG_USER_ONLY
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
{
qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
env->psw.addr);
@@ -62,7 +62,7 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
#endif
} else {
env->int_pgm_code = code;
- env->int_pgm_ilc = ilc;
+ env->int_pgm_ilen = ilen;
env->exception_index = EXCP_PGM;
cpu_loop_exit(env);
}
@@ -149,7 +149,7 @@ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
}
if (r) {
- program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
+ program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
}
return r;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2dbb969..cf455b5 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 */
@@ -338,105 +337,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(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int ilc)
-{
-#ifdef DEBUG_ILLEGAL_INSTRUCTIONS
- uint64_t inst = 0;
-
- switch (ilc & 3) {
- case 1:
- inst = ld_code2(env, s->pc);
- break;
- case 2:
- inst = ld_code4(env, s->pc);
- break;
- case 3:
- inst = ld_code6(env, 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(CPUS390XState *env, DisasContext *s, int ilc,
- int code)
+static void gen_program_exception(DisasContext *s, int code)
{
TCGv_i32 tmp;
- debug_print_inst(env, 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);
- tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
+ tmp = tcg_const_i32(s->next_pc - s->pc);
+ tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
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(CPUS390XState *env, DisasContext *s, int ilc)
+static inline void gen_illegal_opcode(DisasContext *s)
{
- gen_program_exception(env, s, ilc, PGM_SPECIFICATION);
+ gen_program_exception(s, PGM_SPECIFICATION);
}
-static void gen_privileged_exception(CPUS390XState *env, DisasContext *s,
- int ilc)
-{
- gen_program_exception(env, s, ilc, PGM_PRIVILEGED);
-}
-
-static void check_privileged(CPUS390XState *env, DisasContext *s, int ilc)
+static inline void check_privileged(DisasContext *s)
{
if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
- gen_privileged_exception(env, 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;
@@ -1769,7 +1715,7 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
break;
default:
LOG_DISAS("illegal e3 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
tcg_temp_free_i64(addr);
@@ -1794,7 +1740,7 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
break;
default:
LOG_DISAS("illegal e5 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
@@ -1809,7 +1755,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1947,7 +1892,7 @@ do_mh:
#ifndef CONFIG_USER_ONLY
case 0x2f: /* LCTLG R1,R3,D2(B2) [RSE] */
/* Load Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r3);
@@ -1959,7 +1904,7 @@ do_mh:
break;
case 0x25: /* STCTG R1,R3,D2(B2) [RSE] */
/* Store Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
tmp = get_address(s, 0, b2, d2);
tmp32_1 = tcg_const_i32(r1);
tmp32_2 = tcg_const_i32(r3);
@@ -2036,7 +1981,7 @@ do_mh:
break;
default:
LOG_DISAS("illegal eb operation 0x%x\n", op);
- gen_illegal_opcode(env, s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
@@ -2156,7 +2101,7 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
break;
default:
LOG_DISAS("illegal ed operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
return;
}
tcg_temp_free_i32(tmp_r1);
@@ -2313,7 +2258,7 @@ static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1,
break;
default:
LOG_DISAS("illegal a5 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
return;
}
}
@@ -2451,7 +2396,7 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
break;
default:
LOG_DISAS("illegal a7 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
return;
}
}
@@ -2462,7 +2407,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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
@@ -2556,7 +2500,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
#ifndef CONFIG_USER_ONLY
case 0x02: /* STIDP D2(B2) [S] */
/* Store CPU ID */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2565,7 +2509,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x04: /* SCK D2(B2) [S] */
/* Set Clock */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2584,7 +2528,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x06: /* SCKC D2(B2) [S] */
/* Set Clock Comparator */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2593,7 +2537,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x07: /* STCKC D2(B2) [S] */
/* Store Clock Comparator */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2602,7 +2546,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x08: /* SPT D2(B2) [S] */
/* Set CPU Timer */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2611,7 +2555,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x09: /* STPT D2(B2) [S] */
/* Store CPU Timer */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2620,7 +2564,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x0a: /* SPKA D2(B2) [S] */
/* Set PSW Key from Address */
- check_privileged(env, 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();
@@ -2632,12 +2576,12 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x0d: /* PTLB [S] */
/* Purge TLB */
- check_privileged(env, s, ilc);
+ check_privileged(s);
gen_helper_ptlb(cpu_env);
break;
case 0x10: /* SPX D2(B2) [S] */
/* Set Prefix Register */
- check_privileged(env, s, ilc);
+ check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
potential_page_fault(s);
@@ -2646,7 +2590,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x11: /* STPX D2(B2) [S] */
/* Store Prefix */
- check_privileged(env, 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();
@@ -2657,7 +2601,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x12: /* STAP D2(B2) [S] */
/* Store CPU Address */
- check_privileged(env, 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();
@@ -2671,7 +2615,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x21: /* IPTE R1,R2 [RRE] */
/* Invalidate PTE */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp = load_reg(r1);
@@ -2682,7 +2626,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x29: /* ISKE R1,R2 [RRE] */
/* Insert Storage Key Extended */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp = load_reg(r2);
@@ -2694,7 +2638,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x2a: /* RRBE R1,R2 [RRE] */
/* Set Storage Key Extended */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
@@ -2706,7 +2650,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x2b: /* SSKE R1,R2 [RRE] */
/* Set Storage Key Extended */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
@@ -2717,12 +2661,12 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x34: /* STCH ? */
/* Store Subchannel */
- check_privileged(env, s, ilc);
+ check_privileged(s);
gen_op_movi_cc(s, 3);
break;
case 0x46: /* STURA R1,R2 [RRE] */
/* Store Using Real Address */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = load_reg32(r1);
@@ -2734,7 +2678,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x50: /* CSP R1,R2 [RRE] */
/* Compare And Swap And Purge */
- check_privileged(env, s, ilc);
+ check_privileged(s);
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
tmp32_1 = tcg_const_i32(r1);
@@ -2746,7 +2690,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x5f: /* CHSC ? */
/* Channel Subsystem Call */
- check_privileged(env, s, ilc);
+ check_privileged(s);
gen_op_movi_cc(s, 3);
break;
case 0x78: /* STCKE D2(B2) [S] */
@@ -2760,19 +2704,19 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x79: /* SACF D2(B2) [S] */
/* Set Address Space Control Fast */
- check_privileged(env, 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_JUMP;
break;
case 0x7d: /* STSI D2,(B2) [S] */
- check_privileged(env, 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);
@@ -2798,7 +2742,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0xb1: /* STFL D2(B2) [S] */
/* Store Facility List (CPU features) at 200 */
- check_privileged(env, 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));
@@ -2807,7 +2751,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0xb2: /* LPSWE D2(B2) [S] */
/* Load PSW Extended */
- check_privileged(env, 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();
@@ -2824,7 +2768,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
break;
case 0x20: /* SERVC R1,R2 [RRE] */
/* SCLP Service call (PV hypercall) */
- check_privileged(env, s, ilc);
+ check_privileged(s);
potential_page_fault(s);
tmp32_1 = load_reg32(r2);
tmp = load_reg(r1);
@@ -2836,7 +2780,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
#endif
default:
LOG_DISAS("illegal b2 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3112,7 +3056,7 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
break;
default:
LOG_DISAS("illegal b3 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
break;
}
@@ -3419,7 +3363,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
break;
default:
LOG_DISAS("illegal b9 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 2);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3525,7 +3469,7 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
break;
default:
LOG_DISAS("illegal c0 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3559,7 +3503,7 @@ static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
break;
default:
LOG_DISAS("illegal c2 operation 0x%x\n", op);
- gen_illegal_opcode(env, s, 3);
+ gen_illegal_opcode(s);
break;
}
}
@@ -3589,14 +3533,11 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
- ilc = get_ilc(opc);
-
switch (opc) {
#ifndef CONFIG_USER_ONLY
case 0x01: /* SAM */
@@ -3649,15 +3590,13 @@ static void disas_s390_insn(CPUS390XState *env, 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);
+ tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
+ 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(env, s->pc);
@@ -4148,7 +4087,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0x80: /* SSM D2(B2) [S] */
/* Set System Mask */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4164,7 +4103,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
break;
case 0x82: /* LPSW D2(B2) [S] */
/* Load PSW */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4184,7 +4123,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
break;
case 0x83: /* DIAG R1,R3,D2 [RS] */
/* Diagnose call (KVM hypercall) */
- check_privileged(env, s, ilc);
+ check_privileged(s);
potential_page_fault(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -4402,7 +4341,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xac: /* STNSM D1(B1),I2 [SI] */
case 0xad: /* STOSM D1(B1),I2 [SI] */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
tmp2 = tcg_temp_new_i64();
@@ -4418,7 +4357,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp2);
break;
case 0xae: /* SIGP R1,R3,D2(B2) [RS] */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4432,7 +4371,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
break;
case 0xb1: /* LRA R1,D2(X2, B2) [RX] */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
tmp32_1 = tcg_const_i32(r1);
@@ -4476,7 +4415,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xb6: /* STCTL R1,R3,D2(B2) [RS] */
/* Store Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4490,7 +4429,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
break;
case 0xb7: /* LCTL R1,R3,D2(B2) [RS] */
/* Load Control */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
tmp = get_address(s, 0, b2, d2);
@@ -4674,7 +4613,7 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s, ilc);
+ check_privileged(s);
potential_page_fault(s);
insn = ld_code6(env, s->pc);
r1 = (insn >> 36) & 0xf;
@@ -4712,7 +4651,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
#ifndef CONFIG_USER_ONLY
case 0xe5:
/* Test Protection */
- check_privileged(env, s, ilc);
+ check_privileged(s);
insn = ld_code6(env, s->pc);
debug_insn(insn);
disas_e5(env, s, insn);
@@ -4742,7 +4681,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
- gen_illegal_opcode(env, s, ilc);
+ gen_illegal_opcode(s);
break;
}
}
@@ -5273,19 +5212,22 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
DisasFields *f)
{
uint64_t insn, pc = s->pc;
- int op, op2;
+ int op, op2, ilen;
const DisasInsn *info;
insn = ld_code2(env, pc);
op = (insn >> 8) & 0xff;
- switch (get_ilc(op)) {
- case 1:
+ ilen = get_ilen(op);
+ s->next_pc = s->pc + ilen;
+
+ switch (ilen) {
+ case 2:
insn = insn << 48;
break;
- case 2:
+ case 4:
insn = ld_code4(env, pc) << 32;
break;
- case 3:
+ case 6:
insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
break;
default:
@@ -5361,9 +5303,6 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
insn = extract_insn(env, s, &f);
- /* Instruction length is encoded in the opcode */
- 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(env, s);
@@ -5452,6 +5391,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;
@@ -5463,7 +5403,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;
@@ -5479,14 +5419,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) {
@@ -5508,7 +5440,19 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
tcg_gen_debug_insn_start(dc.pc);
}
- status = translate_one(env, &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(env, &dc);
+ }
/* If we reach a page boundary, are single stepping,
or exhaust instruction count, stop generation. */
@@ -5541,8 +5485,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] 152+ messages in thread
* [Qemu-devel] [PATCH 016/147] target-s390: Convert ADD HALFWORD
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (14 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 015/147] target-s390: Reorg exception handling Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 017/147] target-s390: Implement SUBTRACT HALFWORD Richard Henderson
` (131 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 cf455b5..34c1ab8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -559,11 +559,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)
{
@@ -2267,7 +2262,7 @@ static void disas_a7(CPUS390XState *env, 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);
@@ -2342,36 +2337,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -5078,6 +5043,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] 152+ messages in thread
* [Qemu-devel] [PATCH 017/147] target-s390: Implement SUBTRACT HALFWORD
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (15 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 016/147] target-s390: Convert ADD HALFWORD Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:39 ` [Qemu-devel] [PATCH 018/147] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE Richard Henderson
` (130 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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] 152+ messages in thread
* [Qemu-devel] [PATCH 018/147] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (16 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 017/147] target-s390: Implement SUBTRACT HALFWORD Richard Henderson
@ 2012-09-27 22:39 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 019/147] target-s390: Convert MULTIPLY HALFWORD, SINGLE Richard Henderson
` (129 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:39 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 34c1ab8..38d8e6d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5005,6 +5005,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] 152+ messages in thread
* [Qemu-devel] [PATCH 019/147] target-s390: Convert MULTIPLY HALFWORD, SINGLE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (17 preceding siblings ...)
2012-09-27 22:39 ` [Qemu-devel] [PATCH 018/147] target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 020/147] target-s390: Convert 32-bit MULTIPLY, MULTIPLY LOGICAL Richard Henderson
` (128 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 18 +++++++
target-s390x/translate.c | 121 +++++++--------------------------------------
2 files changed, 36 insertions(+), 103 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index acde181..055113a 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)
+/* MULTIPLY HALFWORD */
+ C(0x4c00, MH, RX_a, Z, r1_o, m2_16s, new, r1_32, mul, 0)
+ C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
+/* MULTIPLY HALFWORD IMMEDIATE */
+ C(0xa70c, MHI, RI_a, Z, r1_o, i2, new, r1_32, mul, 0)
+ C(0xa70d, MGHI, RI_a, Z, r1_o, i2, r1, 0, mul, 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_o, i2, new, r1_32, mul, 0)
+ C(0xc200, MSGFI, RIL_a, GIE, r1_o, 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/translate.c b/target-s390x/translate.c
index 38d8e6d..d409b93 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -575,22 +575,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);
@@ -1371,17 +1361,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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();
@@ -2337,18 +2316,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2408,14 +2375,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -3083,18 +3042,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3820,41 +3767,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4022,21 +3934,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4886,6 +4783,12 @@ 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_sub(DisasContext *s, DisasOps *o)
{
tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -4983,6 +4886,12 @@ 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_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_reg(get_field(f, r2));
@@ -5027,6 +4936,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] 152+ messages in thread
* [Qemu-devel] [PATCH 020/147] target-s390: Convert 32-bit MULTIPLY, MULTIPLY LOGICAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (18 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 019/147] target-s390: Convert MULTIPLY HALFWORD, SINGLE Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 021/147] target-s390: Convert 64-bit " Richard Henderson
` (127 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 | 82 ++++++++++++++--------------------------------
2 files changed, 32 insertions(+), 57 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 055113a..ca12e47 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -41,12 +41,19 @@
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_o, m2_16s, new, r1_32, mul, 0)
C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
/* MULTIPLY HALFWORD IMMEDIATE */
C(0xa70c, MHI, RI_a, Z, r1_o, 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)
/* 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)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d409b93..66e6b60 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1624,18 +1624,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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) */
@@ -3219,19 +3207,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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) */
@@ -3605,21 +3580,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3855,23 +3815,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4868,6 +4811,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_shri_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));
@@ -4892,6 +4844,22 @@ static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in1 = true;
}
+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));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 021/147] target-s390: Convert 64-bit MULTIPLY LOGICAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (19 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 020/147] target-s390: Convert 32-bit MULTIPLY, MULTIPLY LOGICAL Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 022/147] target-s390: Convert AND, OR, XOR Richard Henderson
` (126 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Use a new "retxl" member of CPUS290XState to return the "eXtra Low" part
of a 128-bit value. That said, this will get used when two independent
values need returning (e.g. quotient+remainder) as well.
At the same time, shuffle the elements of CPUS390XState to get this new
space from existing padding in the structure.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cpu.h | 15 +++++++++------
target-s390x/helper.h | 2 +-
target-s390x/insn-data.def | 2 ++
target-s390x/int_helper.c | 15 ++++-----------
target-s390x/translate.c | 36 ++++++++++++++++++++++++++++--------
5 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 2c5a743..453be35 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 e72e16e..8527fbb 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -9,7 +9,7 @@ DEF_HELPER_4(clc, i32, env, i32, i64, i64)
DEF_HELPER_3(mvcl, i32, env, 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_CONST, i64, env, i64, i64)
DEF_HELPER_3(dlg, void, env, i32, i64)
DEF_HELPER_4(srst, i32, env, i32, i32, i32)
DEF_HELPER_4(clst, i32, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ca12e47..94cd220 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -54,6 +54,8 @@
/* 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)
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 66e6b60..77305b5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -293,6 +293,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 */
@@ -1563,14 +1568,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -4732,6 +4729,13 @@ static ExitStatus op_mul(DisasContext *s, DisasOps *o)
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);
@@ -4800,6 +4804,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
@@ -4844,6 +4857,13 @@ static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
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. */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 022/147] target-s390: Convert AND, OR, XOR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (20 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 021/147] target-s390: Convert 64-bit " Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 023/147] target-s390: Convert COMPARE, COMPARE LOGICAL Richard Henderson
` (125 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 94cd220..7563cd8 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_o, i2, new, r1_32, mul, 0)
C(0xc200, MSGFI, RIL_a, GIE, r1_o, 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 77305b5..8da7560 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1487,19 +1487,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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));
@@ -1547,27 +1534,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -3115,29 +3081,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3392,23 +3335,6 @@ static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
}
}
-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(CPUS390XState *env, DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -3543,19 +3469,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3768,24 +3681,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4723,6 +4618,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);
@@ -4736,12 +4637,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
@@ -4767,6 +4680,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] 152+ messages in thread
* [Qemu-devel] [PATCH 023/147] target-s390: Convert COMPARE, COMPARE LOGICAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (21 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 022/147] target-s390: Convert AND, OR, XOR Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 024/147] target-s390: Convert LOAD, LOAD LOGICAL Richard Henderson
` (124 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 | 267 ++++++++++++++-------------------------------
2 files changed, 129 insertions(+), 186 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7563cd8..09eb30e 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 8da7560..b472871 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1434,39 +1434,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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;
@@ -1881,17 +1848,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);
@@ -2267,16 +2223,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3047,28 +2993,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3301,40 +3225,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
}
}
-static void disas_c2(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -3476,20 +3366,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3623,20 +3499,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x49: /* CH R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3667,20 +3529,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x55: /* CL R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3693,20 +3541,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3962,15 +3796,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x95: /* CLI D1(B1),I2 [SI] */
- insn = ld_code4(env, 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(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -4239,21 +4064,11 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
}
break;
case 0xc0:
- case 0xc2:
insn = ld_code6(env, s->pc);
r1 = (insn >> 36) & 0xf;
op = (insn >> 32) & 0xf;
i2 = (int)insn;
- switch (opc) {
- case 0xc0:
- disas_c0(env, s, op, r1, i2);
- break;
- case 0xc2:
- disas_c2(env, s, op, r1, i2);
- break;
- default:
- tcg_abort();
- }
+ disas_c0(env, s, op, r1, i2);
break;
case 0xd2: /* MVC D1(L,B1),D2(B2) [SS] */
case 0xd4: /* NC D1(L,B1),D2(B2) [SS] */
@@ -4680,6 +4495,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);
@@ -4819,6 +4654,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);
@@ -4877,6 +4733,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);
@@ -4901,11 +4762,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] 152+ messages in thread
* [Qemu-devel] [PATCH 024/147] target-s390: Convert LOAD, LOAD LOGICAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (22 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 023/147] target-s390: Convert COMPARE, COMPARE LOGICAL Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 025/147] target-s390: Convert LOAD ADDRESS Richard Henderson
` (123 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 09eb30e..0a7cba3 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 b472871..b6744b2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1350,7 +1350,7 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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]);
@@ -1391,16 +1391,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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));
@@ -1454,12 +1444,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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;
@@ -2930,9 +2914,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
}
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);
@@ -2959,22 +2940,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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();
@@ -3134,11 +3099,6 @@ static void disas_c0(CPUS390XState *env, 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] */
if (r1 == 15) { /* m1 == r1 */
gen_goto_tb(s, 0, target);
@@ -3359,13 +3319,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
set_cc_comp32(s, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x18: /* LR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3529,18 +3482,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x58: /* l r1, d2(x2, b2) */
- insn = ld_code4(env, 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(env, s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4439,6 +4380,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);
@@ -4578,6 +4546,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);
@@ -4592,6 +4565,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] 152+ messages in thread
* [Qemu-devel] [PATCH 025/147] target-s390: Convert LOAD ADDRESS
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (23 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 024/147] target-s390: Convert LOAD, LOAD LOGICAL Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 026/147] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD Richard Henderson
` (122 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 0a7cba3..f0dcea6 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 b6744b2..a06d5fd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1444,9 +1444,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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();
@@ -3094,11 +3091,6 @@ static void disas_c0(CPUS390XState *env, 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] */
if (r1 == 15) { /* m1 == r1 */
gen_goto_tb(s, 0, target);
@@ -3376,12 +3368,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x41: /* la */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 026/147] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (24 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 025/147] target-s390: Convert LOAD ADDRESS Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 027/147] target-s390: Convert LOAD AND TEST Richard Henderson
` (121 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 f0dcea6..796185f 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 a06d5fd..12af61f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1391,12 +1391,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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));
@@ -1458,30 +1452,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -1517,24 +1487,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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) */
@@ -2194,16 +2146,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2911,12 +2853,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
}
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);
@@ -2955,18 +2891,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2975,18 +2899,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3021,18 +2933,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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) */
@@ -3429,15 +3329,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4366,6 +4257,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));
@@ -4676,6 +4591,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] 152+ messages in thread
* [Qemu-devel] [PATCH 027/147] target-s390: Convert LOAD AND TEST
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (25 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 026/147] target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 028/147] target-s390: Convert LOAD LOGICAL IMMEDIATE Richard Henderson
` (120 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 796185f..7a8dcbd 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 12af61f..4ea0e95 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1349,23 +1349,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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();
@@ -3192,16 +3175,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
store_reg32(r1, tmp32_1);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x12: /* LTR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -4395,6 +4368,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] 152+ messages in thread
* [Qemu-devel] [PATCH 028/147] target-s390: Convert LOAD LOGICAL IMMEDIATE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (26 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 027/147] target-s390: Convert LOAD AND TEST Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 22:40 ` [Qemu-devel] [PATCH 029/147] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE Richard Henderson
` (119 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 7a8dcbd..89bc635 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 4ea0e95..bc55a96 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2033,26 +2033,6 @@ static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3043,16 +3023,6 @@ static void disas_c0(CPUS390XState *env, 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);
@@ -4694,6 +4664,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] 152+ messages in thread
* [Qemu-devel] [PATCH 029/147] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (27 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 028/147] target-s390: Convert LOAD LOGICAL IMMEDIATE Richard Henderson
@ 2012-09-27 22:40 ` Richard Henderson
2012-09-27 23:06 ` [Qemu-devel] [PATCH 030/147] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE Richard Henderson
` (118 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 22:40 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 89bc635..9507262 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 bc55a96..f099fd7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -570,42 +570,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);
@@ -2779,43 +2749,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3127,33 +3060,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x10: /* LPR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, 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(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -4188,6 +4094,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);
@@ -4264,6 +4176,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);
@@ -4287,6 +4211,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);
@@ -4327,6 +4261,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] 152+ messages in thread
* [Qemu-devel] [PATCH 030/147] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (28 preceding siblings ...)
2012-09-27 22:40 ` [Qemu-devel] [PATCH 029/147] target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE Richard Henderson
@ 2012-09-27 23:06 ` Richard Henderson
2012-09-27 23:07 ` [Qemu-devel] [PATCH 031/147] target-s390: Convert STORE Richard Henderson
` (117 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:06 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 | 237 +++++++++++----------------------------------
2 files changed, 82 insertions(+), 180 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9507262..705b655 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 f099fd7..9cf4c57 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1875,141 +1875,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
tcg_temp_free_i64(addr);
}
-static void disas_a5(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int op, int r1,
int i2)
{
@@ -2918,44 +2783,6 @@ static void disas_c0(CPUS390XState *env, 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);
@@ -3487,13 +3314,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xa5:
- insn = ld_code4(env, s->pc);
- r1 = (insn >> 20) & 0xf;
- op = (insn >> 16) & 0xf;
- i2 = insn & 0xffff;
- disas_a5(env, s, op, r1, i2);
- break;
case 0xa7:
insn = ld_code4(env, s->pc);
r1 = (insn >> 20) & 0xf;
@@ -4112,6 +3932,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));
@@ -4194,6 +4039,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);
@@ -4206,6 +4067,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] 152+ messages in thread
* [Qemu-devel] [PATCH 031/147] target-s390: Convert STORE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (29 preceding siblings ...)
2012-09-27 23:06 ` [Qemu-devel] [PATCH 030/147] target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE Richard Henderson
@ 2012-09-27 23:07 ` Richard Henderson
2012-09-27 23:08 ` [Qemu-devel] [PATCH 032/147] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW Richard Henderson
` (116 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:07 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 705b655..f441a66 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 9cf4c57..bde12fb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1371,9 +1371,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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();
@@ -1383,22 +1380,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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));
@@ -2936,22 +2917,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3027,14 +2992,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i32(tmp32_1);
break;
- case 0x50: /* st r1, d2(x2, b2) */
- insn = ld_code4(env, 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(env, s->pc);
tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4055,6 +4012,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] 152+ messages in thread
* [Qemu-devel] [PATCH 032/147] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (30 preceding siblings ...)
2012-09-27 23:07 ` [Qemu-devel] [PATCH 031/147] target-s390: Convert STORE Richard Henderson
@ 2012-09-27 23:08 ` Richard Henderson
2012-09-27 23:09 ` [Qemu-devel] [PATCH 033/147] target-s390: Convert BRANCH AND SAVE Richard Henderson
` (115 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:08 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 | 3 -
target-s390x/insn-data.def | 10 +++
target-s390x/int_helper.c | 43 ----------
target-s390x/translate.c | 191 +++++++++++++++------------------------------
6 files changed, 157 insertions(+), 206 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 453be35..630198f 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -449,15 +449,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) */
@@ -494,14 +498,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 8527fbb..8216605 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -26,13 +26,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_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 f441a66..373aa40 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 bde12fb..f940613 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -474,15 +474,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);
@@ -564,18 +555,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);
@@ -661,12 +640,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;
@@ -1313,7 +1296,7 @@ static void disas_e3(CPUS390XState *env, 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);
@@ -1394,33 +1377,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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) */
@@ -1441,37 +1397,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -2591,7 +2516,7 @@ static void disas_b9(CPUS390XState *env, 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) {
@@ -2648,33 +2573,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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) */
@@ -2694,28 +2592,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3883,6 +3759,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);
@@ -4042,6 +3935,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);
@@ -4099,6 +4010,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);
@@ -4180,6 +4101,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] 152+ messages in thread
* [Qemu-devel] [PATCH 033/147] target-s390: Convert BRANCH AND SAVE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (31 preceding siblings ...)
2012-09-27 23:08 ` [Qemu-devel] [PATCH 032/147] target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW Richard Henderson
@ 2012-09-27 23:09 ` Richard Henderson
2012-09-27 23:10 ` [Qemu-devel] [PATCH 034/147] target-s390: Convert BRANCH ON CONDITION Richard Henderson
` (114 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:09 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 373aa40..ba78f47 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 f940613..f37773d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -713,20 +713,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);
@@ -1817,13 +1820,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2601,7 +2597,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
static void disas_c0(CPUS390XState *env, 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;
@@ -2633,13 +2628,6 @@ static void disas_c0(CPUS390XState *env, 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);
@@ -2720,19 +2708,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xd: /* BASR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -2846,16 +2821,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3744,6 +3709,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. */
@@ -3799,6 +3784,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;
@@ -4287,6 +4289,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] 152+ messages in thread
* [Qemu-devel] [PATCH 034/147] target-s390: Convert BRANCH ON CONDITION
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (32 preceding siblings ...)
2012-09-27 23:09 ` [Qemu-devel] [PATCH 033/147] target-s390: Convert BRANCH AND SAVE Richard Henderson
@ 2012-09-27 23:10 ` Richard Henderson
2012-09-27 23:11 ` [Qemu-devel] [PATCH 035/147] target-s390: Convert BRANCH ON COUNT Richard Henderson
` (113 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:10 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 | 231 ++++++++++++++++++++++++++-------------------
2 files changed, 142 insertions(+), 95 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ba78f47..0bd05ab 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 f37773d..7705b1d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1021,35 +1021,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 */
- gen_update_cc_op(s);
- 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);
- gen_update_cc_op(s);
- 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;
@@ -2595,46 +2566,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
}
}
-static void disas_c0(CPUS390XState *env, 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] */
- if (r1 == 15) { /* m1 == r1 */
- gen_goto_tb(s, 0, target);
- s->is_jmp = DISAS_TB_JUMP;
- break;
- }
- /* 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(CPUS390XState *env, DisasContext *s)
{
TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -2681,18 +2612,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
}
break;
- case 0x7: /* BCR M1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
debug_insn(insn);
@@ -2814,13 +2733,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3348,13 +3260,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
gen_op_movi_cc(s, 0);
}
break;
- case 0xc0:
- insn = ld_code6(env, s->pc);
- r1 = (insn >> 36) & 0xf;
- op = (insn >> 32) & 0xf;
- i2 = (int)insn;
- disas_c0(env, s, op, r1, i2);
- 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] */
@@ -3728,6 +3633,131 @@ 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;
+ uint64_t dest = s->pc + 2 * imm;
+ int lab;
+
+ /* Take care of the special cases first. */
+ if (c->cond == TCG_COND_NEVER) {
+ ret = NO_EXIT;
+ goto egress;
+ }
+ if (is_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;
+ }
+ } else {
+ if (TCGV_IS_UNUSED_I64(cdest)) {
+ /* E.g. bcr %r0 -> no branch. */
+ ret = NO_EXIT;
+ goto egress;
+ }
+ if (c->cond == TCG_COND_ALWAYS) {
+ tcg_gen_mov_i64(psw_addr, cdest);
+ ret = EXIT_PC_UPDATED;
+ goto egress;
+ }
+ }
+
+ if (use_goto_tb(s, s->next_pc)) {
+ if (is_imm && use_goto_tb(s, dest)) {
+ /* Both exits can use goto_tb. */
+ 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;
+ } else {
+ /* Fallthru can use goto_tb, but taken branch cannot. */
+ /* Store taken branch destination before the brcond. This
+ avoids having to allocate a new local temp to hold it.
+ We'll overwrite this in the not taken case anyway. */
+ if (!is_imm) {
+ tcg_gen_mov_i64(psw_addr, cdest);
+ }
+
+ 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. */
+ gen_update_cc_op(s);
+ tcg_gen_goto_tb(0);
+ tcg_gen_movi_i64(psw_addr, s->next_pc);
+ tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
+
+ gen_set_label(lab);
+ if (is_imm) {
+ tcg_gen_movi_i64(psw_addr, dest);
+ }
+ ret = EXIT_PC_UPDATED;
+ }
+ } else {
+ /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
+ Most commonly we're single-stepping or some other condition that
+ disables all use of goto_tb. Just update the PC and exit. */
+
+ TCGv_i64 next = tcg_const_i64(s->next_pc);
+ if (is_imm) {
+ cdest = tcg_const_i64(dest);
+ }
+
+ if (c->is_64) {
+ tcg_gen_movcond_i64(c->cond, psw_addr, c->u.s64.a, c->u.s64.b,
+ cdest, next);
+ } else {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 z = tcg_const_i64(0);
+ tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b);
+ tcg_gen_extu_i32_i64(t1, t0);
+ tcg_temp_free_i32(t0);
+ tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(z);
+ }
+
+ if (is_imm) {
+ tcg_temp_free_i64(cdest);
+ }
+ tcg_temp_free_i64(next);
+
+ 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. */
@@ -3801,6 +3831,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] 152+ messages in thread
* [Qemu-devel] [PATCH 035/147] target-s390: Convert BRANCH ON COUNT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (33 preceding siblings ...)
2012-09-27 23:10 ` [Qemu-devel] [PATCH 034/147] target-s390: Convert BRANCH ON CONDITION Richard Henderson
@ 2012-09-27 23:11 ` Richard Henderson
2012-09-27 23:12 ` [Qemu-devel] [PATCH 036/147] target-s390: Convert DIVIDE Richard Henderson
` (112 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:11 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 0bd05ab..8ea6630 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 7705b1d..b2aaaf7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1004,43 +1004,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;
@@ -1759,8 +1722,6 @@ static void disas_a7(CPUS390XState *env, 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) {
@@ -1788,35 +1749,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2574,7 +2506,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -2586,32 +2517,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
/* set addressing mode, but we only do 64bit anyways */
break;
#endif
- case 0x6: /* BCTR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
debug_insn(insn);
@@ -2709,30 +2614,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp2);
tcg_temp_free_i64(tmp3);
break;
- case 0x46: /* BCT R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3842,6 +3723,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] 152+ messages in thread
* [Qemu-devel] [PATCH 036/147] target-s390: Convert DIVIDE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (34 preceding siblings ...)
2012-09-27 23:11 ` [Qemu-devel] [PATCH 035/147] target-s390: Convert BRANCH ON COUNT Richard Henderson
@ 2012-09-27 23:12 ` Richard Henderson
2012-09-27 23:15 ` [Qemu-devel] [PATCH 037/147] target-s390: Send signals for divide Richard Henderson
` (111 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:12 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 8216605..2b1abe4 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -10,7 +10,10 @@ DEF_HELPER_3(mvcl, i32, env, 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_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_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)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8ea6630..921c216 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_D32, r2_32s, new_P, r1_P32, divs32, 0)
+ C(0x5d00, D, RX_a, Z, r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
+/* DIVIDE LOGICAL */
+ C(0xb997, DLR, RRE, Z, r1_D32, r2_32u, new_P, r1_P32, divu32, 0)
+ C(0xe397, DL, RXY_a, Z, r1_D32, 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 b2aaaf7..31c08ac 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1232,31 +1232,13 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
static void disas_e3(CPUS390XState *env, 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));
@@ -1306,34 +1288,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -2414,31 +2368,11 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
static void disas_b9(CPUS390XState *env, 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();
@@ -2465,32 +2399,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2543,41 +2451,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x1d: /* DR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -2626,40 +2499,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3766,6 +3605,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;
@@ -4089,6 +3956,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)];
@@ -4120,6 +3993,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. */
@@ -4183,6 +4064,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_D32(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_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
+}
+
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] 152+ messages in thread
* [Qemu-devel] [PATCH 037/147] target-s390: Send signals for divide
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (35 preceding siblings ...)
2012-09-27 23:12 ` [Qemu-devel] [PATCH 036/147] target-s390: Convert DIVIDE Richard Henderson
@ 2012-09-27 23:15 ` Richard Henderson
2012-09-27 23:16 ` [Qemu-devel] [PATCH 038/147] target-s390: Convert TEST UNDER MASK Richard Henderson
` (110 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:15 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 | 23 +++++++++++++++++++++
3 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 630198f..5b6df0e 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -940,5 +940,7 @@ uint32_t set_cc_nz_f64(float64 v);
/* misc_helper.c */
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
+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 bd5fd20..aec222c 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -42,6 +42,29 @@
#define HELPER_LOG(x...)
#endif
+/* Raise an exception dynamically from a helper function. */
+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_ilen = t = get_ilen(t);
+ env->psw.addr += 2 * t;
+
+ cpu_loop_exit(env);
+}
+
/* Raise an exception statically from a TB. */
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 038/147] target-s390: Convert TEST UNDER MASK
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (36 preceding siblings ...)
2012-09-27 23:15 ` [Qemu-devel] [PATCH 037/147] target-s390: Send signals for divide Richard Henderson
@ 2012-09-27 23:16 ` Richard Henderson
2012-09-27 23:17 ` [Qemu-devel] [PATCH 039/147] target-s390: Convert SET ADDRESSING MODE Richard Henderson
` (109 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:16 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 | 74 +++++++---------------------------------------
3 files changed, 27 insertions(+), 80 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 921c216..f70ede9 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 31c08ac..ec18aeb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1514,16 +1514,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);
@@ -1672,44 +1662,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
tcg_temp_free_i64(addr);
}
-static void disas_a7(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int op,
uint32_t insn)
{
@@ -2678,15 +2630,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp3);
tcg_temp_free_i64(tmp4);
break;
- case 0x91: /* TM D1(B1),I2 [SI] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2744,13 +2687,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0xa7:
- insn = ld_code4(env, s->pc);
- r1 = (insn >> 20) & 0xf;
- op = (insn >> 16) & 0xf;
- i2 = (short)insn;
- disas_a7(env, s, op, r1, i2);
- break;
case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
insn = ld_code4(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3945,6 +3881,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] 152+ messages in thread
* [Qemu-devel] [PATCH 039/147] target-s390: Convert SET ADDRESSING MODE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (37 preceding siblings ...)
2012-09-27 23:16 ` [Qemu-devel] [PATCH 038/147] target-s390: Convert TEST UNDER MASK Richard Henderson
@ 2012-09-27 23:17 ` Richard Henderson
2012-09-27 23:31 ` [Qemu-devel] [PATCH 040/147] target-s390: Convert SUPERVISOR CALL Richard Henderson
` (108 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:17 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 f70ede9..69af25d 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 ec18aeb..5b64959 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2371,12 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
-#ifndef CONFIG_USER_ONLY
- case 0x01: /* SAM */
- insn = ld_code2(env, s->pc);
- /* set addressing mode, but we only do 64bit anyways */
- break;
-#endif
case 0xa: /* SVC I [RR] */
insn = ld_code2(env, s->pc);
debug_insn(insn);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 040/147] target-s390: Convert SUPERVISOR CALL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (38 preceding siblings ...)
2012-09-27 23:17 ` [Qemu-devel] [PATCH 039/147] target-s390: Convert SET ADDRESSING MODE Richard Henderson
@ 2012-09-27 23:31 ` Richard Henderson
2012-09-27 23:32 ` [Qemu-devel] [PATCH 041/147] target-s390: Convert MOVE LONG Richard Henderson
` (107 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:31 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 69af25d..7a0c999 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 5b64959..d0adf5a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2371,21 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0xa: /* SVC I [RR] */
- insn = ld_code2(env, 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_ilen));
- 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3717,6 +3702,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_ilen));
+ 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] 152+ messages in thread
* [Qemu-devel] [PATCH 041/147] target-s390: Convert MOVE LONG
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (39 preceding siblings ...)
2012-09-27 23:31 ` [Qemu-devel] [PATCH 040/147] target-s390: Convert SUPERVISOR CALL Richard Henderson
@ 2012-09-27 23:32 ` Richard Henderson
2012-09-27 23:33 ` [Qemu-devel] [PATCH 042/147] target-s390: Convert FP LOAD Richard Henderson
` (106 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:32 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 7a0c999..995c0f6 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 d0adf5a..52aac3d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2371,17 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0xe: /* MVCL R1,R2 [RR] */
- insn = ld_code2(env, 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(env, s->pc);
decode_rr(s, insn, &r1, &r2);
@@ -3607,6 +3596,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] 152+ messages in thread
* [Qemu-devel] [PATCH 042/147] target-s390: Convert FP LOAD
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (40 preceding siblings ...)
2012-09-27 23:32 ` [Qemu-devel] [PATCH 041/147] target-s390: Convert MOVE LONG Richard Henderson
@ 2012-09-27 23:33 ` Richard Henderson
2012-09-27 23:34 ` [Qemu-devel] [PATCH 043/147] target-s390: Convert INSERT CHARACTER Richard Henderson
` (105 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:33 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 995c0f6..c3b1f6f 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 52aac3d..bb593f4 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -224,6 +224,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();
@@ -293,6 +300,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));
@@ -2371,20 +2383,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x28: /* LDR R1,R2 [RR] */
- insn = ld_code2(env, 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(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2427,15 +2425,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(tmp);
tcg_temp_free_i64(tmp2);
break;
- case 0x68: /* LD R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2447,18 +2436,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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 */
@@ -3596,6 +3573,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));
@@ -3955,6 +3944,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)) {
@@ -3962,6 +3968,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));
@@ -4137,6 +4150,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] 152+ messages in thread
* [Qemu-devel] [PATCH 043/147] target-s390: Convert INSERT CHARACTER
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (41 preceding siblings ...)
2012-09-27 23:33 ` [Qemu-devel] [PATCH 042/147] target-s390: Convert FP LOAD Richard Henderson
@ 2012-09-27 23:34 ` Richard Henderson
2012-09-27 23:35 ` [Qemu-devel] [PATCH 044/147] target-s390: Cleanup cc computation helpers Richard Henderson
` (104 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:34 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 c3b1f6f..f37e69a 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 bb593f4..2032264 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -283,12 +283,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 */
@@ -1244,7 +1238,7 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
static void disas_e3(CPUS390XState *env, 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",
@@ -1294,12 +1288,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -2383,15 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x43: /* IC R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3922,6 +3901,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);
@@ -4180,6 +4165,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] 152+ messages in thread
* [Qemu-devel] [PATCH 044/147] target-s390: Cleanup cc computation helpers
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (42 preceding siblings ...)
2012-09-27 23:34 ` [Qemu-devel] [PATCH 043/147] target-s390: Convert INSERT CHARACTER Richard Henderson
@ 2012-09-27 23:35 ` Richard Henderson
2012-09-27 23:36 ` [Qemu-devel] [PATCH 045/147] target-s390: Convert INSERT CHARACTERS UNDER MASK Richard Henderson
` (103 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:35 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] 152+ messages in thread
* [Qemu-devel] [PATCH 045/147] target-s390: Convert INSERT CHARACTERS UNDER MASK
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (43 preceding siblings ...)
2012-09-27 23:35 ` [Qemu-devel] [PATCH 044/147] target-s390: Cleanup cc computation helpers Richard Henderson
@ 2012-09-27 23:36 ` Richard Henderson
2012-09-27 23:37 ` [Qemu-devel] [PATCH 046/147] target-s390: Convert EXECUTE Richard Henderson
` (102 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:36 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 2b1abe4..260d4f3 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -27,7 +27,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 f37e69a..38a93e3 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 0a06df8..00dbd54 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 2032264..ebd619e 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;
@@ -561,11 +562,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);
@@ -896,7 +892,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;
@@ -910,6 +905,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);
@@ -1521,18 +1517,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);
@@ -2361,7 +2345,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
static void disas_s390_insn(CPUS390XState *env, 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;
@@ -2786,60 +2770,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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] */
@@ -3493,6 +3423,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] 152+ messages in thread
* [Qemu-devel] [PATCH 046/147] target-s390: Convert EXECUTE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (44 preceding siblings ...)
2012-09-27 23:36 ` [Qemu-devel] [PATCH 045/147] target-s390: Convert INSERT CHARACTERS UNDER MASK Richard Henderson
@ 2012-09-27 23:37 ` Richard Henderson
2012-09-27 23:38 ` [Qemu-devel] [PATCH 047/147] target-s390: Convert FP STORE Richard Henderson
` (101 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:37 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 38a93e3..0768849 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 ebd619e..2582792 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2355,19 +2355,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x44: /* EX R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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(env, s->pc);
tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3423,6 +3410,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] 152+ messages in thread
* [Qemu-devel] [PATCH 047/147] target-s390: Convert FP STORE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (45 preceding siblings ...)
2012-09-27 23:37 ` [Qemu-devel] [PATCH 046/147] target-s390: Convert EXECUTE Richard Henderson
@ 2012-09-27 23:38 ` Richard Henderson
2012-09-27 23:39 ` [Qemu-devel] [PATCH 048/147] target-s390: Convert CONVERT TO DECIMAL Richard Henderson
` (100 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:38 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 0768849..6b81f69 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 2582792..f27dcd4 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2367,25 +2367,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, 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 */
@@ -4028,6 +4009,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] 152+ messages in thread
* [Qemu-devel] [PATCH 048/147] target-s390: Convert CONVERT TO DECIMAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (46 preceding siblings ...)
2012-09-27 23:38 ` [Qemu-devel] [PATCH 047/147] target-s390: Convert FP STORE Richard Henderson
@ 2012-09-27 23:39 ` Richard Henderson
2012-09-27 23:40 ` [Qemu-devel] [PATCH 049/147] target-s390: Convert SET SYSTEM MASK Richard Henderson
` (99 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:39 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 6b81f69..c5c5614 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_D32, r2_32s, new_P, r1_P32, divs32, 0)
C(0x5d00, D, RX_a, Z, r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f27dcd4..0af507b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2355,18 +2355,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x4e: /* CVD R1,D2(X2,B2) [RX] */
- insn = ld_code4(env, 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 */
@@ -3363,6 +3351,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] 152+ messages in thread
* [Qemu-devel] [PATCH 049/147] target-s390: Convert SET SYSTEM MASK
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (47 preceding siblings ...)
2012-09-27 23:39 ` [Qemu-devel] [PATCH 048/147] target-s390: Convert CONVERT TO DECIMAL Richard Henderson
@ 2012-09-27 23:40 ` Richard Henderson
2012-09-27 23:41 ` [Qemu-devel] [PATCH 050/147] target-s390: Convert LOAD PSW Richard Henderson
` (98 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:40 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 c5c5614..45c36c1 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 0af507b..bbdecab 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2356,22 +2356,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
switch (opc) {
#ifndef CONFIG_USER_ONLY
- case 0x80: /* SSM D2(B2) [S] */
- /* Set System Mask */
- check_privileged(s);
- insn = ld_code4(env, 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);
@@ -3607,6 +3591,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] 152+ messages in thread
* [Qemu-devel] [PATCH 050/147] target-s390: Convert LOAD PSW
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (48 preceding siblings ...)
2012-09-27 23:40 ` [Qemu-devel] [PATCH 049/147] target-s390: Convert SET SYSTEM MASK Richard Henderson
@ 2012-09-27 23:41 ` Richard Henderson
2012-09-27 23:42 ` [Qemu-devel] [PATCH 051/147] target-s390: Convert DIAGNOSE Richard Henderson
` (97 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:41 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 | 41 +++++++++++++++++++++--------------------
2 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 45c36c1..b0bee9b 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 bbdecab..ea876a0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2356,26 +2356,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
switch (opc) {
#ifndef CONFIG_USER_ONLY
- case 0x82: /* LPSW D2(B2) [S] */
- /* Load PSW */
- check_privileged(s);
- insn = ld_code4(env, 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));
- /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
- tcg_gen_shli_i64(tmp2, tmp2, 32);
- 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);
@@ -3511,6 +3491,27 @@ 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));
+ /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
+ tcg_gen_shli_i64(t1, t1, 32);
+ 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] 152+ messages in thread
* [Qemu-devel] [PATCH 051/147] target-s390: Convert DIAGNOSE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (49 preceding siblings ...)
2012-09-27 23:41 ` [Qemu-devel] [PATCH 050/147] target-s390: Convert LOAD PSW Richard Henderson
@ 2012-09-27 23:42 ` Richard Henderson
2012-09-27 23:43 ` [Qemu-devel] [PATCH 052/147] target-s390: Convert SHIFT, ROTATE SINGLE Richard Henderson
` (96 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:42 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 b0bee9b..0a0ec0a 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 ea876a0..49e3599 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2355,23 +2355,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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] */
@@ -3327,6 +3310,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] 152+ messages in thread
* [Qemu-devel] [PATCH 052/147] target-s390: Convert SHIFT, ROTATE SINGLE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (50 preceding siblings ...)
2012-09-27 23:42 ` [Qemu-devel] [PATCH 051/147] target-s390: Convert DIAGNOSE Richard Henderson
@ 2012-09-27 23:43 ` Richard Henderson
2012-09-27 23:44 ` [Qemu-devel] [PATCH 053/147] target-s390: Convert SHIFT DOUBLE Richard Henderson
` (95 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:43 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 5b6df0e..ae9b4a3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -478,7 +478,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
};
@@ -521,7 +522,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 0a0ec0a..6020e04 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 49e3599..848bb26 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -636,7 +636,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;
@@ -1330,74 +1331,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
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;
@@ -2355,35 +2288,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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] */
@@ -3029,6 +2933,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) {
@@ -3591,6 +3509,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)
{
@@ -3961,6 +3932,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. */
@@ -4002,6 +3985,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));
@@ -4153,6 +4154,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] 152+ messages in thread
* [Qemu-devel] [PATCH 053/147] target-s390: Convert SHIFT DOUBLE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (51 preceding siblings ...)
2012-09-27 23:43 ` [Qemu-devel] [PATCH 052/147] target-s390: Convert SHIFT, ROTATE SINGLE Richard Henderson
@ 2012-09-27 23:44 ` Richard Henderson
2012-09-27 23:46 ` [Qemu-devel] [PATCH 054/147] target-s390: Convert LOAD, STORE MULTIPLE Richard Henderson
` (94 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:44 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 6020e04..50a1764 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_D32, sh64, new, r1_D32, sla, 0, 31)
+/* SHIFT LEFT DOUBLE LOGICAL */
+ C(0x8d00, SLDL, RS_a, Z, r1_D32, sh64, new, r1_D32, sll, 0)
+/* SHIFT RIGHT DOUBLE */
+ C(0x8e00, SRDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sra, s64)
+/* SHIFT RIGHT DOUBLE LOGICAL */
+ C(0x8c00, SRDL, RS_a, Z, r1_D32, sh64, new, r1_D32, 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 848bb26..12fa278 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2288,36 +2288,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 054/147] target-s390: Convert LOAD, STORE MULTIPLE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (52 preceding siblings ...)
2012-09-27 23:44 ` [Qemu-devel] [PATCH 053/147] target-s390: Convert SHIFT DOUBLE Richard Henderson
@ 2012-09-27 23:46 ` Richard Henderson
2012-09-27 23:47 ` [Qemu-devel] [PATCH 055/147] target-s390: Convert MOVE Richard Henderson
` (93 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:46 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 | 212 ++++++++++++++++++++++++++-------------------
2 files changed, 137 insertions(+), 89 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 50a1764..393b425 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 12fa278..220eb77 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -273,6 +273,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 */
@@ -1324,65 +1329,12 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
static void disas_eb(CPUS390XState *env, 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);
@@ -2277,44 +2229,17 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
static void disas_s390_insn(CPUS390XState *env, 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(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(env, 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(env, s->pc);
tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2611,19 +2536,17 @@ static void disas_s390_insn(CPUS390XState *env, 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:
@@ -3399,6 +3322,69 @@ 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();
+ TCGv_i64 t4 = tcg_const_i64(4);
+
+ while (1) {
+ tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
+ store_reg32_i64(r1, t);
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_add_i64(o->in2, o->in2, t4);
+ r1 = (r1 + 1) & 15;
+ }
+
+ tcg_temp_free_i64(t);
+ tcg_temp_free_i64(t4);
+ 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();
+ TCGv_i64 t4 = tcg_const_i64(4);
+
+ while (1) {
+ tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
+ store_reg32h_i64(r1, t);
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_add_i64(o->in2, o->in2, t4);
+ r1 = (r1 + 1) & 15;
+ }
+
+ tcg_temp_free_i64(t);
+ tcg_temp_free_i64(t4);
+ 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);
+ TCGv_i64 t8 = tcg_const_i64(8);
+
+ while (1) {
+ tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_add_i64(o->in2, o->in2, t8);
+ r1 = (r1 + 1) & 15;
+ }
+
+ tcg_temp_free_i64(t8);
+ return NO_EXIT;
+}
+
static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
{
o->out = o->in2;
@@ -3565,6 +3551,54 @@ 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;
+ TCGv_i64 tsize = tcg_const_i64(size);
+
+ 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_add_i64(o->in2, o->in2, tsize);
+ r1 = (r1 + 1) & 15;
+ }
+
+ tcg_temp_free_i64(tsize);
+ 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();
+ TCGv_i64 t4 = tcg_const_i64(4);
+ TCGv_i64 t32 = tcg_const_i64(32);
+
+ while (1) {
+ tcg_gen_shl_i64(t, regs[r1], t32);
+ tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
+ if (r1 == r3) {
+ break;
+ }
+ tcg_gen_add_i64(o->in2, o->in2, t4);
+ r1 = (r1 + 1) & 15;
+ }
+
+ tcg_temp_free_i64(t);
+ tcg_temp_free_i64(t4);
+ tcg_temp_free_i64(t32);
+ 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] 152+ messages in thread
* [Qemu-devel] [PATCH 055/147] target-s390: Convert MOVE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (53 preceding siblings ...)
2012-09-27 23:46 ` [Qemu-devel] [PATCH 054/147] target-s390: Convert LOAD, STORE MULTIPLE Richard Henderson
@ 2012-09-27 23:47 ` Richard Henderson
2012-09-27 23:48 ` [Qemu-devel] [PATCH 056/147] target-s390: Convert NI, XI, OI Richard Henderson
` (92 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:47 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 393b425..c971308 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 220eb77..2661868 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1329,7 +1329,7 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
static void disas_eb(CPUS390XState *env, 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",
@@ -1395,13 +1395,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2240,14 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x92: /* MVI D1(B1),I2 [SI] */
- insn = ld_code4(env, 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] */
@@ -3912,6 +3897,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] 152+ messages in thread
* [Qemu-devel] [PATCH 056/147] target-s390: Convert NI, XI, OI
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (54 preceding siblings ...)
2012-09-27 23:47 ` [Qemu-devel] [PATCH 055/147] target-s390: Convert MOVE Richard Henderson
@ 2012-09-27 23:48 ` Richard Henderson
2012-09-27 23:49 ` [Qemu-devel] [PATCH 057/147] target-s390: Convert STNSM, STOSM Richard Henderson
` (91 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:48 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 c971308..2383a36 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 2661868..331580f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2233,31 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 057/147] target-s390: Convert STNSM, STOSM
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (55 preceding siblings ...)
2012-09-27 23:48 ` [Qemu-devel] [PATCH 056/147] target-s390: Convert NI, XI, OI Richard Henderson
@ 2012-09-27 23:49 ` Richard Henderson
2012-09-27 23:50 ` [Qemu-devel] [PATCH 058/147] target-s390: Convert LAM, STAM Richard Henderson
` (90 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:49 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 | 43 +++++++++++++++++++++++++------------------
2 files changed, 29 insertions(+), 18 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2383a36..9859b3b 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, 0, 0, stnosm, 0)
+/* STORE THEN OR SYSTEM MASK */
+ C(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 331580f..3cca318 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2226,7 +2226,7 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s->pc);
@@ -2284,23 +2284,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
@@ -3485,6 +3468,30 @@ 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_stnosm(DisasContext *s, DisasOps *o)
+{
+ uint64_t i2 = get_field(s->fields, i2);
+ TCGv_i64 t;
+
+ check_privileged(s);
+
+ /* It is important to do what the instruction name says: STORE THEN.
+ If we let the output hook perform the store then if we fault and
+ restart, we'll have the wrong SYSTEM MASK in place. */
+ t = tcg_temp_new_i64();
+ tcg_gen_shri_i64(t, psw_mask, 56);
+ tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
+ tcg_temp_free_i64(t);
+
+ if (s->fields->op == 0xac) {
+ tcg_gen_andi_i64(psw_mask, psw_mask,
+ (i2 << 56) | 0x00ffffffffffffffull);
+ } else {
+ 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] 152+ messages in thread
* [Qemu-devel] [PATCH 058/147] target-s390: Convert LAM, STAM
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (56 preceding siblings ...)
2012-09-27 23:49 ` [Qemu-devel] [PATCH 057/147] target-s390: Convert STNSM, STOSM Richard Henderson
@ 2012-09-27 23:50 ` Richard Henderson
2012-09-27 23:51 ` [Qemu-devel] [PATCH 059/147] target-s390: Convert CLCLE, MVCLE Richard Henderson
` (89 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:50 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 9859b3b..2e09838 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 3cca318..f583020 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2233,30 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0x9a: /* LAM R1,R3,D2(B2) [RS] */
- insn = ld_code4(env, 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(env, 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(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3265,6 +3241,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);
@@ -3518,6 +3505,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] 152+ messages in thread
* [Qemu-devel] [PATCH 059/147] target-s390: Convert CLCLE, MVCLE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (57 preceding siblings ...)
2012-09-27 23:50 ` [Qemu-devel] [PATCH 058/147] target-s390: Convert LAM, STAM Richard Henderson
@ 2012-09-27 23:51 ` Richard Henderson
2012-09-27 23:52 ` [Qemu-devel] [PATCH 060/147] target-s390: Convert MVC Richard Henderson
` (88 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:51 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 2e09838..4d7f862 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 f583020..8e63721 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2233,32 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
LOG_DISAS("opc 0x%x\n", opc);
switch (opc) {
- case 0xa8: /* MVCLE R1,R3,D2(B2) [RS] */
- insn = ld_code4(env, 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(env, 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);
@@ -3028,6 +3002,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();
@@ -3348,6 +3334,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] 152+ messages in thread
* [Qemu-devel] [PATCH 060/147] target-s390: Convert MVC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (58 preceding siblings ...)
2012-09-27 23:51 ` [Qemu-devel] [PATCH 059/147] target-s390: Convert CLCLE, MVCLE Richard Henderson
@ 2012-09-27 23:52 ` Richard Henderson
2012-09-27 23:53 ` [Qemu-devel] [PATCH 061/147] target-s390: Convert NC, XC, OC, TR, UNPK Richard Henderson
` (87 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:52 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 4d7f862..a8056a8 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 8e63721..7a0ca3e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1012,170 +1012,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;
@@ -2365,7 +2201,6 @@ static void disas_s390_insn(CPUS390XState *env, 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] */
@@ -2381,9 +2216,6 @@ static void disas_s390_insn(CPUS390XState *env, 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);
@@ -3322,6 +3154,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] 152+ messages in thread
* [Qemu-devel] [PATCH 061/147] target-s390: Convert NC, XC, OC, TR, UNPK
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (59 preceding siblings ...)
2012-09-27 23:52 ` [Qemu-devel] [PATCH 060/147] target-s390: Convert MVC Richard Henderson
@ 2012-09-27 23:53 ` Richard Henderson
2012-09-27 23:54 ` [Qemu-devel] [PATCH 062/147] target-s390: Convert CLC Richard Henderson
` (86 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:53 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 a8056a8..015a7f5 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 7a0ca3e..61b63c5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2063,7 +2063,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -2201,51 +2200,15 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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;
@@ -3206,12 +3169,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);
@@ -3446,6 +3429,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] 152+ messages in thread
* [Qemu-devel] [PATCH 062/147] target-s390: Convert CLC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (60 preceding siblings ...)
2012-09-27 23:53 ` [Qemu-devel] [PATCH 061/147] target-s390: Convert NC, XC, OC, TR, UNPK Richard Henderson
@ 2012-09-27 23:54 ` Richard Henderson
2012-09-27 23:55 ` [Qemu-devel] [PATCH 063/147] target-s390: Convert MVCP, MVCS Richard Henderson
` (85 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:54 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 015a7f5..ff8f57f 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 61b63c5..f8698aa 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1012,67 +1012,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(CPUS390XState *env, DisasContext* s, int op, int r1,
int x2, int b2, int d2)
{
@@ -2200,18 +2139,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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] */
@@ -2797,6 +2724,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] 152+ messages in thread
* [Qemu-devel] [PATCH 063/147] target-s390: Convert MVCP, MVCS
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (61 preceding siblings ...)
2012-09-27 23:54 ` [Qemu-devel] [PATCH 062/147] target-s390: Convert CLC Richard Henderson
@ 2012-09-27 23:55 ` Richard Henderson
2012-09-27 23:56 ` [Qemu-devel] [PATCH 064/147] target-s390: Convert LRA Richard Henderson
` (84 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:55 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 ff8f57f..65f0bfd 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 f8698aa..dadf36c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2001,7 +2001,7 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -2139,31 +2139,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
debug_insn(insn);
@@ -3111,6 +3086,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] 152+ messages in thread
* [Qemu-devel] [PATCH 064/147] target-s390: Convert LRA
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (62 preceding siblings ...)
2012-09-27 23:55 ` [Qemu-devel] [PATCH 063/147] target-s390: Convert MVCP, MVCS Richard Henderson
@ 2012-09-27 23:56 ` Richard Henderson
2012-09-27 23:57 ` [Qemu-devel] [PATCH 065/147] target-s390: Convert SIGP Richard Henderson
` (83 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:56 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 260d4f3..c0de601 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -133,7 +133,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)
#endif
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 65f0bfd..a83ce95 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 00dbd54..2c2b105 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 dadf36c..550d6bb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2022,17 +2022,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
@@ -2938,6 +2927,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] 152+ messages in thread
* [Qemu-devel] [PATCH 065/147] target-s390: Convert SIGP
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (63 preceding siblings ...)
2012-09-27 23:56 ` [Qemu-devel] [PATCH 064/147] target-s390: Convert LRA Richard Henderson
@ 2012-09-27 23:57 ` Richard Henderson
2012-09-27 23:58 ` [Qemu-devel] [PATCH 066/147] target-s390: Convert EFPC, STFPC Richard Henderson
` (82 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:57 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 a83ce95..899c6a5 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, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 550d6bb..1e63a0d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2007,22 +2007,6 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, 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(env, s->pc);
op = (insn >> 16) & 0xff;
@@ -3194,6 +3178,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] 152+ messages in thread
* [Qemu-devel] [PATCH 066/147] target-s390: Convert EFPC, STFPC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (64 preceding siblings ...)
2012-09-27 23:57 ` [Qemu-devel] [PATCH 065/147] target-s390: Convert SIGP Richard Henderson
@ 2012-09-27 23:58 ` Richard Henderson
2012-09-27 23:59 ` [Qemu-devel] [PATCH 067/147] target-s390: Convert LCTL, STCTL Richard Henderson
` (81 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:58 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 899c6a5..819c3f5 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 1e63a0d..97ff84b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1839,12 +1839,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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] */
@@ -1997,7 +1991,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
{
- TCGv_i64 tmp, tmp2;
+ TCGv_i64 tmp;
TCGv_i32 tmp32_1, tmp32_2;
unsigned char opc;
uint64_t insn;
@@ -2010,24 +2004,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
case 0xb2:
insn = ld_code4(env, 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(env, s, op, insn);
- break;
- }
+ disas_b2(env, s, op, insn);
break;
case 0xb3:
insn = ld_code4(env, s->pc);
@@ -2774,6 +2751,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
@@ -3700,6 +3683,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] 152+ messages in thread
* [Qemu-devel] [PATCH 067/147] target-s390: Convert LCTL, STCTL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (65 preceding siblings ...)
2012-09-27 23:58 ` [Qemu-devel] [PATCH 066/147] target-s390: Convert EFPC, STFPC Richard Henderson
@ 2012-09-27 23:59 ` Richard Henderson
2012-09-28 0:00 ` [Qemu-devel] [PATCH 068/147] target-s390: Convert COMPARE AND SWAP Richard Henderson
` (80 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-27 23:59 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 819c3f5..6fff22a 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, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 97ff84b..86586ba 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2014,36 +2014,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
r2 = insn & 0xf;
disas_b3(env, 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(env, 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(env, 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(env, s->pc);
r1 = (insn >> 4) & 0xf;
@@ -2894,6 +2864,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);
@@ -3213,6 +3195,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_stnosm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 068/147] target-s390: Convert COMPARE AND SWAP
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (66 preceding siblings ...)
2012-09-27 23:59 ` [Qemu-devel] [PATCH 067/147] target-s390: Convert LCTL, STCTL Richard Henderson
@ 2012-09-28 0:00 ` Richard Henderson
2012-09-28 0:01 ` [Qemu-devel] [PATCH 069/147] target-s390: Convert CLM Richard Henderson
` (79 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:00 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 c0de601..d8d410a 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -18,9 +18,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 6fff22a..4714095 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_D32, a2, new, r1_D32, cds, 0)
+ C(0xeb31, CDSY, RSY_a, LD, r1_D32, a2, new, r1_D32, 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 2c2b105..2604900 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 86586ba..f7a4ad2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1146,30 +1146,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -2021,19 +1997,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(env, s, op, r1, r2);
break;
- case 0xba: /* CS R1,R3,D2(B2) [RS] */
- insn = ld_code4(env, 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(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2665,6 +2628,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] 152+ messages in thread
* [Qemu-devel] [PATCH 069/147] target-s390: Convert CLM
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (67 preceding siblings ...)
2012-09-28 0:00 ` [Qemu-devel] [PATCH 068/147] target-s390: Convert COMPARE AND SWAP Richard Henderson
@ 2012-09-28 0:01 ` Richard Henderson
2012-09-28 0:03 ` [Qemu-devel] [PATCH 070/147] target-s390: Convert STCM Richard Henderson
` (78 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:01 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 4714095..15ded97 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 f7a4ad2..458cd08 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1997,19 +1997,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(env, s, op, r1, r2);
break;
- case 0xbd: /* CLM R1,M3,D2(B2) [RS] */
- insn = ld_code4(env, 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(env, s->pc);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2628,6 +2615,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);
@@ -3712,6 +3712,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] 152+ messages in thread
* [Qemu-devel] [PATCH 070/147] target-s390: Convert STCM
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (68 preceding siblings ...)
2012-09-28 0:01 ` [Qemu-devel] [PATCH 069/147] target-s390: Convert CLM Richard Henderson
@ 2012-09-28 0:03 ` Richard Henderson
2012-09-28 0:04 ` [Qemu-devel] [PATCH 071/147] target-s390: Convert TPROT Richard Henderson
` (77 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:03 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 d8d410a..c33c844 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -8,7 +8,6 @@ DEF_HELPER_4(mvc, void, env, i32, i64, i64)
DEF_HELPER_4(clc, i32, env, i32, i64, i64)
DEF_HELPER_3(mvcl, i32, env, 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_CONST, i64, env, i64, i64)
DEF_HELPER_3(divs32, s64, env, s64, s64)
DEF_HELPER_3(divu32, i64, env, i64, i64)
@@ -26,7 +25,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 15ded97..6c2f455 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 2604900..db48d63 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 458cd08..ae56a51 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1110,16 +1110,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
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 */
@@ -1967,8 +1957,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
static void disas_s390_insn(CPUS390XState *env, 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;
@@ -1997,18 +1985,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(env, s, op, r1, r2);
break;
- case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
- insn = ld_code4(env, 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(env, s->pc);
debug_insn(insn);
@@ -3271,6 +3247,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] 152+ messages in thread
* [Qemu-devel] [PATCH 071/147] target-s390: Convert TPROT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (69 preceding siblings ...)
2012-09-28 0:03 ` [Qemu-devel] [PATCH 070/147] target-s390: Convert STCM Richard Henderson
@ 2012-09-28 0:04 ` Richard Henderson
2012-09-28 0:05 ` [Qemu-devel] [PATCH 072/147] target-s390: Convert LOAD CONTROL, part 2 Richard Henderson
` (76 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:04 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 6c2f455..8bfc6f9 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -508,4 +508,6 @@
C(0xac00, STNSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
C(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 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 ae56a51..4195c7e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1073,34 +1073,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
tcg_temp_free_i64(addr);
}
-#ifndef CONFIG_USER_ONLY
-static void disas_e5(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int op, int r1,
int r3, int b2, int d2)
{
@@ -1996,15 +1968,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
| ((insn << 4) & 0xff000)) << 12)) >> 12;
disas_e3(env, s, op, r1, x2, b2, d2 );
break;
-#ifndef CONFIG_USER_ONLY
- case 0xe5:
- /* Test Protection */
- check_privileged(s);
- insn = ld_code6(env, s->pc);
- debug_insn(insn);
- disas_e5(env, s, insn);
- break;
-#endif
case 0xeb:
insn = ld_code6(env, s->pc);
debug_insn(insn);
@@ -3387,6 +3350,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] 152+ messages in thread
* [Qemu-devel] [PATCH 072/147] target-s390: Convert LOAD CONTROL, part 2
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (70 preceding siblings ...)
2012-09-28 0:04 ` [Qemu-devel] [PATCH 071/147] target-s390: Convert TPROT Richard Henderson
@ 2012-09-28 0:05 ` Richard Henderson
2012-09-28 0:06 ` [Qemu-devel] [PATCH 073/147] target-s390: Convert LOAD REVERSED Richard Henderson
` (75 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0: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 | 76 ++++++++++++++--------------------------------
2 files changed, 25 insertions(+), 53 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8bfc6f9..a8dffcd 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, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4195c7e..b78e31c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1073,48 +1073,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
tcg_temp_free_i64(addr);
}
-static void disas_eb(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int op, int r1,
int x2, int b2, int d2, int r1b)
{
@@ -1968,17 +1926,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
| ((insn << 4) & 0xff000)) << 12)) >> 12;
disas_e3(env, s, op, r1, x2, b2, d2 );
break;
- case 0xeb:
- insn = ld_code6(env, 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(env, s, op, r1, r3, b2, d2);
- break;
case 0xed:
insn = ld_code6(env, s->pc);
debug_insn(insn);
@@ -2819,6 +2766,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);
@@ -3138,6 +3096,18 @@ static ExitStatus op_ssm(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_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] 152+ messages in thread
* [Qemu-devel] [PATCH 073/147] target-s390: Convert LOAD REVERSED
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (71 preceding siblings ...)
2012-09-28 0:05 ` [Qemu-devel] [PATCH 072/147] target-s390: Convert LOAD CONTROL, part 2 Richard Henderson
@ 2012-09-28 0:06 ` Richard Henderson
2012-09-28 0:07 ` [Qemu-devel] [PATCH 074/147] target-s390: Convert STORE REVERSED Richard Henderson
` (74 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:06 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 a8dffcd..1ee0d42 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 b78e31c..468c8ea 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -278,17 +278,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 */
@@ -1022,13 +1011,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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));
@@ -1036,26 +1018,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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();
@@ -1861,15 +1823,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -3023,6 +2976,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();
@@ -3576,6 +3547,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);
@@ -3918,6 +3895,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] 152+ messages in thread
* [Qemu-devel] [PATCH 074/147] target-s390: Convert STORE REVERSED
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (72 preceding siblings ...)
2012-09-28 0:06 ` [Qemu-devel] [PATCH 073/147] target-s390: Convert LOAD REVERSED Richard Henderson
@ 2012-09-28 0:07 ` Richard Henderson
2012-09-28 0:08 ` [Qemu-devel] [PATCH 075/147] target-s390: Convert LLGT Richard Henderson
` (73 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:07 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 1ee0d42..fa3ee00 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 468c8ea..4757713 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1005,7 +1005,6 @@ static void disas_e3(CPUS390XState *env, 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);
@@ -1018,15 +1017,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
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);
@@ -3738,6 +3728,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);
@@ -3783,6 +3779,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] 152+ messages in thread
* [Qemu-devel] [PATCH 075/147] target-s390: Convert LLGT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (73 preceding siblings ...)
2012-09-28 0:07 ` [Qemu-devel] [PATCH 074/147] target-s390: Convert STORE REVERSED Richard Henderson
@ 2012-09-28 0:08 ` Richard Henderson
2012-09-28 0:09 ` [Qemu-devel] [PATCH 076/147] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED Richard Henderson
` (72 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:08 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 | 50 ++++++----------------------------------------
2 files changed, 9 insertions(+), 44 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index fa3ee00..8914d34 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 4757713..739d665 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1001,30 +1001,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void disas_e3(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int op, int r1,
int x2, int b2, int d2, int r1b)
{
@@ -1804,15 +1780,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1858,17 +1825,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(env, s, op, r1, r2);
break;
- case 0xe3:
- insn = ld_code6(env, 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(env, s, op, r1, x2, b2, d2 );
- break;
case 0xed:
insn = ld_code6(env, s->pc);
debug_insn(insn);
@@ -2654,6 +2610,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] 152+ messages in thread
* [Qemu-devel] [PATCH 076/147] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (74 preceding siblings ...)
2012-09-28 0:08 ` [Qemu-devel] [PATCH 075/147] target-s390: Convert LLGT Richard Henderson
@ 2012-09-28 0:09 ` Richard Henderson
2012-09-28 0:10 ` [Qemu-devel] [PATCH 077/147] target-s390: Convert FP SUBTRACT Richard Henderson
` (71 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:09 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 | 298 +++++++++++++++++----------------------------
target-s390x/helper.h | 31 ++---
target-s390x/insn-data.def | 25 ++++
target-s390x/translate.c | 217 +++++++++++++++++++--------------
6 files changed, 278 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 ae9b4a3..7d17bf3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -471,11 +471,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) */
@@ -517,10 +515,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",
@@ -935,10 +932,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 ilen);
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index ee9420d..debaa7f 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -32,6 +32,52 @@
#define HELPER_LOG(x...)
#endif
+#define RET128(F) (env->retxl = F.low, F.high)
+
+#define convert_bit(mask, from, to) \
+ (to < from \
+ ? (mask / (from / to)) & to \
+ : (mask & from) * (to / from))
+
+static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
+{
+ /* Install the DXC code. */
+ env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
+ /* Trap. */
+ runtime_exception(env, PGM_DATA, retaddr);
+}
+
+/* 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;
+ if (qemu_exc == 0) {
+ return;
+ }
+ 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. */
+ s390_exc &= env->fpc >> 24;
+ if (s390_exc) {
+ ieee_exception(env, s390_exc, retaddr);
+ }
+}
+
static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
{
switch (float_compare) {
@@ -48,19 +94,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 +121,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 +185,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 +283,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 +366,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 +395,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 +419,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)
-{
- 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);
-}
-
-/* 64-bit FP compare RR */
-uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP compare */
+uint32_t HELPER(ceb)(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 = float32_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)
+/* 64-bit FP compare */
+uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- 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);
+ int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return float_comp_to_cc(env, cmp);
}
-/* 64-bit FP addition RM */
-uint32_t HELPER(adb)(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: 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 +637,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 +695,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 c33c844..a2ef6af 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -36,40 +36,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)
@@ -79,7 +75,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)
@@ -87,8 +82,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 8914d34..f1c37e8 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 739d665..b37c140 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -556,14 +556,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);
@@ -628,10 +620,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;
@@ -1009,35 +1000,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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();
@@ -1084,16 +1046,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1524,24 +1476,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -1551,9 +1488,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -1563,12 +1497,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -1605,27 +1533,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -2260,6 +2170,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);
@@ -2354,6 +2283,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);
@@ -2610,6 +2560,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);
@@ -3369,6 +3357,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);
@@ -3482,6 +3485,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
@@ -3539,6 +3557,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);
@@ -3685,6 +3704,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));
@@ -3832,9 +3860,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] 152+ messages in thread
* [Qemu-devel] [PATCH 077/147] target-s390: Convert FP SUBTRACT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (75 preceding siblings ...)
2012-09-28 0:09 ` [Qemu-devel] [PATCH 076/147] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED Richard Henderson
@ 2012-09-28 0:10 ` Richard Henderson
2012-09-28 0:11 ` [Qemu-devel] [PATCH 078/147] target-s390: Convert FP DIVIDE Richard Henderson
` (70 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:10 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 debaa7f..1d6b7b4 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -212,27 +212,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 */
@@ -446,27 +450,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)
{
@@ -620,23 +603,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 a2ef6af..ad4f7ef 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -39,8 +39,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)
@@ -59,8 +60,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)
@@ -75,7 +74,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 f1c37e8..fdfcffc 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 b37c140..d896fee 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -556,11 +556,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)
{
@@ -1000,19 +995,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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();
@@ -1046,11 +1028,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1479,9 +1456,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -1497,9 +1471,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -1536,9 +1507,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -2955,6 +2923,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] 152+ messages in thread
* [Qemu-devel] [PATCH 078/147] target-s390: Convert FP DIVIDE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (76 preceding siblings ...)
2012-09-28 0:10 ` [Qemu-devel] [PATCH 077/147] target-s390: Convert FP SUBTRACT Richard Henderson
@ 2012-09-28 0:11 ` Richard Henderson
2012-09-28 0:12 ` [Qemu-devel] [PATCH 079/147] target-s390: Convert FP MULTIPLY Richard Henderson
` (69 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:11 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 1d6b7b4..8aef76b 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -239,28 +239,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 */
@@ -399,18 +402,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)
{
@@ -462,18 +453,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) {
@@ -611,13 +590,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 ad4f7ef..c04b04c 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -42,8 +42,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)
@@ -58,10 +59,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)
@@ -75,7 +74,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 fdfcffc..14dcd12 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_D32, r2_32s, new_P, r1_P32, divs32, 0)
C(0x5d00, D, RX_a, Z, r1_D32, 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_D32, r2_32u, new_P, r1_P32, divu32, 0)
C(0xe397, DL, RXY_a, Z, r1_D32, m2_32u, new_P, r1_P32, divu32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d896fee..6a30b82 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -995,15 +995,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1032,10 +1023,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1456,9 +1443,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -1474,9 +1458,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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] */
@@ -1510,9 +1491,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -2428,6 +2406,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] 152+ messages in thread
* [Qemu-devel] [PATCH 079/147] target-s390: Convert FP MULTIPLY
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (77 preceding siblings ...)
2012-09-28 0:11 ` [Qemu-devel] [PATCH 078/147] target-s390: Convert FP DIVIDE Richard Henderson
@ 2012-09-28 0:12 ` Richard Henderson
2012-09-28 0:13 ` [Qemu-devel] [PATCH 080/147] target-s390: Convert MULTIPLY AND ADD, SUBTRACT Richard Henderson
` (68 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:12 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 8aef76b..dd7e3a0 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -266,27 +266,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 */
@@ -402,18 +425,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)
{
@@ -441,18 +452,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) {
@@ -582,14 +581,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 c04b04c..8fe2031 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -45,8 +45,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)
@@ -59,8 +62,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)
@@ -73,7 +74,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 14dcd12..89f71ac 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_o, m2_16s, new, r1_32, mul, 0)
C(0xe37c, MHY, RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6a30b82..4c7fee1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -991,7 +991,7 @@ static void disas_ed(CPUS390XState *env, 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) {
@@ -1010,19 +1010,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1452,12 +1439,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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] */
@@ -1488,9 +1469,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -2827,6 +2805,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] 152+ messages in thread
* [Qemu-devel] [PATCH 080/147] target-s390: Convert MULTIPLY AND ADD, SUBTRACT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (78 preceding siblings ...)
2012-09-28 0:12 ` [Qemu-devel] [PATCH 079/147] target-s390: Convert FP MULTIPLY Richard Henderson
@ 2012-09-28 0:13 ` Richard Henderson
2012-09-28 0:14 ` [Qemu-devel] [PATCH 081/147] target-s390: Convert TEST DATA CLASS Richard Henderson
` (67 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:13 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 dd7e3a0..c4ce4b5 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -581,47 +581,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 8fe2031..6fa80e1 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -74,10 +74,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 89f71ac..a924a93 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -391,6 +391,17 @@
C(0xc201, MSFI, RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
C(0xc200, MSGFI, RIL_a, GIE, r1_o, 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 4c7fee1..6c1f505 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -990,7 +990,7 @@ static void free_compare(DisasCompare *c)
static void disas_ed(CPUS390XState *env, 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);
@@ -1010,13 +1010,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
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);
@@ -1439,30 +1432,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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;
@@ -2837,6 +2806,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] 152+ messages in thread
* [Qemu-devel] [PATCH 081/147] target-s390: Convert TEST DATA CLASS
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (79 preceding siblings ...)
2012-09-28 0:13 ` [Qemu-devel] [PATCH 080/147] target-s390: Convert MULTIPLY AND ADD, SUBTRACT Richard Henderson
@ 2012-09-28 0:14 ` Richard Henderson
2012-09-28 0:15 ` [Qemu-devel] [PATCH 082/147] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE Richard Henderson
` (66 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:14 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 c4ce4b5..c940b4a 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -620,13 +620,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)))) ||
@@ -636,19 +635,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)))) ||
@@ -663,20 +659,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 6fa80e1..31fffc8 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -78,9 +78,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 a924a93..54b75e1 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 6c1f505..af58ddd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -987,38 +987,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void disas_ed(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s, int op,
uint32_t insn)
{
@@ -1602,7 +1570,7 @@ static void disas_s390_insn(CPUS390XState *env, 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(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -1628,17 +1596,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b9(env, s, op, r1, r2);
break;
- case 0xed:
- insn = ld_code6(env, 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(env, s, op, r1, x2, b2, d2, r1b);
- break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s);
@@ -3224,6 +3181,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] 152+ messages in thread
* [Qemu-devel] [PATCH 082/147] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (80 preceding siblings ...)
2012-09-28 0:14 ` [Qemu-devel] [PATCH 081/147] target-s390: Convert TEST DATA CLASS Richard Henderson
@ 2012-09-28 0:15 ` Richard Henderson
2012-09-28 0:16 ` [Qemu-devel] [PATCH 083/147] target-s390: Convert FP SQUARE ROOT Richard Henderson
` (65 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:15 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 c940b4a..0a2bdd0 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -360,71 +360,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 31fffc8..a32ba9b 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -56,12 +56,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 54b75e1..74bc994 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 af58ddd..0bb39bb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1385,35 +1385,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -1997,6 +1971,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);
@@ -2799,6 +2792,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));
@@ -2815,6 +2827,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] 152+ messages in thread
* [Qemu-devel] [PATCH 083/147] target-s390: Convert FP SQUARE ROOT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (81 preceding siblings ...)
2012-09-28 0:15 ` [Qemu-devel] [PATCH 082/147] target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE Richard Henderson
@ 2012-09-28 0:16 ` Richard Henderson
2012-09-28 0:17 ` [Qemu-devel] [PATCH 084/147] target-s390: Convert LOAD ZERO Richard Henderson
` (64 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:16 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 0a2bdd0..82e44c5 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -613,8 +613,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 a32ba9b..6e5c340 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -76,7 +76,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 74bc994..93fd3ca 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_D32, sh64, new, r1_D32, 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 0bb39bb..b51c6f7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1385,9 +1385,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -2936,6 +2933,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] 152+ messages in thread
* [Qemu-devel] [PATCH 084/147] target-s390: Convert LOAD ZERO
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (82 preceding siblings ...)
2012-09-28 0:16 ` [Qemu-devel] [PATCH 083/147] target-s390: Convert FP SQUARE ROOT Richard Henderson
@ 2012-09-28 0:17 ` Richard Henderson
2012-09-28 0:18 ` [Qemu-devel] [PATCH 085/147] target-s390: Convert CONVERT TO FIXED Richard Henderson
` (63 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:17 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 82e44c5..e3d74ff 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -494,28 +494,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 6e5c340..66127e4 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -62,9 +62,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 93fd3ca..e6b9a5a 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 b51c6f7..4efc286 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1385,21 +1385,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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));
@@ -3310,6 +3295,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] 152+ messages in thread
* [Qemu-devel] [PATCH 085/147] target-s390: Convert CONVERT TO FIXED
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (83 preceding siblings ...)
2012-09-28 0:17 ` [Qemu-devel] [PATCH 084/147] target-s390: Convert LOAD ZERO Richard Henderson
@ 2012-09-28 0:18 ` Richard Henderson
2012-09-28 0:20 ` [Qemu-devel] [PATCH 086/147] target-s390: Convert CONVERT FROM FIXED Richard Henderson
` (62 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:18 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 e3d74ff..a28cf08 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -387,8 +387,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 */
@@ -412,86 +413,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 66127e4..3350040 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -59,12 +59,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 e6b9a5a..2d88b70 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_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4efc286..0284ded 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -485,6 +485,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)
{
@@ -1367,7 +1382,7 @@ static void disas_b3(CPUS390XState *env, 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); \
@@ -1411,30 +1426,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -1459,36 +1450,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -2129,6 +2090,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] 152+ messages in thread
* [Qemu-devel] [PATCH 086/147] target-s390: Convert CONVERT FROM FIXED
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (84 preceding siblings ...)
2012-09-28 0:18 ` [Qemu-devel] [PATCH 085/147] target-s390: Convert CONVERT TO FIXED Richard Henderson
@ 2012-09-28 0:20 ` Richard Henderson
2012-09-28 0:21 ` [Qemu-devel] [PATCH 087/147] target-s390: Convert FLOGR Richard Henderson
` (61 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:20 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 a28cf08..82505eb 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -134,57 +134,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)
{
@@ -416,6 +365,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 3350040..5d42951 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -30,12 +30,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 2d88b70..d5e1c5c 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_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0284ded..6694443 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1381,8 +1381,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
static void disas_b3(CPUS390XState *env, 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); \
@@ -1405,51 +1404,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
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);
@@ -2144,6 +2098,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] 152+ messages in thread
* [Qemu-devel] [PATCH 087/147] target-s390: Convert FLOGR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (85 preceding siblings ...)
2012-09-28 0:20 ` [Qemu-devel] [PATCH 086/147] target-s390: Convert CONVERT FROM FIXED Richard Henderson
@ 2012-09-28 0:21 ` Richard Henderson
2012-09-28 0:22 ` [Qemu-devel] [PATCH 088/147] target-s390: Convert LFPC, SFPC Richard Henderson
` (60 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:21 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 | 66 +++++++++++++++++++++++++---------------------
6 files changed, 53 insertions(+), 50 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 7d17bf3..a6a6e3f 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -478,6 +478,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
};
@@ -521,6 +522,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 5d42951..be37f8a 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -69,7 +69,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 d5e1c5c..771baaf 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 6694443..e65b752 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -620,6 +620,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;
@@ -852,6 +853,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. */
@@ -888,6 +903,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;
@@ -1414,29 +1430,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
#undef FP_HELPER
}
-static void disas_b9(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s)
{
unsigned char opc;
@@ -1460,13 +1453,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
r2 = insn & 0xf;
disas_b3(env, s, op, r3, r1, r2);
break;
- case 0xb9:
- insn = ld_code4(env, s->pc);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- op = (insn >> 16) & 0xff;
- disas_b9(env, s, op, r1, r2);
- break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s);
@@ -2330,6 +2316,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] 152+ messages in thread
* [Qemu-devel] [PATCH 088/147] target-s390: Convert LFPC, SFPC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (86 preceding siblings ...)
2012-09-28 0:21 ` [Qemu-devel] [PATCH 087/147] target-s390: Convert FLOGR Richard Henderson
@ 2012-09-28 0:22 ` Richard Henderson
2012-09-28 0:23 ` [Qemu-devel] [PATCH 089/147] target-s390: Convert IPM Richard Henderson
` (59 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:22 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 | 64 +++++-----------------------------------------
4 files changed, 31 insertions(+), 57 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 82505eb..e40e531 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -577,3 +577,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 be37f8a..e8300ec 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -77,6 +77,7 @@ 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)
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 771baaf..b319beb 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 e65b752..9f8fcb5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1337,18 +1337,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -1394,47 +1382,11 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
}
}
-static void disas_b3(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s)
{
unsigned char opc;
uint64_t insn;
- int op, r1, r2, r3;
+ int op;
opc = cpu_ldub_code(env, s->pc);
LOG_DISAS("opc 0x%x\n", opc);
@@ -1445,14 +1397,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
op = (insn >> 16) & 0xff;
disas_b2(env, s, op, insn);
break;
- case 0xb3:
- insn = ld_code4(env, s->pc);
- op = (insn >> 16) & 0xff;
- r3 = (insn >> 12) & 0xf; /* aka m3 */
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- disas_b3(env, s, op, r3, r1, r2);
- break;
default:
qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s);
@@ -2981,6 +2925,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] 152+ messages in thread
* [Qemu-devel] [PATCH 089/147] target-s390: Convert IPM
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (87 preceding siblings ...)
2012-09-28 0:22 ` [Qemu-devel] [PATCH 088/147] target-s390: Convert LFPC, SFPC Richard Henderson
@ 2012-09-28 0:23 ` Richard Henderson
2012-09-28 0:24 ` [Qemu-devel] [PATCH 090/147] target-s390: Convert CKSM Richard Henderson
` (58 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:23 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 e8300ec..5ae723e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -25,7 +25,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 b319beb..13b1771 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 9f8fcb5..4990e57 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,12 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2348,6 +2342,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] 152+ messages in thread
* [Qemu-devel] [PATCH 090/147] target-s390: Convert CKSM
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (88 preceding siblings ...)
2012-09-28 0:23 ` [Qemu-devel] [PATCH 089/147] target-s390: Convert IPM Richard Henderson
@ 2012-09-28 0:24 ` Richard Henderson
2012-09-28 0:25 ` [Qemu-devel] [PATCH 091/147] target-s390: Convert EAR, SAR Richard Henderson
` (57 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:24 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 | 43 +++++++++++++++++++++++++------------------
target-s390x/translate.c | 31 ++++++++++++++++++++++---------
4 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5ae723e..9bcf79f 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -75,7 +75,7 @@ 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)
-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 13b1771..74f1032 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 db48d63..1b06297 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -753,42 +753,49 @@ 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;
+ len += 1;
break;
case 2:
cksm += cpu_lduw_data(env, src) << 16;
+ len += 2;
break;
case 3:
cksm += cpu_lduw_data(env, src) << 16;
cksm += cpu_ldub_data(env, src + 2) << 8;
+ len += 3;
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 4990e57..06b0322 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,15 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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]));
@@ -2047,6 +2038,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);
@@ -3847,6 +3855,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] 152+ messages in thread
* [Qemu-devel] [PATCH 091/147] target-s390: Convert EAR, SAR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (89 preceding siblings ...)
2012-09-28 0:24 ` [Qemu-devel] [PATCH 090/147] target-s390: Convert CKSM Richard Henderson
@ 2012-09-28 0:25 ` Richard Henderson
2012-09-28 0:26 ` [Qemu-devel] [PATCH 092/147] target-s390: Convert MVPG Richard Henderson
` (56 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:25 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 74f1032..c4ce7e2 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 06b0322..030fa0a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,17 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2230,6 +2219,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));
@@ -2864,6 +2860,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] 152+ messages in thread
* [Qemu-devel] [PATCH 092/147] target-s390: Convert MVPG
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (90 preceding siblings ...)
2012-09-28 0:25 ` [Qemu-devel] [PATCH 091/147] target-s390: Convert EAR, SAR Richard Henderson
@ 2012-09-28 0:26 ` Richard Henderson
2012-09-28 0:27 ` [Qemu-devel] [PATCH 093/147] target-s390: Convert CLST, MVST Richard Henderson
` (55 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:26 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 c4ce7e2..4223d35 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 1b06297..afeda18 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 030fa0a..ed4f794 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,18 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2654,6 +2642,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] 152+ messages in thread
* [Qemu-devel] [PATCH 093/147] target-s390: Convert CLST, MVST
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (91 preceding siblings ...)
2012-09-28 0:26 ` [Qemu-devel] [PATCH 092/147] target-s390: Convert MVPG Richard Henderson
@ 2012-09-28 0:27 ` Richard Henderson
2012-09-28 0:28 ` [Qemu-devel] [PATCH 094/147] target-s390: Convert SRST Richard Henderson
` (54 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:27 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 9bcf79f..2bac4e6 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -14,9 +14,9 @@ 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_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 4223d35..b485b85 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 afeda18..6ce6ea3 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 ed4f794..dceb738 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -427,7 +427,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;
}
@@ -1034,28 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2091,6 +2069,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);
@@ -2650,6 +2637,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] 152+ messages in thread
* [Qemu-devel] [PATCH 094/147] target-s390: Convert SRST
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (92 preceding siblings ...)
2012-09-28 0:27 ` [Qemu-devel] [PATCH 093/147] target-s390: Convert CLST, MVST Richard Henderson
@ 2012-09-28 0:28 ` Richard Henderson
2012-09-28 0:29 ` [Qemu-devel] [PATCH 095/147] target-s390: Convert STIDP Richard Henderson
` (53 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:28 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 | 39 ++++++++++++++++++++++++++-------------
target-s390x/translate.c | 31 ++++++++++++++-----------------
4 files changed, 44 insertions(+), 31 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 2bac4e6..79bebc9 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -13,7 +13,7 @@ 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_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 b485b85..5e1f8fd 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 6ce6ea3..8522140 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -337,25 +337,38 @@ 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 r0, 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;
+ uint8_t v, c = r0;
- HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
- c, env->regs[r1], env->regs[r2]);
+ 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) {
+ if (str + len == end) {
+ /* Character not found. R1 & R2 are unmodified. */
+ env->cc_op = 2;
+ return end;
+ }
+ v = cpu_ldub_data(env, str + len);
+ if (v == c) {
+ /* Character found. Set R1 to the location; R2 is unmodified. */
+ env->cc_op = 1;
+ return str + len;
}
}
- 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 dceb738..2ccf569 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1021,12 +1021,11 @@ static void free_compare(DisasCompare *c)
static void disas_b2(CPUS390XState *env, 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;
@@ -1034,19 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -1314,12 +1300,14 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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(CPUS390XState *env, DisasContext *s)
@@ -3136,6 +3124,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] 152+ messages in thread
* [Qemu-devel] [PATCH 095/147] target-s390: Convert STIDP
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (93 preceding siblings ...)
2012-09-28 0:28 ` [Qemu-devel] [PATCH 094/147] target-s390: Convert SRST Richard Henderson
@ 2012-09-28 0:29 ` Richard Henderson
2012-09-28 0:30 ` [Qemu-devel] [PATCH 096/147] target-s390: Convert SCK Richard Henderson
` (52 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:29 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 79bebc9..df6172e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -85,7 +85,6 @@ DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
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_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 5e1f8fd..4d9ecf4 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, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index aec222c..e4518a6 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -178,12 +178,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 2ccf569..f7eaa29 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2967,6 +2958,13 @@ static ExitStatus op_stctl(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_stnosm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 096/147] target-s390: Convert SCK
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (94 preceding siblings ...)
2012-09-28 0:29 ` [Qemu-devel] [PATCH 095/147] target-s390: Convert STIDP Richard Henderson
@ 2012-09-28 0:30 ` Richard Henderson
2012-09-28 0:31 ` [Qemu-devel] [PATCH 097/147] target-s390: Convert STCK Richard Henderson
` (51 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:30 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 df6172e..1a7e305 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -86,7 +86,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_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 4d9ecf4..824e9dc 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 e4518a6..0b404f5 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -190,14 +190,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 f7eaa29..01a30a3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,16 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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] 152+ messages in thread
* [Qemu-devel] [PATCH 097/147] target-s390: Convert STCK
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (95 preceding siblings ...)
2012-09-28 0:30 ` [Qemu-devel] [PATCH 096/147] target-s390: Convert SCK Richard Henderson
@ 2012-09-28 0:31 ` Richard Henderson
2012-09-28 0:32 ` [Qemu-devel] [PATCH 098/147] target-s390: Convert SCKC, STCKC Richard Henderson
` (50 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:31 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 1a7e305..c3c538a 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -86,7 +86,7 @@ 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_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 824e9dc..4404791 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 0b404f5..326272b 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -201,11 +201,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 01a30a3..e67a070 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2924,6 +2915,14 @@ static ExitStatus op_ssm(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_stctg(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] 152+ messages in thread
* [Qemu-devel] [PATCH 098/147] target-s390: Convert SCKC, STCKC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (96 preceding siblings ...)
2012-09-28 0:31 ` [Qemu-devel] [PATCH 097/147] target-s390: Convert STCK Richard Henderson
@ 2012-09-28 0:32 ` Richard Henderson
2012-09-28 0:33 ` [Qemu-devel] [PATCH 099/147] target-s390: Convert SPT, STPT Richard Henderson
` (49 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:32 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 c3c538a..85659fd 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -89,7 +89,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 4404791..06c780b 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 326272b..16cc0c3 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -221,10 +221,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;
}
@@ -238,10 +236,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 e67a070..0dd3265 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,24 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2923,6 +2905,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_stctg(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] 152+ messages in thread
* [Qemu-devel] [PATCH 099/147] target-s390: Convert SPT, STPT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (97 preceding siblings ...)
2012-09-28 0:32 ` [Qemu-devel] [PATCH 098/147] target-s390: Convert SCKC, STCKC Richard Henderson
@ 2012-09-28 0:33 ` Richard Henderson
2012-09-28 0:34 ` [Qemu-devel] [PATCH 100/147] target-s390: Convert SPKA Richard Henderson
` (48 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:33 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 85659fd..28aabe7 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -91,7 +91,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 06c780b..a45454c 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, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 16cc0c3..3fe74de 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -243,10 +243,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;
}
@@ -258,10 +256,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 0dd3265..a1f28a7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,24 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2950,6 +2932,20 @@ static ExitStatus op_stidp(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_stnosm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 100/147] target-s390: Convert SPKA
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (98 preceding siblings ...)
2012-09-28 0:33 ` [Qemu-devel] [PATCH 099/147] target-s390: Convert SPT, STPT Richard Henderson
@ 2012-09-28 0:34 ` Richard Henderson
2012-09-28 0:35 ` [Qemu-devel] [PATCH 101/147] target-s390: Convert PTLB Richard Henderson
` (47 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:34 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 a45454c..f95ba11 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 a1f28a7..b593b79 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2872,6 +2860,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] 152+ messages in thread
* [Qemu-devel] [PATCH 101/147] target-s390: Convert PTLB
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (99 preceding siblings ...)
2012-09-28 0:34 ` [Qemu-devel] [PATCH 100/147] target-s390: Convert SPKA Richard Henderson
@ 2012-09-28 0:35 ` Richard Henderson
2012-09-28 0:37 ` [Qemu-devel] [PATCH 102/147] target-s390: Convert SPX, STPX Richard Henderson
` (46 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:35 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 f95ba11..e9b9dc1 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 b593b79..952de68 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,11 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2725,6 +2720,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] 152+ messages in thread
* [Qemu-devel] [PATCH 102/147] target-s390: Convert SPX, STPX
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (100 preceding siblings ...)
2012-09-28 0:35 ` [Qemu-devel] [PATCH 101/147] target-s390: Convert PTLB Richard Henderson
@ 2012-09-28 0:37 ` Richard Henderson
2012-09-28 0:38 ` [Qemu-devel] [PATCH 103/147] target-s390: Convert STAP Richard Henderson
` (45 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:37 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 e9b9dc1..87a77a2 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, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 3fe74de..925dc0a 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -181,10 +181,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 952de68..36fbb1d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,26 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2946,6 +2926,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_stnosm(DisasContext *s, DisasOps *o)
{
uint64_t i2 = get_field(s->fields, i2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 103/147] target-s390: Convert STAP
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (101 preceding siblings ...)
2012-09-28 0:37 ` [Qemu-devel] [PATCH 102/147] target-s390: Convert SPX, STPX Richard Henderson
@ 2012-09-28 0:38 ` Richard Henderson
2012-09-28 0:39 ` [Qemu-devel] [PATCH 104/147] target-s390: Convert IPTE Richard Henderson
` (44 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:38 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 87a77a2..f68e586 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 36fbb1d..fd58524 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,20 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2859,6 +2845,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_stck(DisasContext *s, DisasOps *o)
{
gen_helper_stck(o->out, cpu_env);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 104/147] target-s390: Convert IPTE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (102 preceding siblings ...)
2012-09-28 0:38 ` [Qemu-devel] [PATCH 103/147] target-s390: Convert STAP Richard Henderson
@ 2012-09-28 0:39 ` Richard Henderson
2012-09-28 0:40 ` [Qemu-devel] [PATCH 105/147] target-s390: Convert ISKE Richard Henderson
` (43 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:39 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 f68e586..c8368cf 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 fd58524..1001812 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,17 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2213,6 +2202,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] 152+ messages in thread
* [Qemu-devel] [PATCH 105/147] target-s390: Convert ISKE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (103 preceding siblings ...)
2012-09-28 0:39 ` [Qemu-devel] [PATCH 104/147] target-s390: Convert IPTE Richard Henderson
@ 2012-09-28 0:40 ` Richard Henderson
2012-09-28 0:41 ` [Qemu-devel] [PATCH 106/147] target-s390: Convert SSKE Richard Henderson
` (42 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:40 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 c8368cf..87daec1 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 1001812..bf746c7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2209,6 +2197,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] 152+ messages in thread
* [Qemu-devel] [PATCH 106/147] target-s390: Convert SSKE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (104 preceding siblings ...)
2012-09-28 0:40 ` [Qemu-devel] [PATCH 105/147] target-s390: Convert ISKE Richard Henderson
@ 2012-09-28 0:41 ` Richard Henderson
2012-09-28 0:42 ` [Qemu-devel] [PATCH 107/147] target-s390: Convert RRBE Richard Henderson
` (41 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:41 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 28aabe7..3b437c0 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -99,7 +99,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 87daec1..f554c1b 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 8522140..c6f7741 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -952,7 +952,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 bf746c7..68f5b3c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1045,17 +1045,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2831,6 +2820,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] 152+ messages in thread
* [Qemu-devel] [PATCH 107/147] target-s390: Convert RRBE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (105 preceding siblings ...)
2012-09-28 0:41 ` [Qemu-devel] [PATCH 106/147] target-s390: Convert SSKE Richard Henderson
@ 2012-09-28 0:42 ` Richard Henderson
2012-09-28 0:43 ` [Qemu-devel] [PATCH 108/147] target-s390: Convert subchannel instructions Richard Henderson
` (40 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:42 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 3b437c0..0b8e7a9 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -100,7 +100,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 f554c1b..2a04572 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 c6f7741..1a32436 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -964,7 +964,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 68f5b3c..e211a60 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2716,6 +2704,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] 152+ messages in thread
* [Qemu-devel] [PATCH 108/147] target-s390: Convert subchannel instructions
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (106 preceding siblings ...)
2012-09-28 0:42 ` [Qemu-devel] [PATCH 107/147] target-s390: Convert RRBE Richard Henderson
@ 2012-09-28 0:43 ` Richard Henderson
2012-09-28 0:44 ` [Qemu-devel] [PATCH 109/147] target-s390: Convert STURA Richard Henderson
` (39 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:43 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
While we're at it, list 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 | 14 ++++++++++++++
target-s390x/translate.c | 18 ++++++++----------
2 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2a04572..24a419c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -680,4 +680,18 @@
C(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 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)
+ /* ??? Not listed in PoO ninth edition, but there's a linux driver that
+ uses it: "A CHSC subchannel is usually present on LPAR only." */
+ C(0xb25f, CHSC, 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 e211a60..334d4ea 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,11 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -1062,11 +1057,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
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);
@@ -2916,6 +2906,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] 152+ messages in thread
* [Qemu-devel] [PATCH 109/147] target-s390: Convert STURA
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (107 preceding siblings ...)
2012-09-28 0:43 ` [Qemu-devel] [PATCH 108/147] target-s390: Convert subchannel instructions Richard Henderson
@ 2012-09-28 0:44 ` Richard Henderson
2012-09-28 0:45 ` [Qemu-devel] [PATCH 110/147] target-s390: Convert CSP Richard Henderson
` (38 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:44 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 | 4 ++--
target-s390x/translate.c | 20 ++++++++------------
4 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0b8e7a9..0a2cd7c 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -109,7 +109,7 @@ 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_2(lra, i64, env, i64)
-DEF_HELPER_3(stura, void, env, i64, i32)
+DEF_HELPER_3(stura, void, env, i64, i64)
#endif
#include "def-helper.h"
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 24a419c..8e457cb 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -678,6 +678,8 @@
C(0xac00, STNSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
C(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
+/* STORE USING REAL ADDRESS */
+ C(0xb246, STURA, RRE, Z, r1_o, r2_o, 0, 0, stura, 0)
/* TEST PROTECTION */
C(0xe501, TPROT, SSE, Z, la1, a2, 0, 0, tprot, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 1a32436..b8e4681 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -1099,9 +1099,9 @@ void HELPER(ptlb)(CPUS390XState *env)
}
/* store using real address */
-void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1)
+void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
{
- stw_phys(get_address(env, 0, 0, addr), v1);
+ stw_phys(get_address(env, 0, 0, addr), (uint32_t)v1);
}
/* load real address */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 334d4ea..f1546a7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x46: /* STURA R1,R2 [RRE] */
- /* Store Using Real Address */
- check_privileged(s);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- tmp32_1 = load_reg32(r1);
- tmp = load_reg(r2);
- potential_page_fault(s);
- gen_helper_stura(cpu_env, tmp, tmp32_1);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
case 0x50: /* CSP R1,R2 [RRE] */
/* Compare And Swap And Purge */
check_privileged(s);
@@ -2945,6 +2933,14 @@ static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
}
return NO_EXIT;
}
+
+static ExitStatus op_stura(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_stura(cpu_env, o->in2, o->in1);
+ return NO_EXIT;
+}
#endif
static ExitStatus op_st8(DisasContext *s, DisasOps *o)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 110/147] target-s390: Convert CSP
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (108 preceding siblings ...)
2012-09-28 0:44 ` [Qemu-devel] [PATCH 109/147] target-s390: Convert STURA Richard Henderson
@ 2012-09-28 0:45 ` Richard Henderson
2012-09-28 0:46 ` [Qemu-devel] [PATCH 111/147] target-s390: Convert STCKE Richard Henderson
` (37 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:45 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 | 6 +++---
target-s390x/translate.c | 24 ++++++++++++------------
4 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0a2cd7c..84a46f5 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -101,7 +101,7 @@ 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_2(rrbe, TCG_CALL_CONST, i32, env, i64)
-DEF_HELPER_3(csp, i32, env, i32, i32)
+DEF_HELPER_3(csp, i32, env, i32, i64)
DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8e457cb..12468a3 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -614,6 +614,8 @@
C(0xf300, UNPK, SS_a, Z, la1, a2, 0, 0, unpk, 0)
#ifndef CONFIG_USER_ONLY
+/* COMPARE AND SWAP AND PURGE */
+ C(0xb250, CSP, RRE, Z, 0, ra2, 0, 0, csp, 0)
/* DIAGNOSE (KVM hypercall) */
C(0x8300, DIAG, RX_a, Z, 0, 0, 0, 0, diag, 0)
/* INSERT STORAGE KEY EXTENDED */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index b8e4681..2d4da45 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -990,16 +990,16 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
}
/* compare and swap and purge */
-uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2)
{
uint32_t cc;
uint32_t o1 = env->regs[r1];
- uint64_t a2 = get_address_31fix(env, r2) & ~3ULL;
+ uint64_t a2 = r2 & ~3ULL;
uint32_t o2 = cpu_ldl_data(env, a2);
if (o1 == o2) {
cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]);
- if (env->regs[r2] & 0x3) {
+ if (r2 & 0x3) {
/* flush TLB / ALB */
tlb_flush(env, 1);
}
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f1546a7..585e739 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x50: /* CSP R1,R2 [RRE] */
- /* Compare And Swap And Purge */
- check_privileged(s);
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- gen_helper_csp(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 0x78: /* STCKE D2(B2) [S] */
/* Store Clock Extended */
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -1901,6 +1889,18 @@ static ExitStatus op_csg(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_csp(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+ check_privileged(s);
+ gen_helper_csp(cc_op, cpu_env, r1, o->in2);
+ tcg_temp_free_i32(r1);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+#endif
+
static ExitStatus op_cds(DisasContext *s, DisasOps *o)
{
int r3 = get_field(s->fields, r3);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 111/147] target-s390: Convert STCKE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (109 preceding siblings ...)
2012-09-28 0:45 ` [Qemu-devel] [PATCH 110/147] target-s390: Convert CSP Richard Henderson
@ 2012-09-28 0:46 ` Richard Henderson
2012-09-28 0:47 ` [Qemu-devel] [PATCH 112/147] target-s390: Convert SACF Richard Henderson
` (36 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:46 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 | 14 --------------
target-s390x/translate.c | 31 ++++++++++++++++++++++---------
4 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 84a46f5..4ba81af 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -87,7 +87,6 @@ DEF_HELPER_4(diag, i64, env, i32, i64, i64)
DEF_HELPER_3(load_psw, void, env, i64, i64)
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_1(stckc, TCG_CALL_CONST, i64, env)
DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 12468a3..75729fe 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -663,6 +663,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 EXTENDED */
+ C(0xb278, STCKE, S, Z, 0, a2, 0, 0, stcke, 0)
/* STORE CLOCK COMPARATOR */
C(0xb207, STCKC, S, Z, la2, 0, new, m1_64, stckc, 0)
/* STORE CONTROL */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 925dc0a..cf4ae62 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -204,20 +204,6 @@ uint64_t HELPER(stck)(CPUS390XState *env)
return clock_value(env);
}
-/* Store Clock Extended */
-uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
-{
- cpu_stb_data(env, a1, 0);
- /* basically the same value as stck */
- cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num);
- /* more fine grained than stck */
- cpu_stq_data(env, a1 + 9, 0);
- /* XXX programmable fields */
- cpu_stw_data(env, a1 + 17, 0);
-
- return 0;
-}
-
/* Set Clock Comparator */
void HELPER(sckc)(CPUS390XState *env, uint64_t time)
{
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 585e739..9b664aa 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x78: /* STCKE D2(B2) [S] */
- /* Store Clock Extended */
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- potential_page_fault(s);
- gen_helper_stcke(cc_op, cpu_env, tmp);
- set_cc_static(s);
- tcg_temp_free_i64(tmp);
- break;
case 0x79: /* SACF D2(B2) [S] */
/* Set Address Space Control Fast */
check_privileged(s);
@@ -2828,6 +2819,28 @@ static ExitStatus op_stck(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 c1 = tcg_temp_new_i64();
+ TCGv_i64 c2 = tcg_temp_new_i64();
+ gen_helper_stck(c1, cpu_env);
+ /* Shift the 64-bit value into its place as a zero-extended
+ 104-bit value. Note that "bit positions 64-103 are always
+ non-zero so that they compare differently to STCK"; we set
+ the least significant bit to 1. */
+ tcg_gen_shli_i64(c2, c1, 56);
+ tcg_gen_shri_i64(c1, c1, 8);
+ tcg_gen_ori_i64(c2, c2, 0x10000);
+ tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
+ tcg_gen_addi_i64(o->in2, o->in2, 8);
+ tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
+ tcg_temp_free_i64(c1);
+ tcg_temp_free_i64(c2);
+ /* ??? We don't implement clock states. */
+ gen_op_movi_cc(s, 0);
+ return NO_EXIT;
+}
+
static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
{
check_privileged(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 112/147] target-s390: Convert SACF
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (110 preceding siblings ...)
2012-09-28 0:46 ` [Qemu-devel] [PATCH 111/147] target-s390: Convert STCKE Richard Henderson
@ 2012-09-28 0:47 ` Richard Henderson
2012-09-28 0:48 ` [Qemu-devel] [PATCH 113/147] target-s390: Convert STSI Richard Henderson
` (35 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:47 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 | 21 ++++++++-------------
2 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 75729fe..a389f15 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -643,6 +643,8 @@
/* 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 ADDRESS SPACE CONTROL FAST */
+ C(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0)
/* SET CLOCK */
/* ??? Not implemented - is it necessary? */
C(0xb204, SCK, S, Z, 0, 0, 0, 0, 0, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9b664aa..b29e2ea 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,19 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x79: /* SACF D2(B2) [S] */
- /* Set Address Space Control Fast */
- 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 = s->next_pc;
- update_psw_addr(s);
- s->is_jmp = DISAS_JUMP;
- break;
case 0x7d: /* STSI D2,(B2) [S] */
check_privileged(s);
decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2681,6 +2668,14 @@ static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
set_cc_static(s);
return NO_EXIT;
}
+
+static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ gen_helper_sacf(cpu_env, o->in2);
+ /* Addressing mode has changed, so end the block. */
+ return EXIT_PC_STALE;
+}
#endif
static ExitStatus op_sar(DisasContext *s, DisasOps *o)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 113/147] target-s390: Convert STSI
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (111 preceding siblings ...)
2012-09-28 0:47 ` [Qemu-devel] [PATCH 112/147] target-s390: Convert SACF Richard Henderson
@ 2012-09-28 0:48 ` Richard Henderson
2012-09-28 0:49 ` [Qemu-devel] [PATCH 114/147] target-s390: Convert STFL Richard Henderson
` (34 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:48 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/misc_helper.c | 4 ++--
target-s390x/translate.c | 24 ++++++++++--------------
4 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 4ba81af..55eaeea 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -91,7 +91,7 @@ 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_1(stpt, TCG_CALL_CONST, i64, env)
-DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
+DEF_HELPER_4(stsi, i32, env, i64, i64, i64)
DEF_HELPER_4(lctl, void, env, i32, i64, i32)
DEF_HELPER_4(lctlg, void, env, i32, i64, i32)
DEF_HELPER_4(stctl, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a389f15..5de3256 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -680,6 +680,8 @@
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 SYSTEM INFORMATION */
+ C(0xb27d, STSI, S, Z, 0, a2, 0, 0, stsi, 0)
/* STORE THEN AND SYSTEM MASK */
C(0xac00, STNSM, SI, Z, la1, 0, 0, 0, stnosm, 0)
/* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index cf4ae62..b24e3d1 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -247,8 +247,8 @@ uint64_t HELPER(stpt)(CPUS390XState *env)
}
/* Store System Information */
-uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint32_t r0,
- uint32_t r1)
+uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
+ uint64_t r0, uint64_t r1)
{
int cc = 0;
int sel1, sel2;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b29e2ea..2bb6ac1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1023,7 +1023,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
{
#ifndef CONFIG_USER_ONLY
TCGv_i64 tmp, tmp2, tmp3;
- TCGv_i32 tmp32_1, tmp32_2;
+ TCGv_i32 tmp32_1;
int r1, r2;
int r3, d2, b2;
@@ -1033,19 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0x7d: /* STSI D2,(B2) [S] */
- check_privileged(s);
- decode_rs(s, insn, &r1, &r3, &b2, &d2);
- tmp = get_address(s, 0, b2, d2);
- tmp32_1 = load_reg32(0);
- tmp32_2 = load_reg32(1);
- potential_page_fault(s);
- gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, 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 0xb1: /* STFL D2(B2) [S] */
/* Store Facility List (CPU features) at 200 */
check_privileged(s);
@@ -2895,6 +2882,15 @@ static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_spx(DisasContext *s, DisasOps *o)
{
check_privileged(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 114/147] target-s390: Convert STFL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (112 preceding siblings ...)
2012-09-28 0:48 ` [Qemu-devel] [PATCH 113/147] target-s390: Convert STSI Richard Henderson
@ 2012-09-28 0:49 ` Richard Henderson
2012-09-28 0:50 ` [Qemu-devel] [PATCH 115/147] target-s390: Convert LPSWE Richard Henderson
` (33 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:49 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 | 23 ++++++++++++++---------
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5de3256..ba070f1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -678,6 +678,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 FACILITY LIST */
+ C(0xb2b1, STFL, S, Z, 0, 0, 0, 0, stfl, 0)
/* STORE PREFIX */
C(0xb211, STPX, S, Z, la2, 0, new, m1_32, stpx, 0)
/* STORE SYSTEM INFORMATION */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2bb6ac1..63d4be6 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0xb1: /* STFL D2(B2) [S] */
- /* Store Facility List (CPU features) at 200 */
- check_privileged(s);
- tmp2 = tcg_const_i64(0xc0000000);
- tmp = tcg_const_i64(200);
- tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp);
- break;
case 0xb2: /* LPSWE D2(B2) [S] */
/* Load PSW Extended */
check_privileged(s);
@@ -2875,6 +2866,20 @@ static ExitStatus op_spt(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 f, a;
+ /* We really ought to have more complete indication of facilities
+ that we implement. Address this when STFLE is implemented. */
+ check_privileged(s);
+ f = tcg_const_i64(0xc0000000);
+ a = tcg_const_i64(200);
+ tcg_gen_qemu_st32(f, a, get_mem_index(s));
+ tcg_temp_free_i64(f);
+ tcg_temp_free_i64(a);
+ return NO_EXIT;
+}
+
static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
{
check_privileged(s);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 115/147] target-s390: Convert LPSWE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (113 preceding siblings ...)
2012-09-28 0:49 ` [Qemu-devel] [PATCH 114/147] target-s390: Convert STFL Richard Henderson
@ 2012-09-28 0:50 ` Richard Henderson
2012-09-28 0:51 ` [Qemu-devel] [PATCH 116/147] target-s390: Convert SERVC Richard Henderson
` (32 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:50 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, 20 insertions(+), 19 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ba070f1..b0cf908 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -627,6 +627,8 @@
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 PSW EXTENDED */
+ C(0xb2b2, LPSWE, S, Z, 0, a2, 0, 0, lpswe, 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)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 63d4be6..61bac81 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1022,10 +1022,9 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
uint32_t insn)
{
#ifndef CONFIG_USER_ONLY
- TCGv_i64 tmp, tmp2, tmp3;
+ TCGv_i64 tmp;
TCGv_i32 tmp32_1;
int r1, r2;
- int r3, d2, b2;
r1 = (insn >> 4) & 0xf;
r2 = insn & 0xf;
@@ -1033,23 +1032,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
switch (op) {
- case 0xb2: /* LPSWE D2(B2) [S] */
- /* Load PSW Extended */
- check_privileged(s);
- 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_ld64(tmp2, tmp, get_mem_index(s));
- tcg_gen_addi_i64(tmp, tmp, 8);
- tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
- gen_helper_load_psw(cpu_env, tmp2, tmp3);
- /* we need to keep cc_op intact */
- s->is_jmp = DISAS_JUMP;
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tmp2);
- tcg_temp_free_i64(tmp3);
- break;
case 0x20: /* SERVC R1,R2 [RRE] */
/* SCLP Service call (PV hypercall) */
check_privileged(s);
@@ -2254,6 +2236,23 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
tcg_temp_free_i64(t2);
return EXIT_NORETURN;
}
+
+static ExitStatus op_lpswe(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 t1, t2;
+
+ check_privileged(s);
+
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+ tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
+ tcg_gen_addi_i64(o->in2, o->in2, 8);
+ tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
+ gen_helper_load_psw(cpu_env, t1, t2);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+ return EXIT_NORETURN;
+}
#endif
static ExitStatus op_lam(DisasContext *s, DisasOps *o)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 116/147] target-s390: Convert SERVC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (114 preceding siblings ...)
2012-09-28 0:50 ` [Qemu-devel] [PATCH 115/147] target-s390: Convert LPSWE Richard Henderson
@ 2012-09-28 0:51 ` Richard Henderson
2012-09-28 0:52 ` [Qemu-devel] [PATCH 117/147] target-s390: Delete dead code from old translator Richard Henderson
` (31 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:51 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/misc_helper.c | 6 ++----
target-s390x/translate.c | 29 +++++++++--------------------
4 files changed, 14 insertions(+), 25 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 55eaeea..71cd9aa 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -82,7 +82,7 @@ DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
i32, env, i32, i64, i64, i64)
#ifndef CONFIG_USER_ONLY
-DEF_HELPER_3(servc, i32, env, i32, i64)
+DEF_HELPER_3(servc, i32, env, i64, i64)
DEF_HELPER_4(diag, i64, env, i32, i64, i64)
DEF_HELPER_3(load_psw, void, env, i64, i64)
DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b0cf908..cd773d0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -641,6 +641,8 @@
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)
+/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
+ C(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 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/misc_helper.c b/target-s390x/misc_helper.c
index b24e3d1..6addc07 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -135,11 +135,9 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
}
/* SCLP service call */
-uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
{
- int r;
-
- r = sclp_service_call(env, r1, r2);
+ int r = sclp_service_call(env, r1, r2);
if (r < 0) {
program_interrupt(env, -r, 4);
return 0;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 61bac81..a4ac079 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1022,27 +1022,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
uint32_t insn)
{
#ifndef CONFIG_USER_ONLY
- TCGv_i64 tmp;
- TCGv_i32 tmp32_1;
- int r1, r2;
-
- r1 = (insn >> 4) & 0xf;
- r2 = insn & 0xf;
-
- LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
-
switch (op) {
- case 0x20: /* SERVC R1,R2 [RRE] */
- /* SCLP Service call (PV hypercall) */
- check_privileged(s);
- potential_page_fault(s);
- tmp32_1 = load_reg32(r2);
- tmp = load_reg(r1);
- gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i64(tmp);
- break;
default:
#endif
LOG_DISAS("illegal b2 operation 0x%x\n", op);
@@ -2701,6 +2681,15 @@ static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
}
#ifndef CONFIG_USER_ONLY
+static ExitStatus op_servc(DisasContext *s, DisasOps *o)
+{
+ check_privileged(s);
+ potential_page_fault(s);
+ gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
+ set_cc_static(s);
+ return NO_EXIT;
+}
+
static ExitStatus op_sigp(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] 152+ messages in thread
* [Qemu-devel] [PATCH 117/147] target-s390: Delete dead code from old translator
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (115 preceding siblings ...)
2012-09-28 0:51 ` [Qemu-devel] [PATCH 116/147] target-s390: Convert SERVC Richard Henderson
@ 2012-09-28 0:52 ` Richard Henderson
2012-09-28 0:53 ` [Qemu-devel] [PATCH 118/147] target-s390: Implement BRANCH ON INDEX Richard Henderson
` (30 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:52 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
The use of inline restricts detection of static functions that are
no longer used. Limit the use of inline to those functions that
are conditionally used based on CONFIG_USER_ONLY.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 318 ++++-------------------------------------------
1 file changed, 27 insertions(+), 291 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a4ac079..f2ac98f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -79,12 +79,7 @@ static uint64_t inline_branch_hit[CC_OP_MAX];
static uint64_t inline_branch_miss[CC_OP_MAX];
#endif
-static inline void debug_insn(uint64_t insn)
-{
- LOG_DISAS("insn: 0x%" PRIx64 "\n", insn);
-}
-
-static inline uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
+static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
{
if (!(s->tb->flags & FLAG_MASK_64)) {
if (s->tb->flags & FLAG_MASK_32) {
@@ -200,112 +195,58 @@ void s390x_translate_init(void)
#include "helper.h"
}
-static inline TCGv_i64 load_reg(int reg)
+static TCGv_i64 load_reg(int reg)
{
TCGv_i64 r = tcg_temp_new_i64();
tcg_gen_mov_i64(r, regs[reg]);
return r;
}
-static inline TCGv_i64 load_freg(int reg)
-{
- TCGv_i64 r = tcg_temp_new_i64();
- tcg_gen_mov_i64(r, fregs[reg]);
- return r;
-}
-
-static inline TCGv_i32 load_freg32(int reg)
-{
- TCGv_i32 r = tcg_temp_new_i32();
-#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;
-}
-
-static inline TCGv_i64 load_freg32_i64(int reg)
+static 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();
- tcg_gen_trunc_i64_i32(r, regs[reg]);
- return r;
-}
-
-static inline TCGv_i64 load_reg32_i64(int reg)
-{
- TCGv_i64 r = tcg_temp_new_i64();
- tcg_gen_ext32s_i64(r, regs[reg]);
- return r;
-}
-
-static inline void store_reg(int reg, TCGv_i64 v)
+static void store_reg(int reg, TCGv_i64 v)
{
tcg_gen_mov_i64(regs[reg], v);
}
-static inline void store_freg(int reg, TCGv_i64 v)
+static void store_freg(int reg, TCGv_i64 v)
{
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
- 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)
+static void store_reg32_i64(int reg, TCGv_i64 v)
{
/* 32 bit register writes keep the upper half */
tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
}
-static inline void store_reg32h_i64(int reg, TCGv_i64 v)
+static void store_reg32h_i64(int reg, TCGv_i64 v)
{
tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
}
-static inline void store_freg32(int reg, TCGv_i32 v)
-{
- /* 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 store_freg32_i64(int reg, TCGv_i64 v)
+static 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)
+static void return_low128(TCGv_i64 dest)
{
tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
}
-static inline void update_psw_addr(DisasContext *s)
+static void update_psw_addr(DisasContext *s)
{
/* psw.addr */
tcg_gen_movi_i64(psw_addr, s->pc);
}
-static inline void potential_page_fault(DisasContext *s)
+static void potential_page_fault(DisasContext *s)
{
#ifndef CONFIG_USER_ONLY
update_psw_addr(s);
@@ -328,7 +269,7 @@ static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc)
return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
}
-static inline int get_mem_index(DisasContext *s)
+static int get_mem_index(DisasContext *s)
{
switch (s->tb->flags & FLAG_MASK_ASC) {
case PSW_ASC_PRIMARY >> 32:
@@ -440,14 +381,6 @@ static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
s->cc_op = op;
}
-static void gen_op_update1_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 dst)
-{
- tcg_gen_discard_i64(cc_src);
- tcg_gen_extu_i32_i64(cc_dst, dst);
- tcg_gen_discard_i64(cc_vr);
- s->cc_op = op;
-}
-
static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
TCGv_i64 dst)
{
@@ -457,15 +390,6 @@ static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
s->cc_op = op;
}
-static void gen_op_update2_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
- TCGv_i32 dst)
-{
- tcg_gen_extu_i32_i64(cc_src, src);
- tcg_gen_extu_i32_i64(cc_dst, dst);
- tcg_gen_discard_i64(cc_vr);
- s->cc_op = op;
-}
-
static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
TCGv_i64 dst, TCGv_i64 vr)
{
@@ -475,104 +399,28 @@ static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
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);
-}
-
-static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
+static 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)
+static 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)
+static 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)
+static 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)
-{
- gen_op_update2_cc_i32(s, cond, v1, v2);
-}
-
-static inline void cmp_64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
- enum cc_op cond)
-{
- gen_op_update2_cc_i64(s, cond, v1, v2);
-}
-
-static inline void cmp_s32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
-{
- cmp_32(s, v1, v2, CC_OP_LTGT_32);
-}
-
-static inline void cmp_u32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
-{
- cmp_32(s, v1, v2, CC_OP_LTUGTU_32);
-}
-
-static inline void cmp_s32c(DisasContext *s, TCGv_i32 v1, int32_t v2)
-{
- /* XXX optimize for the constant? put it in s? */
- TCGv_i32 tmp = tcg_const_i32(v2);
- cmp_32(s, v1, tmp, CC_OP_LTGT_32);
- tcg_temp_free_i32(tmp);
-}
-
-static inline void cmp_u32c(DisasContext *s, TCGv_i32 v1, uint32_t v2)
-{
- TCGv_i32 tmp = tcg_const_i32(v2);
- cmp_32(s, v1, tmp, CC_OP_LTUGTU_32);
- tcg_temp_free_i32(tmp);
-}
-
-static inline void cmp_s64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
-{
- cmp_64(s, v1, v2, CC_OP_LTGT_64);
-}
-
-static inline void cmp_u64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
-{
- cmp_64(s, v1, v2, CC_OP_LTUGTU_64);
-}
-
-static inline void cmp_s64c(DisasContext *s, TCGv_i64 v1, int64_t v2)
-{
- TCGv_i64 tmp = tcg_const_i64(v2);
- cmp_s64(s, v1, tmp);
- tcg_temp_free_i64(tmp);
-}
-
-static inline void cmp_u64c(DisasContext *s, TCGv_i64 v1, uint64_t v2)
-{
- TCGv_i64 tmp = tcg_const_i64(v2);
- cmp_u64(s, v1, tmp);
- tcg_temp_free_i64(tmp);
-}
-
-static inline void set_cc_s32(DisasContext *s, TCGv_i32 val)
-{
- gen_op_update1_cc_i32(s, CC_OP_LTGT0_32, val);
-}
-
-static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
-{
- gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
-}
-
/* CC value is in env->cc_op */
-static inline void set_cc_static(DisasContext *s)
+static void set_cc_static(DisasContext *s)
{
tcg_gen_discard_i64(cc_src);
tcg_gen_discard_i64(cc_dst);
@@ -580,14 +428,14 @@ static inline void set_cc_static(DisasContext *s)
s->cc_op = CC_OP_STATIC;
}
-static inline void gen_op_set_cc_op(DisasContext *s)
+static void gen_op_set_cc_op(DisasContext *s)
{
if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
tcg_gen_movi_i32(cc_op, s->cc_op);
}
}
-static inline void gen_update_cc_op(DisasContext *s)
+static void gen_update_cc_op(DisasContext *s)
{
gen_op_set_cc_op(s);
}
@@ -667,51 +515,6 @@ static void gen_op_calc_cc(DisasContext *s)
set_cc_static(s);
}
-static inline void decode_rr(DisasContext *s, uint64_t insn, int *r1, int *r2)
-{
- debug_insn(insn);
-
- *r1 = (insn >> 4) & 0xf;
- *r2 = insn & 0xf;
-}
-
-static inline TCGv_i64 decode_rx(DisasContext *s, uint64_t insn, int *r1,
- int *x2, int *b2, int *d2)
-{
- debug_insn(insn);
-
- *r1 = (insn >> 20) & 0xf;
- *x2 = (insn >> 16) & 0xf;
- *b2 = (insn >> 12) & 0xf;
- *d2 = insn & 0xfff;
-
- return get_address(s, *x2, *b2, *d2);
-}
-
-static inline void decode_rs(DisasContext *s, uint64_t insn, int *r1, int *r3,
- int *b2, int *d2)
-{
- debug_insn(insn);
-
- *r1 = (insn >> 20) & 0xf;
- /* aka m3 */
- *r3 = (insn >> 16) & 0xf;
- *b2 = (insn >> 12) & 0xf;
- *d2 = insn & 0xfff;
-}
-
-static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
- int *b1, int *d1)
-{
- debug_insn(insn);
-
- *i2 = (insn >> 16) & 0xff;
- *b1 = (insn >> 12) & 0xf;
- *d1 = insn & 0xfff;
-
- return get_address(s, 0, *b1, *d1);
-}
-
static int use_goto_tb(DisasContext *s, uint64_t dest)
{
/* NOTE: we handle the case where the TB spans two pages here */
@@ -721,29 +524,14 @@ static int use_goto_tb(DisasContext *s, uint64_t dest)
&& !(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);
-
- 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)s->tb + tb_num);
- } else {
- /* jump to another page: currently not optimized */
- tcg_gen_movi_i64(psw_addr, pc);
- tcg_gen_exit_tb(0);
- }
-}
-
-static inline void account_noninline_branch(DisasContext *s, int cc_op)
+static void account_noninline_branch(DisasContext *s, int cc_op)
{
#ifdef DEBUG_INLINE_BRANCHES
inline_branch_miss[cc_op]++;
#endif
}
-static inline void account_inline_branch(DisasContext *s, int cc_op)
+static void account_inline_branch(DisasContext *s, int cc_op)
{
#ifdef DEBUG_INLINE_BRANCHES
inline_branch_hit[cc_op]++;
@@ -1018,43 +806,6 @@ static void free_compare(DisasCompare *c)
}
}
-static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
- uint32_t insn)
-{
-#ifndef CONFIG_USER_ONLY
- switch (op) {
- 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(CPUS390XState *env, DisasContext *s)
-{
- unsigned char opc;
- uint64_t insn;
- int op;
-
- opc = cpu_ldub_code(env, s->pc);
- LOG_DISAS("opc 0x%x\n", opc);
-
- switch (opc) {
- case 0xb2:
- insn = ld_code4(env, s->pc);
- op = (insn >> 16) & 0xff;
- disas_b2(env, s, op, insn);
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
- gen_illegal_opcode(s);
- break;
- }
-}
-
/* ====================================================================== */
/* Define the insn format enumeration. */
#define F0(N) FMT_##N,
@@ -4108,30 +3859,15 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
DisasFields f;
DisasOps o;
+ /* Search for the insn in the table. */
insn = extract_insn(env, s, &f);
- /* If not found, try the old interpreter. This includes ILLOPC. */
+ /* Not found means unimplemented/illegal opcode. */
if (insn == NULL) {
- disas_s390_insn(env, 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;
+ qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
+ f.op, f.op2);
+ gen_illegal_opcode(s);
+ return EXIT_NORETURN;
}
/* Set up the strutures we use to communicate with the helpers. */
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 118/147] target-s390: Implement BRANCH ON INDEX
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (116 preceding siblings ...)
2012-09-28 0:52 ` [Qemu-devel] [PATCH 117/147] target-s390: Delete dead code from old translator Richard Henderson
@ 2012-09-28 0:53 ` Richard Henderson
2012-09-28 0:55 ` [Qemu-devel] [PATCH 119/147] target-s390: Tidy s->op_cc handling Richard Henderson
` (29 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:53 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 10 +++++++++
target-s390x/translate.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index cd773d0..8b89ce6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -90,6 +90,16 @@
/* 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)
+/* BRANCH ON INDEX */
+ D(0x8600, BXH, RS_a, Z, 0, a2, 0, 0, bx32, 0, 0)
+ D(0x8700, BXLE, RS_a, Z, 0, a2, 0, 0, bx32, 0, 1)
+ D(0xeb44, BXHG, RSY_a, Z, 0, a2, 0, 0, bx64, 0, 0)
+ D(0xeb45, BXLEG, RSY_a, Z, 0, a2, 0, 0, bx64, 0, 1)
+/* BRANCH RELATIVE ON INDEX */
+ D(0x8400, BRXH, RSI, Z, 0, 0, 0, 0, bx32, 0, 0)
+ D(0x8500, BRXLE, RSI, Z, 0, 0, 0, 0, bx32, 0, 1)
+ D(0xec44, BRXHG, RIE_e, Z, 0, 0, 0, 0, bx64, 0, 0)
+ D(0xec45, BRXHLE, RIE_e, Z, 0, 0, 0, 0, bx64, 0, 1)
/* CHECKSUM */
C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f2ac98f..74f14bc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1355,6 +1355,58 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_bx32(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ 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 = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
+ c.is_64 = false;
+ c.g1 = false;
+ c.g2 = false;
+
+ t = tcg_temp_new_i64();
+ tcg_gen_add_i64(t, regs[r1], regs[r3]);
+ c.u.s32.a = tcg_temp_new_i32();
+ c.u.s32.b = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(c.u.s32.a, t);
+ tcg_gen_trunc_i64_i32(c.u.s32.b, regs[r3 | 1]);
+ store_reg32_i64(r1, t);
+ tcg_temp_free_i64(t);
+
+ return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
+static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
+{
+ int r1 = get_field(s->fields, r1);
+ int r3 = get_field(s->fields, r3);
+ bool is_imm = have_field(s->fields, i2);
+ int imm = is_imm ? get_field(s->fields, i2) : 0;
+ DisasCompare c;
+
+ c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
+ c.is_64 = true;
+
+ if (r1 == (r3 | 1)) {
+ c.u.s64.b = load_reg(r3 | 1);
+ c.g2 = false;
+ } else {
+ c.u.s64.b = regs[r3 | 1];
+ c.g2 = true;
+ }
+
+ tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
+ c.u.s64.a = regs[r1];
+ c.g1 = true;
+
+ 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);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 119/147] target-s390: Tidy s->op_cc handling
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (117 preceding siblings ...)
2012-09-28 0:53 ` [Qemu-devel] [PATCH 118/147] target-s390: Implement BRANCH ON INDEX Richard Henderson
@ 2012-09-28 0:55 ` Richard Henderson
2012-09-28 0:56 ` [Qemu-devel] [PATCH 120/147] target-s390: Implement COMPARE AND BRANCH Richard Henderson
` (28 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:55 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
There's no need to force computation of the true cc_op when taking an
exception or single stepping. In either case we'll enter the next TB
with s->cc_op = DYNAMIC and recompute anyway. Just make sure that
s->cc_op is stored back to env->cc_op as needed.
Delete some dead functions, avoid allocating unused TCG temps, drop
the old s->is_jmp setting.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 95 ++++++++++++++++++++++++++++--------------------
1 file changed, 55 insertions(+), 40 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 74f14bc..fdb31cd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -55,7 +55,6 @@ struct DisasContext {
uint64_t pc, next_pc;
enum cc_op cc_op;
bool singlestep_enabled;
- int is_jmp;
};
/* Information carried about a condition to be evaluated. */
@@ -72,8 +71,6 @@ typedef struct {
#define DISAS_EXCP 4
-static void gen_op_calc_cc(DisasContext *s);
-
#ifdef DEBUG_INLINE_BRANCHES
static uint64_t inline_branch_hit[CC_OP_MAX];
static uint64_t inline_branch_miss[CC_OP_MAX];
@@ -246,12 +243,17 @@ static void update_psw_addr(DisasContext *s)
tcg_gen_movi_i64(psw_addr, s->pc);
}
+static void update_cc_op(DisasContext *s)
+{
+ if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
+ tcg_gen_movi_i32(cc_op, s->cc_op);
+ }
+}
+
static void potential_page_fault(DisasContext *s)
{
-#ifndef CONFIG_USER_ONLY
update_psw_addr(s);
- gen_op_calc_cc(s);
-#endif
+ update_cc_op(s);
}
static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
@@ -309,13 +311,10 @@ static void gen_program_exception(DisasContext *s, int code)
update_psw_addr(s);
/* Save off cc. */
- gen_op_calc_cc(s);
+ update_cc_op(s);
/* Trigger exception. */
gen_exception(EXCP_PGM);
-
- /* End TB here. */
- s->is_jmp = DISAS_EXCP;
}
static inline void gen_illegal_opcode(DisasContext *s)
@@ -428,23 +427,40 @@ static void set_cc_static(DisasContext *s)
s->cc_op = CC_OP_STATIC;
}
-static void gen_op_set_cc_op(DisasContext *s)
-{
- if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
- tcg_gen_movi_i32(cc_op, s->cc_op);
- }
-}
-
-static void gen_update_cc_op(DisasContext *s)
-{
- gen_op_set_cc_op(s);
-}
-
/* calculates cc into cc_op */
static void gen_op_calc_cc(DisasContext *s)
{
- TCGv_i32 local_cc_op = tcg_const_i32(s->cc_op);
- TCGv_i64 dummy = tcg_const_i64(0);
+ TCGv_i32 local_cc_op;
+ TCGv_i64 dummy;
+
+ TCGV_UNUSED_I32(local_cc_op);
+ TCGV_UNUSED_I64(dummy);
+ switch (s->cc_op) {
+ default:
+ dummy = tcg_const_i64(0);
+ /* FALLTHRU */
+ 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:
+ local_cc_op = tcg_const_i32(s->cc_op);
+ break;
+ case CC_OP_CONST0:
+ case CC_OP_CONST1:
+ case CC_OP_CONST2:
+ case CC_OP_CONST3:
+ case CC_OP_STATIC:
+ case CC_OP_DYNAMIC:
+ break;
+ }
switch (s->cc_op) {
case CC_OP_CONST0:
@@ -508,8 +524,12 @@ static void gen_op_calc_cc(DisasContext *s)
tcg_abort();
}
- tcg_temp_free_i32(local_cc_op);
- tcg_temp_free_i64(dummy);
+ if (!TCGV_IS_UNUSED_I32(local_cc_op)) {
+ tcg_temp_free_i32(local_cc_op);
+ }
+ if (!TCGV_IS_UNUSED_I64(dummy)) {
+ tcg_temp_free_i64(dummy);
+ }
/* We now have cc in cc_op as constant */
set_cc_static(s);
@@ -1054,7 +1074,7 @@ static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
return NO_EXIT;
}
if (use_goto_tb(s, dest)) {
- gen_update_cc_op(s);
+ 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);
@@ -1103,7 +1123,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
if (use_goto_tb(s, s->next_pc)) {
if (is_imm && use_goto_tb(s, dest)) {
/* Both exits can use goto_tb. */
- gen_update_cc_op(s);
+ update_cc_op(s);
lab = gen_new_label();
if (c->is_64) {
@@ -1141,7 +1161,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
}
/* Branch not taken. */
- gen_update_cc_op(s);
+ update_cc_op(s);
tcg_gen_goto_tb(0);
tcg_gen_movi_i64(psw_addr, s->next_pc);
tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
@@ -1749,7 +1769,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
TCGv_i64 tmp;
update_psw_addr(s);
- gen_op_calc_cc(s);
+ update_cc_op(s);
tmp = tcg_const_i64(s->next_pc);
gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
@@ -2913,7 +2933,7 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
TCGv_i32 t;
update_psw_addr(s);
- gen_op_calc_cc(s);
+ update_cc_op(s);
t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
@@ -3999,7 +4019,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
dc.pc = pc_start;
dc.cc_op = CC_OP_DYNAMIC;
do_debug = dc.singlestep_enabled = env->singlestep_enabled;
- dc.is_jmp = DISAS_NEXT;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
@@ -4073,17 +4092,13 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
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);
- }
+ /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
+ cc op type is in env */
+ update_cc_op(&dc);
+ /* Exit the TB, either by raising a debug exception or by return. */
if (do_debug) {
gen_exception(EXCP_DEBUG);
} else {
- /* Generate the return instruction */
tcg_gen_exit_tb(0);
}
break;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 120/147] target-s390: Implement COMPARE AND BRANCH
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (118 preceding siblings ...)
2012-09-28 0:55 ` [Qemu-devel] [PATCH 119/147] target-s390: Tidy s->op_cc handling Richard Henderson
@ 2012-09-28 0:56 ` Richard Henderson
2012-09-28 0:57 ` [Qemu-devel] [PATCH 121/147] target-s390: Implement RISBG Richard Henderson
` (27 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:56 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 19 +++++++++++++++++++
target-s390x/translate.c | 28 ++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8b89ce6..4478d1c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -166,6 +166,25 @@
/* COMPARE LOGICAL STRING */
C(0xb25d, CLST, RRE, Z, r1_o, r2_o, 0, 0, clst, 0)
+/* COMPARE AND BRANCH */
+ D(0xecf6, CRB, RRS, GIE, r1_32s, r2_32s, 0, 0, cj, 0, 0)
+ D(0xece4, CGRB, RRS, GIE, r1_o, r2_o, 0, 0, cj, 0, 0)
+ D(0xec76, CRJ, RIE_b, GIE, r1_32s, r2_32s, 0, 0, cj, 0, 0)
+ D(0xec64, CGRJ, RIE_b, GIE, r1_o, r2_o, 0, 0, cj, 0, 0)
+ D(0xecfe, CIB, RIS, GIE, r1_32s, i2, 0, 0, cj, 0, 0)
+ D(0xecfc, CGIB, RIS, GIE, r1_o, i2, 0, 0, cj, 0, 0)
+ D(0xec7e, CIJ, RIE_c, GIE, r1_32s, i2, 0, 0, cj, 0, 0)
+ D(0xec7c, CGIJ, RIE_c, GIE, r1_o, i2, 0, 0, cj, 0, 0)
+/* COMPARE LOGICAL AND BRANCH */
+ D(0xecf7, CLRB, RRS, GIE, r1_32u, r2_32u, 0, 0, cj, 0, 1)
+ D(0xece5, CLGRB, RRS, GIE, r1_o, r2_o, 0, 0, cj, 0, 1)
+ D(0xec77, CLRJ, RIE_b, GIE, r1_32u, r2_32u, 0, 0, cj, 0, 1)
+ D(0xec65, CLGRJ, RIE_b, GIE, r1_o, r2_o, 0, 0, cj, 0, 1)
+ D(0xecff, CLIB, RIS, GIE, r1_32u, i2_8u, 0, 0, cj, 0, 1)
+ D(0xecfd, CLGIB, RIS, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
+ D(0xec7f, CLIJ, RIE_c, GIE, r1_32u, i2_8u, 0, 0, cj, 0, 1)
+ D(0xec7d, CLGIJ, RIE_c, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
+
/* 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)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index fdb31cd..1130902 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1427,6 +1427,34 @@ static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
+static ExitStatus op_cj(DisasContext *s, DisasOps *o)
+{
+ int imm, m3 = get_field(s->fields, m3);
+ bool is_imm;
+ DisasCompare c;
+
+ /* Bit 3 of the m3 field is reserved and should be zero.
+ Choose to ignore it wrt the ltgt_cond table above. */
+ c.cond = ltgt_cond[m3 & 14];
+ if (s->insn->data) {
+ c.cond = tcg_unsigned_cond(c.cond);
+ }
+ c.is_64 = c.g1 = c.g2 = true;
+ c.u.s64.a = o->in1;
+ c.u.s64.b = o->in2;
+
+ is_imm = have_field(s->fields, i4);
+ if (is_imm) {
+ imm = get_field(s->fields, i4);
+ } else {
+ imm = 0;
+ o->out = get_address(s, 0, get_field(s->fields, b4),
+ get_field(s->fields, d4));
+ }
+
+ return help_branch(s, &c, is_imm, imm, o->out);
+}
+
static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
{
gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 121/147] target-s390: Implement RISBG
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (119 preceding siblings ...)
2012-09-28 0:56 ` [Qemu-devel] [PATCH 120/147] target-s390: Implement COMPARE AND BRANCH Richard Henderson
@ 2012-09-28 0:57 ` Richard Henderson
2012-09-28 0:58 ` [Qemu-devel] [PATCH 122/147] target-s390: Implement LDGR, LGDR Richard Henderson
` (26 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:57 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 | 83 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4478d1c..c80a386 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -500,6 +500,11 @@
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)
+/* ROTATE THEN INSERT SELECTED BITS */
+ C(0xec55, RISBG, RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
+ C(0xec5d, RISBHG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+ C(0xec51, RISBLG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+
/* SEARCH STRING */
C(0xb25e, SRST, RRE, Z, r1_o, r2_o, 0, 0, srst, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1130902..3fa0213 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2429,6 +2429,89 @@ static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
}
#endif
+static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
+{
+ int i3 = get_field(s->fields, i3);
+ int i4 = get_field(s->fields, i4);
+ int i5 = get_field(s->fields, i5);
+ int do_zero = i4 & 0x80;
+ uint64_t mask, imask, pmask;
+ int pos, len, rot;
+
+ /* Adjust the arguments for the specific insn. */
+ switch (s->fields->op2) {
+ case 0x55: /* risbg */
+ i3 &= 63;
+ i4 &= 63;
+ pmask = ~0;
+ break;
+ case 0x5d: /* risbhg */
+ i3 &= 31;
+ i4 &= 31;
+ pmask = 0xffffffff00000000ull;
+ break;
+ case 0x51: /* risblg */
+ i3 &= 31;
+ i4 &= 31;
+ pmask = 0x00000000ffffffffull;
+ break;
+ default:
+ abort();
+ }
+
+ /* MASK is the set of bits to be inserted from R2.
+ Take care for I3/I4 wraparound. */
+ mask = pmask >> i3;
+ if (i3 <= i4) {
+ mask ^= pmask >> i4 >> 1;
+ } else {
+ mask |= ~(pmask >> i4 >> 1);
+ }
+ mask &= pmask;
+
+ /* IMASK is the set of bits to be kept from R1. In the case of the high/low
+ insns, we need to keep the other half of the register. */
+ imask = ~mask | ~pmask;
+ if (do_zero) {
+ if (s->fields->op2 == 0x55) {
+ imask = 0;
+ } else {
+ imask = ~pmask;
+ }
+ }
+
+ /* In some cases we can implement this with deposit, which can be more
+ efficient on some hosts. */
+ if (~mask == imask && i3 <= i4) {
+ if (s->fields->op2 == 0x5d) {
+ i3 += 32, i4 += 32;
+ }
+ /* Note that we rotate the bits to be inserted to the lsb, not to
+ the position as described in the PoO. */
+ len = i4 - i3 + 1;
+ pos = 63 - i4;
+ rot = (i5 - pos) & 63;
+ } else {
+ pos = len = -1;
+ rot = i5 & 63;
+ }
+
+ /* Rotate the input as necessary. */
+ tcg_gen_rotli_i64(o->in2, o->in2, rot);
+
+ /* Insert the selected bits into the output. */
+ if (pos >= 0) {
+ tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
+ } else if (imask == 0) {
+ tcg_gen_andi_i64(o->out, o->in2, mask);
+ } else {
+ tcg_gen_andi_i64(o->in2, o->in2, mask);
+ tcg_gen_andi_i64(o->out, o->out, imask);
+ tcg_gen_or_i64(o->out, o->out, o->in2);
+ }
+ return NO_EXIT;
+}
+
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] 152+ messages in thread
* [Qemu-devel] [PATCH 122/147] target-s390: Implement LDGR, LGDR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (120 preceding siblings ...)
2012-09-28 0:57 ` [Qemu-devel] [PATCH 121/147] target-s390: Implement RISBG Richard Henderson
@ 2012-09-28 0:58 ` Richard Henderson
2012-09-28 0:59 ` [Qemu-devel] [PATCH 123/147] target-s390: Implement R[NOX]SBG Richard Henderson
` (25 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:58 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c80a386..8bcfb2b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -364,6 +364,10 @@
/* 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 FPR FROM GR */
+ C(0xb3c1, LDGR, RRE, FPRGR, 0, r2_o, 0, f1, mov2, 0)
+/* LOAD GR FROM FPR */
+ C(0xb3cd, LGDR, RRE, FPRGR, 0, f2_o, 0, r1, mov2, 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)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 123/147] target-s390: Implement R[NOX]SBG
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (121 preceding siblings ...)
2012-09-28 0:58 ` [Qemu-devel] [PATCH 122/147] target-s390: Implement LDGR, LGDR Richard Henderson
@ 2012-09-28 0:59 ` Richard Henderson
2012-09-28 1:00 ` [Qemu-devel] [PATCH 124/147] target-s390: Implement PREFETCH Richard Henderson
` (24 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 0:59 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 | 53 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8bcfb2b..9582f0c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -508,6 +508,10 @@
C(0xec55, RISBG, RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
C(0xec5d, RISBHG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
C(0xec51, RISBLG, RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+/* ROTATE_THEN <OP> SELECTED BITS */
+ C(0xec54, RNSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
+ C(0xec56, ROSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
+ C(0xec57, RXSBG, RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
/* SEARCH STRING */
C(0xb25e, SRST, RRE, Z, r1_o, r2_o, 0, 0, srst, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3fa0213..4489126 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2512,6 +2512,59 @@ static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
+{
+ int i3 = get_field(s->fields, i3);
+ int i4 = get_field(s->fields, i4);
+ int i5 = get_field(s->fields, i5);
+ uint64_t mask;
+
+ /* If this is a test-only form, arrange to discard the result. */
+ if (i3 & 0x80) {
+ o->out = tcg_temp_new_i64();
+ o->g_out = false;
+ }
+
+ i3 &= 63;
+ i4 &= 63;
+ i5 &= 63;
+
+ /* MASK is the set of bits to be operated on from R2.
+ Take care for I3/I4 wraparound. */
+ mask = ~0ull >> i3;
+ if (i3 <= i4) {
+ mask ^= ~0ull >> i4 >> 1;
+ } else {
+ mask |= ~(~0ull >> i4 >> 1);
+ }
+
+ /* Rotate the input as necessary. */
+ tcg_gen_rotli_i64(o->in2, o->in2, i5);
+
+ /* Operate. */
+ switch (s->fields->op2) {
+ case 0x55: /* AND */
+ tcg_gen_ori_i64(o->in2, o->in2, ~mask);
+ tcg_gen_and_i64(o->out, o->out, o->in2);
+ break;
+ case 0x56: /* OR */
+ tcg_gen_andi_i64(o->in2, o->in2, mask);
+ tcg_gen_or_i64(o->out, o->out, o->in2);
+ break;
+ case 0x57: /* XOR */
+ tcg_gen_andi_i64(o->in2, o->in2, mask);
+ tcg_gen_xor_i64(o->out, o->out, o->in2);
+ break;
+ default:
+ abort();
+ }
+
+ /* Set the CC. */
+ tcg_gen_andi_i64(cc_dst, o->out, mask);
+ set_cc_nz_u64(s, cc_dst);
+ return NO_EXIT;
+}
+
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] 152+ messages in thread
* [Qemu-devel] [PATCH 124/147] target-s390: Implement PREFETCH
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (122 preceding siblings ...)
2012-09-28 0:59 ` [Qemu-devel] [PATCH 123/147] target-s390: Implement R[NOX]SBG Richard Henderson
@ 2012-09-28 1:00 ` Richard Henderson
2012-09-28 1:01 ` [Qemu-devel] [PATCH 125/147] target-s390: Implement COMPARE RELATIVE LONG Richard Henderson
` (23 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:00 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9582f0c..eb88c55 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -500,6 +500,11 @@
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)
+/* PREFETCH */
+ /* Implemented as nops of course. */
+ C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0)
+ C(0xc602, PFDRL, RIL_c, GIE, 0, 0, 0, 0, 0, 0)
+
/* 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)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 125/147] target-s390: Implement COMPARE RELATIVE LONG
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (123 preceding siblings ...)
2012-09-28 1:00 ` [Qemu-devel] [PATCH 124/147] target-s390: Implement PREFETCH Richard Henderson
@ 2012-09-28 1:01 ` Richard Henderson
2012-09-28 1:02 ` [Qemu-devel] [PATCH 126/147] target-s390: Implement COMPARE AND TRAP Richard Henderson
` (22 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:01 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index eb88c55..5c19aef 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -120,6 +120,10 @@
/* 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 RELATIVE LONG */
+ C(0xc60d, CRL, RIL_b, GIE, r1, mri2_32s, 0, 0, 0, cmps32)
+ C(0xc608, CGRL, RIL_b, GIE, r1, mri2_64, 0, 0, 0, cmps64)
+ C(0xc60c, CGFRL, RIL_b, GIE, r1, mri2_32s, 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)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 126/147] target-s390: Implement COMPARE AND TRAP
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (124 preceding siblings ...)
2012-09-28 1:01 ` [Qemu-devel] [PATCH 125/147] target-s390: Implement COMPARE RELATIVE LONG Richard Henderson
@ 2012-09-28 1:02 ` Richard Henderson
2012-09-28 1:03 ` [Qemu-devel] [PATCH 127/147] target-s390: Implement LOAD ON CONDITION Richard Henderson
` (21 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:02 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 | 29 +++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5c19aef..b739d70 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -198,6 +198,17 @@
C(0xeb31, CDSY, RSY_a, LD, r1_D32, a2, new, r1_D32, cds, 0)
C(0xeb3e, CDSG, RSY_a, Z, 0, a2, 0, 0, cdsg, 0)
+/* COMPARE AND TRAP */
+ D(0xb972, CRT, RRF_c, GIE, r1_32s, r2_32s, 0, 0, ct, 0, 0)
+ D(0xb960, CGRT, RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 0)
+ D(0xec72, CIT, RIE_a, GIE, r1_32s, i2, 0, 0, ct, 0, 0)
+ D(0xec70, CGIT, RIE_a, GIE, r1_o, i2, 0, 0, ct, 0, 0)
+/* COMPARE LOGICAL AND TRAP */
+ D(0xb973, CLRT, RRF_c, GIE, r1_32u, r2_32u, 0, 0, ct, 0, 1)
+ D(0xb961, CLGRT, RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 1)
+ D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_32u, 0, 0, ct, 0, 1)
+ D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_32u, 0, 0, ct, 0, 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/translate.c b/target-s390x/translate.c
index 4489126..0c9df96 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1705,6 +1705,35 @@ static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_ct(DisasContext *s, DisasOps *o)
+{
+ int m3 = get_field(s->fields, m3);
+ int lab = gen_new_label();
+ TCGv_i32 t;
+ TCGCond c;
+
+ /* Bit 3 of the m3 field is reserved and should be zero.
+ Choose to ignore it wrt the ltgt_cond table above. */
+ c = tcg_invert_cond(ltgt_cond[m3 & 14]);
+ if (s->insn->data) {
+ c = tcg_unsigned_cond(c);
+ }
+ tcg_gen_brcond_i64(c, o->in1, o->in2, lab);
+
+ /* Set DXC to 0xff. */
+ t = tcg_temp_new_i32();
+ tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
+ tcg_gen_ori_i32(t, t, 0xff00);
+ tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
+ tcg_temp_free_i32(t);
+
+ /* Trap. */
+ gen_program_exception(s, PGM_DATA);
+
+ gen_set_label(lab);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_diag(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 127/147] target-s390: Implement LOAD ON CONDITION
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (125 preceding siblings ...)
2012-09-28 1:02 ` [Qemu-devel] [PATCH 126/147] target-s390: Implement COMPARE AND TRAP Richard Henderson
@ 2012-09-28 1:03 ` Richard Henderson
2012-09-28 1:04 ` [Qemu-devel] [PATCH 128/147] target-s390: Implement STORE " Richard Henderson
` (20 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:03 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 | 30 ++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b739d70..91ee055 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -390,6 +390,11 @@
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 ON CONDITION */
+ C(0xb9f2, LOCR, RRF_c, LOC, r1, r2, new, r1_32, loc, 0)
+ C(0xb9e2, LOCGR, RRF_c, LOC, r1, r2, r1, 0, loc, 0)
+ C(0xebf2, LOC, RSY_b, LOC, r1, m2_32u, new, r1_32, loc, 0)
+ C(0xebe2, LOCG, RSY_b, LOC, r1, m2_64, r1, 0, loc, 0)
/* 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)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0c9df96..130b88e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2045,6 +2045,36 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_loc(DisasContext *s, DisasOps *o)
+{
+ DisasCompare c;
+
+ disas_jcc(s, &c, get_field(s->fields, m3));
+
+ if (c.is_64) {
+ tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
+ o->in2, o->in1);
+ free_compare(&c);
+ } else {
+ TCGv_i32 t32 = tcg_temp_new_i32();
+ TCGv_i64 t, z;
+
+ tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
+ free_compare(&c);
+
+ t = tcg_temp_new_i64();
+ tcg_gen_extu_i32_i64(t, t32);
+ tcg_temp_free_i32(t32);
+
+ z = tcg_const_i64(0);
+ tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
+ tcg_temp_free_i64(t);
+ tcg_temp_free_i64(z);
+ }
+
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 128/147] target-s390: Implement STORE ON CONDITION
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (126 preceding siblings ...)
2012-09-28 1:03 ` [Qemu-devel] [PATCH 127/147] target-s390: Implement LOAD ON CONDITION Richard Henderson
@ 2012-09-28 1:04 ` Richard Henderson
2012-09-28 1:05 ` [Qemu-devel] [PATCH 129/147] target-s390: Implement CONVERT TO LOGICAL Richard Henderson
` (19 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1: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 | 29 +++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 91ee055..00b95b6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -601,6 +601,9 @@
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 ON CONDITION */
+ D(0xebf3, STOC, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 0)
+ D(0xebe3, STOCG, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 1)
/* 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)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 130b88e..a0590f0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2747,6 +2747,35 @@ static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
}
#endif
+static ExitStatus op_soc(DisasContext *s, DisasOps *o)
+{
+ DisasCompare c;
+ TCGv_i64 a;
+ int lab, r1;
+
+ disas_jcc(s, &c, get_field(s->fields, m3));
+
+ 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);
+ }
+ free_compare(&c);
+
+ r1 = get_field(s->fields, r1);
+ a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
+ if (s->insn->data) {
+ tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
+ } else {
+ tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
+ }
+ tcg_temp_free_i64(a);
+
+ gen_set_label(lab);
+ return NO_EXIT;
+}
+
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] 152+ messages in thread
* [Qemu-devel] [PATCH 129/147] target-s390: Implement CONVERT TO LOGICAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (127 preceding siblings ...)
2012-09-28 1:04 ` [Qemu-devel] [PATCH 128/147] target-s390: Implement STORE " Richard Henderson
@ 2012-09-28 1:05 ` Richard Henderson
2012-09-28 1:06 ` [Qemu-devel] [PATCH 130/147] target-s390: Implement CONVERT FROM LOGICAL Richard Henderson
` (18 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
target-s390x/helper.h | 6 +++++
target-s390x/insn-data.def | 7 +++++
target-s390x/translate.c | 54 +++++++++++++++++++++++++++++++++++++
4 files changed, 133 insertions(+)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index e40e531..1d5cd39 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -457,6 +457,72 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
return ret;
}
+/* convert 32-bit float to 64-bit uint */
+uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ uint64_t ret;
+ v2 = float32_to_float64(v2, &env->fpu_status);
+ ret = float64_to_uint64(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 uint */
+uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ uint64_t ret = float64_to_uint64(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 uint */
+uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float128 v2 = make_float128(h, l);
+ /* ??? Not 100% correct. */
+ uint64_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 uint */
+uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ uint32_t ret = float32_to_uint32(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 uint */
+uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ uint32_t ret = float64_to_uint32(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 uint */
+uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float128 v2 = make_float128(h, l);
+ /* Not 100% correct. */
+ uint32_t ret = float128_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
/* 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 71cd9aa..db606e8 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -61,6 +61,12 @@ 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_3(clgeb, i64, env, i64, i32)
+DEF_HELPER_3(clgdb, i64, env, i64, i32)
+DEF_HELPER_4(clgxb, i64, env, i64, i64, i32)
+DEF_HELPER_3(clfeb, i64, env, i64, i32)
+DEF_HELPER_3(clfdb, i64, env, i64, i32)
+DEF_HELPER_4(clfxb, 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 00b95b6..a67fdcc 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -226,6 +226,13 @@
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)
+/* CONVERT TO LOGICAL */
+ C(0xb39c, CLFEBR, RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0)
+ C(0xb39d, CLFDBR, RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0)
+ C(0xb39e, CLFXBR, RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0)
+ C(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0)
+ C(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0)
+ C(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0)
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a0590f0..0161bd0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1530,6 +1530,60 @@ static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_clfeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_clfeb(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_clfdb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_clfdb(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_clfxb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_clfxb(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_clgeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_clgeb(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_clgdb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_clgdb(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_clgxb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_clgxb(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_cegb(DisasContext *s, DisasOps *o)
{
TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 130/147] target-s390: Implement CONVERT FROM LOGICAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (128 preceding siblings ...)
2012-09-28 1:05 ` [Qemu-devel] [PATCH 129/147] target-s390: Implement CONVERT TO LOGICAL Richard Henderson
@ 2012-09-28 1:06 ` Richard Henderson
2012-09-28 1:07 ` [Qemu-devel] [PATCH 131/147] target-s390: Implement POPCNT Richard Henderson
` (17 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 31 +++++++++++++++++++++++++++++++
target-s390x/helper.h | 3 +++
target-s390x/insn-data.def | 7 +++++++
target-s390x/translate.c | 25 +++++++++++++++++++++++++
4 files changed, 66 insertions(+)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 1d5cd39..2983360 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -395,6 +395,37 @@ uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
return RET128(ret);
}
+/* convert 64-bit uint to 32-bit float */
+uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float32 ret = uint64_to_float32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* convert 64-bit uint to 64-bit float */
+uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ float64 ret = uint64_to_float64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
+}
+
+/* convert 64-bit uint to 128-bit float */
+uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+ int hold = swap_round_mode(env, m3);
+ /* ??? Not 50% correct. */
+ 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 db606e8..fba3b70 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -32,6 +32,9 @@ DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
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(celgb, i64, env, i64, i32)
+DEF_HELPER_3(cdlgb, i64, env, i64, i32)
+DEF_HELPER_3(cxlgb, i64, env, i64, 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 a67fdcc..0777b55 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -233,6 +233,13 @@
C(0xb3ac, CLGEBR, RRF_e, FPE, 0, e2, r1, 0, clgeb, 0)
C(0xb3ad, CLGDBR, RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0)
C(0xb3ae, CLGXBR, RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0)
+/* CONVERT FROM LOGICAL */
+ C(0xb390, CELFBR, RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0)
+ C(0xb391, CDLFBR, RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0)
+ C(0xb392, CXLFBR, RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0)
+ C(0xb3a0, CELGBR, RRF_e, FPE, 0, r2_o, new, e1, celgb, 0)
+ C(0xb3a1, CDLGBR, RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0)
+ C(0xb3a2, CXLGBR, RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0)
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0161bd0..dddd822 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1609,6 +1609,31 @@ static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_celgb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_celgb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cdlgb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cxlgb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ return_low128(o->out2);
+ return NO_EXIT;
+}
+
static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
{
int r2 = get_field(s->fields, r2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 131/147] target-s390: Implement POPCNT
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (129 preceding siblings ...)
2012-09-28 1:06 ` [Qemu-devel] [PATCH 130/147] target-s390: Implement CONVERT FROM LOGICAL Richard Henderson
@ 2012-09-28 1:07 ` Richard Henderson
2012-09-28 1:08 ` [Qemu-devel] [PATCH 132/147] target-s390: Implement CPSDR Richard Henderson
` (16 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:07 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/int_helper.c | 12 ++++++++++++
target-s390x/translate.c | 6 ++++++
4 files changed, 22 insertions(+)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index fba3b70..03effd1 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -86,6 +86,7 @@ DEF_HELPER_4(unpk, void, env, i32, i64, i64)
DEF_HELPER_4(tr, void, env, i32, i64, i64)
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_PURE|TCG_CALL_CONST, i64, 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 0777b55..49e4a44 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -539,6 +539,9 @@
C(0xe336, PFD, RXY_b, GIE, 0, 0, 0, 0, 0, 0)
C(0xc602, PFDRL, RIL_c, GIE, 0, 0, 0, 0, 0, 0)
+/* POPULATION COUNT */
+ C(0xb9e1, POPCNT, RRE, PC, 0, r2_o, r1, 0, popcnt, nz64)
+
/* 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)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index 00f764c..3a86fba 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -191,3 +191,15 @@ uint64_t HELPER(cvd)(int32_t bin)
return dec;
}
+
+uint64_t HELPER(popcnt)(uint64_t r2)
+{
+ uint64_t ret = 0;
+ int i;
+
+ for (i = 0; i < 64; i += 8) {
+ uint64_t t = ctpop32((r2 >> i) & 0xff);
+ ret |= t << i;
+ }
+ return ret;
+}
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dddd822..6c23729 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2558,6 +2558,12 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
+{
+ gen_helper_popcnt(o->out, o->in2);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 132/147] target-s390: Implement CPSDR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (130 preceding siblings ...)
2012-09-28 1:07 ` [Qemu-devel] [PATCH 131/147] target-s390: Implement POPCNT Richard Henderson
@ 2012-09-28 1:08 ` Richard Henderson
2012-09-28 1:09 ` [Qemu-devel] [PATCH 133/147] target-s390: Check insn operand specifications Richard Henderson
` (15 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:08 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 | 16 ++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 49e4a44..b023911 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -104,6 +104,9 @@
/* CHECKSUM */
C(0xb241, CKSM, RRE, Z, r1_o, ra2, new, r1_32, cksm, 0)
+/* COPY SIGN */
+ C(0xb372, CPSDR, RRF_b, FPSSH, f3_o, f2_o, f1, 0, cps, 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 6c23729..d30e98d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1719,6 +1719,16 @@ static ExitStatus op_clst(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_cps(DisasContext *s, DisasOps *o)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+ tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull);
+ tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
+ tcg_gen_or_i64(o->out, o->out, t);
+ tcg_temp_free_i64(t);
+ return NO_EXIT;
+}
+
static ExitStatus op_cs(DisasContext *s, DisasOps *o)
{
int r3 = get_field(s->fields, r3);
@@ -3801,6 +3811,12 @@ static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_out = o->g_out2 = true;
}
+static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ o->in1 = fregs[get_field(f, r3)];
+ 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] 152+ messages in thread
* [Qemu-devel] [PATCH 133/147] target-s390: Check insn operand specifications
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (131 preceding siblings ...)
2012-09-28 1:08 ` [Qemu-devel] [PATCH 132/147] target-s390: Implement CPSDR Richard Henderson
@ 2012-09-28 1:09 ` Richard Henderson
2012-09-28 1:10 ` [Qemu-devel] [PATCH 134/147] target-s390: Implement LCDFR Richard Henderson
` (14 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Removes all the fixmes for even register numbers, etc.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 195 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 159 insertions(+), 36 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d30e98d..83b5e6f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -993,6 +993,17 @@ typedef struct {
TCGv_i64 addr1;
} DisasOps;
+/* Instructions can place constraints on their operands, raising specification
+ exceptions if they are violated. To make this easy to automate, each "in1",
+ "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
+ of the following, or 0. To make this easy to document, we'll put the
+ SPEC_<name> defines next to <name>. */
+
+#define SPEC_r1_even 1
+#define SPEC_r2_even 2
+#define SPEC_r1_f128 4
+#define SPEC_r2_f128 8
+
/* Return values from translate_one, indicating the state of the TB. */
typedef enum {
/* Continue the TB. */
@@ -1038,6 +1049,7 @@ struct DisasInsn {
unsigned opc:16;
DisasFormat fmt:6;
DisasFacility fac:6;
+ unsigned spec:4;
const char *name;
@@ -3561,42 +3573,46 @@ static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->out = tcg_temp_new_i64();
}
+#define SPEC_prep_new 0
static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->out = tcg_temp_new_i64();
o->out2 = tcg_temp_new_i64();
}
+#define SPEC_prep_new_P 0
static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->out = regs[get_field(f, r1)];
o->g_out = true;
}
+#define SPEC_prep_r1 0
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->out2 = regs[r1 + 1];
o->g_out = o->g_out2 = true;
}
+#define SPEC_prep_r1_P SPEC_r1_even
static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->out = fregs[get_field(f, r1)];
o->g_out = true;
}
+#define SPEC_prep_f1 0
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->out2 = fregs[r1 + 2];
o->g_out = o->g_out2 = true;
}
+#define SPEC_prep_x1 SPEC_r1_f128
/* ====================================================================== */
/* The "Write OUTput" generators. These generally perform some non-trivial
@@ -3608,58 +3624,64 @@ static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_reg(get_field(f, r1), o->out);
}
+#define SPEC_wout_r1 0
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);
}
+#define SPEC_wout_r1_8 0
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);
}
+#define SPEC_wout_r1_16 0
static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_reg32_i64(get_field(f, r1), o->out);
}
+#define SPEC_wout_r1_32 0
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);
+ store_reg32_i64(r1 + 1, o->out2);
}
+#define SPEC_wout_r1_P32 SPEC_r1_even
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);
+ store_reg32_i64(r1 + 1, o->out);
tcg_gen_shri_i64(o->out, o->out, 32);
store_reg32_i64(r1, o->out);
}
+#define SPEC_wout_r1_D32 SPEC_r1_even
static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_freg32_i64(get_field(f, r1), o->out);
}
+#define SPEC_wout_e1 0
static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
{
store_freg(get_field(f, r1), o->out);
}
+#define SPEC_wout_f1 0
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);
+ store_freg(f1 + 2, o->out2);
}
+#define SPEC_wout_x1 SPEC_r1_f128
static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3667,6 +3689,7 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
store_reg32_i64(get_field(f, r1), o->out);
}
}
+#define SPEC_wout_cond_r1r2_32 0
static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3674,31 +3697,37 @@ static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
store_freg32_i64(get_field(f, r1), o->out);
}
}
+#define SPEC_wout_cond_e1e2 0
static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
}
+#define SPEC_wout_m1_8 0
static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
}
+#define SPEC_wout_m1_16 0
static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
}
+#define SPEC_wout_m1_32 0
static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
}
+#define SPEC_wout_m1_64 0
static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
{
tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
}
+#define SPEC_wout_m2_32 0
/* ====================================================================== */
/* The "INput 1" generators. These load the first operand to an insn. */
@@ -3707,126 +3736,138 @@ static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_reg(get_field(f, r1));
}
+#define SPEC_in1_r1 0
static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = regs[get_field(f, r1)];
o->g_in1 = true;
}
+#define SPEC_in1_r1_o 0
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)]);
}
+#define SPEC_in1_r1_32s 0
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)]);
}
+#define SPEC_in1_r1_32u 0
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);
}
+#define SPEC_in1_r1_sr32 0
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);
+ o->in1 = load_reg(get_field(f, r1) + 1);
}
+#define SPEC_in1_r1p1 SPEC_r1_even
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]);
+ tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
}
+#define SPEC_in1_r1p1_32s SPEC_r1_even
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]);
+ tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
}
+#define SPEC_in1_r1p1_32u SPEC_r1_even
static void in1_r1_D32(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_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
}
+#define SPEC_in1_r1_D32 SPEC_r1_even
static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_reg(get_field(f, r2));
}
+#define SPEC_in1_r2 0
static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_reg(get_field(f, r3));
}
+#define SPEC_in1_r3 0
static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = regs[get_field(f, r3)];
o->g_in1 = true;
}
+#define SPEC_in1_r3_o 0
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)]);
}
+#define SPEC_in1_r3_32s 0
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)]);
}
+#define SPEC_in1_r3_32u 0
static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_freg32_i64(get_field(f, r1));
}
+#define SPEC_in1_e1 0
static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = fregs[get_field(f, r1)];
o->g_in1 = true;
}
+#define SPEC_in1_f1_o 0
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->out2 = fregs[r1 + 2];
o->g_out = o->g_out2 = true;
}
+#define SPEC_in1_x1_o SPEC_r1_f128
static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = fregs[get_field(f, r3)];
o->g_in1 = true;
}
+#define SPEC_in1_f3_o 0
static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
}
+#define SPEC_in1_la1 0
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));
}
+#define SPEC_in1_la2 0
static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3834,6 +3875,7 @@ static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = tcg_temp_new_i64();
tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
}
+#define SPEC_in1_m1_8u 0
static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3841,6 +3883,7 @@ static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = tcg_temp_new_i64();
tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
}
+#define SPEC_in1_m1_16s 0
static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3848,6 +3891,7 @@ static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = tcg_temp_new_i64();
tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
}
+#define SPEC_in1_m1_16u 0
static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3855,6 +3899,7 @@ static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = tcg_temp_new_i64();
tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
}
+#define SPEC_in1_m1_32s 0
static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3862,6 +3907,7 @@ static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = tcg_temp_new_i64();
tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
}
+#define SPEC_in1_m1_32u 0
static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3869,6 +3915,7 @@ static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
o->in1 = tcg_temp_new_i64();
tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
}
+#define SPEC_in1_m1_64 0
/* ====================================================================== */
/* The "INput 2" generators. These load the second operand to an insn. */
@@ -3878,29 +3925,34 @@ static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = regs[get_field(f, r1)];
o->g_in2 = true;
}
+#define SPEC_in2_r1_o 0
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)]);
}
+#define SPEC_in2_r1_16u 0
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)]);
}
+#define SPEC_in2_r1_32u 0
static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_reg(get_field(f, r2));
}
+#define SPEC_in2_r2 0
static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = regs[get_field(f, r2)];
o->g_in2 = true;
}
+#define SPEC_in2_r2_o 0
static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
{
@@ -3909,185 +3961,216 @@ static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
o->in2 = load_reg(r2);
}
}
+#define SPEC_in2_r2_nz 0
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)]);
}
+#define SPEC_in2_r2_8s 0
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)]);
}
+#define SPEC_in2_r2_8u 0
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)]);
}
+#define SPEC_in2_r2_16s 0
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)]);
}
+#define SPEC_in2_r2_16u 0
static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_reg(get_field(f, r3));
}
+#define SPEC_in2_r3 0
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)]);
}
+#define SPEC_in2_r2_32s 0
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)]);
}
+#define SPEC_in2_r2_32u 0
static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_freg32_i64(get_field(f, r2));
}
+#define SPEC_in2_e2 0
static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = fregs[get_field(f, r2)];
o->g_in2 = true;
}
+#define SPEC_in2_f2_o 0
static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
- /* ??? Specification exception: r1 must be < 14. */
int r2 = get_field(f, r2);
o->in1 = fregs[r2];
- o->in2 = fregs[(r2 + 2) & 15];
+ o->in2 = fregs[r2 + 2];
o->g_in1 = o->g_in2 = true;
}
+#define SPEC_in2_x2_o SPEC_r2_f128
static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = get_address(s, 0, get_field(f, r2), 0);
}
+#define SPEC_in2_ra2 0
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));
}
+#define SPEC_in2_a2 0
static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
}
+#define SPEC_in2_ri2 0
static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
{
help_l2_shift(s, f, o, 31);
}
+#define SPEC_in2_sh32 0
static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
{
help_l2_shift(s, f, o, 63);
}
+#define SPEC_in2_sh64 0
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));
}
+#define SPEC_in2_m2_8u 0
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));
}
+#define SPEC_in2_m2_16s 0
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));
}
+#define SPEC_in2_m2_16u 0
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));
}
+#define SPEC_in2_m2_32s 0
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));
}
+#define SPEC_in2_m2_32u 0
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));
}
+#define SPEC_in2_m2_64 0
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));
}
+#define SPEC_in2_mri2_16u 0
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));
}
+#define SPEC_in2_mri2_32s 0
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));
}
+#define SPEC_in2_mri2_32u 0
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));
}
+#define SPEC_in2_mri2_64 0
static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64(get_field(f, i2));
}
+#define SPEC_in2_i2 0
static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
}
+#define SPEC_in2_i2_8u 0
static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
}
+#define SPEC_in2_i2_16u 0
static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
}
+#define SPEC_in2_i2_32u 0
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);
}
+#define SPEC_in2_i2_16u_shl 0
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);
}
+#define SPEC_in2_i2_32u_shl 0
/* ====================================================================== */
@@ -4106,18 +4189,19 @@ enum DisasInsnEnum {
};
#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 \
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
+ .opc = OPC, \
+ .fmt = FMT_##FT, \
+ .fac = FAC_##FC, \
+ .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
+ .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. */
@@ -4128,6 +4212,11 @@ enum DisasInsnEnum {
#define cout_0 NULL
#define op_0 NULL
+#define SPEC_in1_0 0
+#define SPEC_in2_0 0
+#define SPEC_prep_0 0
+#define SPEC_wout_0 0
+
static const DisasInsn insn_info[] = {
#include "insn-data.def"
};
@@ -4295,6 +4384,40 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
return EXIT_NORETURN;
}
+ /* Check for insn specification exceptions. */
+ if (insn->spec) {
+ int spec = insn->spec, excp = 0, r;
+
+ if (spec & SPEC_r1_even) {
+ r = get_field(&f, r1);
+ if (r & 1) {
+ excp = PGM_SPECIFICATION;
+ }
+ }
+ if (spec & SPEC_r2_even) {
+ r = get_field(&f, r2);
+ if (r & 1) {
+ excp = PGM_SPECIFICATION;
+ }
+ }
+ if (spec & SPEC_r1_f128) {
+ r = get_field(&f, r1);
+ if (r > 13) {
+ excp = PGM_SPECIFICATION;
+ }
+ }
+ if (spec & SPEC_r2_f128) {
+ r = get_field(&f, r2);
+ if (r > 13) {
+ excp = PGM_SPECIFICATION;
+ }
+ }
+ if (excp) {
+ gen_program_exception(s, excp);
+ return EXIT_NORETURN;
+ }
+ }
+
/* Set up the strutures we use to communicate with the helpers. */
s->insn = insn;
s->fields = &f;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 134/147] target-s390: Implement LCDFR
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (132 preceding siblings ...)
2012-09-28 1:09 ` [Qemu-devel] [PATCH 133/147] target-s390: Check insn operand specifications Richard Henderson
@ 2012-09-28 1:10 ` Richard Henderson
2012-09-28 1:12 ` [Qemu-devel] [PATCH 135/147] softfloat: Fix uint64_to_float64 Richard Henderson
` (13 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 1 +
1 file changed, 1 insertion(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b023911..6e92790 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -356,6 +356,7 @@
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)
+ C(0xb373, LCDFR, RRE, FPSSH, 0, f2_o, f1, 0, negf64, 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)
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 135/147] softfloat: Fix uint64_to_float64
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (133 preceding siblings ...)
2012-09-28 1:10 ` [Qemu-devel] [PATCH 134/147] target-s390: Implement LCDFR Richard Henderson
@ 2012-09-28 1:12 ` Richard Henderson
2012-09-28 14:14 ` Peter Maydell
2012-09-28 1:13 ` [Qemu-devel] [PATCH 136/147] softfloat: Implement uint64_to_float128 Richard Henderson
` (12 subsequent siblings)
147 siblings, 1 reply; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
The interface to normalizeRoundAndPackFloat64 requires that the
high bit be clear. Perform one shift-right-and-jam if needed.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
fpu/softfloat.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b29256a..45f105a 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1273,9 +1273,14 @@ float64 int64_to_float64( int64 a STATUS_PARAM )
float64 uint64_to_float64( uint64 a STATUS_PARAM )
{
- if ( a == 0 ) return float64_zero;
- return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR );
+ int exp = 0x43C;
+ if ( a == 0 ) return float64_zero;
+ if ( (int64_t)a < 0 ) {
+ a = (a >> 1) | (a & 1);
+ exp += 1;
+ }
+ return normalizeRoundAndPackFloat64( 0, exp, a STATUS_VAR );
}
/*----------------------------------------------------------------------------
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* Re: [Qemu-devel] [PATCH 135/147] softfloat: Fix uint64_to_float64
2012-09-28 1:12 ` [Qemu-devel] [PATCH 135/147] softfloat: Fix uint64_to_float64 Richard Henderson
@ 2012-09-28 14:14 ` Peter Maydell
0 siblings, 0 replies; 152+ messages in thread
From: Peter Maydell @ 2012-09-28 14:14 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On 28 September 2012 02:12, Richard Henderson <rth@twiddle.net> wrote:
> The interface to normalizeRoundAndPackFloat64 requires that the
> high bit be clear. Perform one shift-right-and-jam if needed.
>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> fpu/softfloat.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index b29256a..45f105a 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -1273,9 +1273,14 @@ float64 int64_to_float64( int64 a STATUS_PARAM )
>
> float64 uint64_to_float64( uint64 a STATUS_PARAM )
> {
> - if ( a == 0 ) return float64_zero;
> - return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR );
> + int exp = 0x43C;
>
> + if ( a == 0 ) return float64_zero;
> + if ( (int64_t)a < 0 ) {
> + a = (a >> 1) | (a & 1);
> + exp += 1;
> + }
You could just use
shift64RightJamming(a, 1, &a);
rather than calculating a like that; gcc is smart enough to emit
the same code as your longhand version.
> + return normalizeRoundAndPackFloat64( 0, exp, a STATUS_VAR );
I worked through it and I believe this patch does the right thing
with raising or not raising the inexact flag...
-- PMM
^ permalink raw reply [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 136/147] softfloat: Implement uint64_to_float128
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (134 preceding siblings ...)
2012-09-28 1:12 ` [Qemu-devel] [PATCH 135/147] softfloat: Fix uint64_to_float64 Richard Henderson
@ 2012-09-28 1:13 ` Richard Henderson
2012-09-28 14:27 ` Peter Maydell
2012-09-28 1:14 ` [Qemu-devel] [PATCH 137/147] target-s390: Use uint64_to_float128 Richard Henderson
` (11 subsequent siblings)
147 siblings, 1 reply; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:13 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
fpu/softfloat.c | 6 ++++++
fpu/softfloat.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 45f105a..8df3a32 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1337,6 +1337,12 @@ float128 int64_to_float128( int64 a STATUS_PARAM )
}
+float128 uint64_to_float128( uint64 a STATUS_PARAM )
+{
+ if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
+ return normalizeRoundAndPackFloat128( 0, 0x406E, a, 0 STATUS_VAR );
+}
+
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the 32-bit two's complement integer format. The conversion is
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index d8999b3..ee925ad 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -237,6 +237,7 @@ float64 int64_to_float64( int64 STATUS_PARAM );
float64 uint64_to_float64( uint64 STATUS_PARAM );
floatx80 int64_to_floatx80( int64 STATUS_PARAM );
float128 int64_to_float128( int64 STATUS_PARAM );
+float128 uint64_to_float128( uint64 STATUS_PARAM );
/*----------------------------------------------------------------------------
| Software half-precision conversion routines.
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* Re: [Qemu-devel] [PATCH 136/147] softfloat: Implement uint64_to_float128
2012-09-28 1:13 ` [Qemu-devel] [PATCH 136/147] softfloat: Implement uint64_to_float128 Richard Henderson
@ 2012-09-28 14:27 ` Peter Maydell
0 siblings, 0 replies; 152+ messages in thread
From: Peter Maydell @ 2012-09-28 14:27 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, Alexander Graf
On 28 September 2012 02:13, Richard Henderson <rth@twiddle.net> wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
> fpu/softfloat.c | 6 ++++++
> fpu/softfloat.h | 1 +
> 2 files changed, 7 insertions(+)
>
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index 45f105a..8df3a32 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -1337,6 +1337,12 @@ float128 int64_to_float128( int64 a STATUS_PARAM )
>
> }
>
> +float128 uint64_to_float128( uint64 a STATUS_PARAM )
> +{
> + if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
It would be more in line with the other float sizes to have
#define float128_zero make_float128(0, 0)
and then return float128_zero here.
> + return normalizeRoundAndPackFloat128( 0, 0x406E, a, 0 STATUS_VAR );
(I assume you've tested at least enough to confirm that 0x406E
is the right number and not off by one one way or the other :-))
Incidentally personally I prefer to follow QEMU's spacing/bracing
style rather than the insane original-softfloat one, when
making changes. But the file is enough of a mess that I don't
care much one way or another, if you prefer to follow local
style.
-- PMM
^ permalink raw reply [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 137/147] target-s390: Use uint64_to_float128
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (135 preceding siblings ...)
2012-09-28 1:13 ` [Qemu-devel] [PATCH 136/147] softfloat: Implement uint64_to_float128 Richard Henderson
@ 2012-09-28 1:14 ` Richard Henderson
2012-09-28 1:15 ` [Qemu-devel] [PATCH 138/147] target-s390: Implement SET ROUNDING MODE Richard Henderson
` (10 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:14 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 2983360..899421e 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -419,8 +419,7 @@ uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
int hold = swap_round_mode(env, m3);
- /* ??? Not 50% correct. */
- float128 ret = int64_to_float128(v2, &env->fpu_status);
+ float128 ret = uint64_to_float128(v2, &env->fpu_status);
set_float_rounding_mode(hold, &env->fpu_status);
handle_exceptions(env, GETPC());
return RET128(ret);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 138/147] target-s390: Implement SET ROUNDING MODE
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (136 preceding siblings ...)
2012-09-28 1:14 ` [Qemu-devel] [PATCH 137/147] target-s390: Use uint64_to_float128 Richard Henderson
@ 2012-09-28 1:15 ` Richard Henderson
2012-09-28 1:16 ` [Qemu-devel] [PATCH 139/147] target-s390: Implement LOAD/SET FP AND SIGNAL Richard Henderson
` (9 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:15 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, 44 insertions(+)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6e92790..79341a4 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -566,6 +566,11 @@
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)
+/* SET BFP ROUNDING MODE */
+ C(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0)
+ C(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0)
+/* SET DFP ROUNDING MODE */
+ C(0xb2b9, SRNMT, S, DFP, 0, 0, 0, 0, srnm, 0)
/* SHIFT LEFT SINGLE */
D(0x8b00, SLA, RS_a, Z, r1, sh32, new, r1_32, sla, 0, 31)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 83b5e6f..6cf2634 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2921,6 +2921,45 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
+{
+ int b2 = get_field(s->fields, b2);
+ int d2 = get_field(s->fields, d2);
+ TCGv_i64 t1 = tcg_temp_new_i64();
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ int mask, pos, len;
+
+ switch (s->fields->op2) {
+ case 0x99: /* SRNM */
+ pos = 0, len = 2;
+ break;
+ case 0xb8: /* SRNMB */
+ pos = 0, len = 3;
+ break;
+ case 0xb9: /* SRNMT */
+ pos = 4, len = 3;
+ default:
+ tcg_abort();
+ }
+ mask = (1 << len) - 1;
+
+ /* Insert the value into the appropriate field of the FPC. */
+ if (b2 == 0) {
+ tcg_gen_movi_i64(t1, d2 & mask);
+ } else {
+ tcg_gen_addi_i64(t1, regs[b2], d2);
+ tcg_gen_andi_i64(t1, t1, mask);
+ }
+ tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
+ tcg_gen_deposit_i64(t2, t2, t1, pos, len);
+ tcg_temp_free_i64(t1);
+
+ /* Then install the new FPC to set the rounding mode in fpu_status. */
+ gen_helper_sfpc(cpu_env, t2);
+ tcg_temp_free_i64(t2);
+ return NO_EXIT;
+}
+
#ifndef CONFIG_USER_ONLY
static ExitStatus op_spka(DisasContext *s, DisasOps *o)
{
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 139/147] target-s390: Implement LOAD/SET FP AND SIGNAL
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (137 preceding siblings ...)
2012-09-28 1:15 ` [Qemu-devel] [PATCH 138/147] target-s390: Implement SET ROUNDING MODE Richard Henderson
@ 2012-09-28 1:16 ` Richard Henderson
2012-09-28 1:17 ` [Qemu-devel] [PATCH 140/147] target-s390: Fix cpu_clone_regs Richard Henderson
` (8 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/fpu_helper.c | 37 +++++++++++++++++++++++++++++--------
target-s390x/helper.h | 1 +
target-s390x/insn-data.def | 4 ++++
target-s390x/translate.c | 6 ++++++
4 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 899421e..edfcee1 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -674,19 +674,40 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
return RET128(ret);
}
+static const int fpc_to_rnd[4] = {
+ float_round_nearest_even,
+ float_round_to_zero,
+ float_round_up,
+ float_round_down
+};
+
/* 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);
+ set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+}
+
+/* set fpc and signal */
+void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+{
+ uint32_t signalling = env->fpc;
+ uint32_t source = val;
+ uint32_t s390_exc;
+
+ /* The contents of the source operand are placed in the FPC register;
+ then the flags in the FPC register are set to the logical OR of the
+ signalling flags and the source flags. */
+ env->fpc = source | (signalling & 0x00ff0000);
+ set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+
+ /* If any signalling flag is 1 and the corresponding source mask
+ is also 1, a simulated-iee-exception trap occurs. */
+ s390_exc = (signalling >> 16) & (source >> 24);
+ if (s390_exc) {
+ ieee_exception(env, s390_exc | 3, GETPC());
+ }
}
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 03effd1..9df25ab 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -86,6 +86,7 @@ DEF_HELPER_4(unpk, void, env, i32, i64, i64)
DEF_HELPER_4(tr, void, env, i32, i64, i64)
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(sfas, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_PURE|TCG_CALL_CONST, i64, 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 79341a4..e915984 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -433,6 +433,8 @@
/* LOAD FPC */
C(0xb29d, LFPC, S, Z, 0, m2_32u, 0, 0, sfpc, 0)
+/* LOAD FPC AND SIGNAL */
+ C(0xb2bd, LFAS, S, IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0)
/* LOAD LENGTHENED */
C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0)
@@ -566,6 +568,8 @@
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)
+/* SET FPC AND SIGNAL */
+ C(0xb385, SFASR, RRE, IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0)
/* SET BFP ROUNDING MODE */
C(0xb299, SRNM, S, Z, 0, 0, 0, 0, srnm, 0)
C(0xb2b8, SRNMB, S, FPE, 0, 0, 0, 0, srnm, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6cf2634..b945ba1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2921,6 +2921,12 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
+{
+ gen_helper_sfas(cpu_env, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
{
int b2 = get_field(s->fields, b2);
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 140/147] target-s390: Fix cpu_clone_regs
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (138 preceding siblings ...)
2012-09-28 1:16 ` [Qemu-devel] [PATCH 139/147] target-s390: Implement LOAD/SET FP AND SIGNAL Richard Henderson
@ 2012-09-28 1:17 ` Richard Henderson
2012-09-28 1:18 ` [Qemu-devel] [PATCH 141/147] target-s390: Optimize XC Richard Henderson
` (7 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
R2 is the syscall return register, not R0.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/cpu.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index a6a6e3f..cfc716a 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -116,7 +116,7 @@ static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
if (newsp) {
env->regs[15] = newsp;
}
- env->regs[0] = 0;
+ env->regs[2] = 0;
}
#endif
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 141/147] target-s390: Optimize XC
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (139 preceding siblings ...)
2012-09-28 1:17 ` [Qemu-devel] [PATCH 140/147] target-s390: Fix cpu_clone_regs Richard Henderson
@ 2012-09-28 1:18 ` Richard Henderson
2012-09-28 1:19 ` [Qemu-devel] [PATCH 142/147] target-s390: Optmize emitting discards Richard Henderson
` (6 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:18 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Notice XC with same address and convert that to store of zero.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/insn-data.def | 2 +-
target-s390x/translate.c | 50 +++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index e915984..480f1fd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -271,7 +271,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)
+ C(0xd700, XC, SS_a, Z, 0, 0, 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)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b945ba1..5b88efb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3403,10 +3403,54 @@ static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
static ExitStatus op_xc(DisasContext *s, DisasOps *o)
{
- TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+ int d1 = get_field(s->fields, d1);
+ int d2 = get_field(s->fields, d2);
+ int b1 = get_field(s->fields, b1);
+ int b2 = get_field(s->fields, b2);
+ int l = get_field(s->fields, l1);
+ TCGv_i32 t32;
+
+ o->addr1 = get_address(s, 0, b1, d1);
+
+ /* If the addresses are identical, this is a store/memset of zero. */
+ if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
+ o->in2 = tcg_const_i64(0);
+
+ l++;
+ while (l >= 8) {
+ tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
+ l -= 8;
+ if (l > 0) {
+ tcg_gen_addi_i64(o->addr1, o->addr1, 8);
+ }
+ }
+ if (l >= 4) {
+ tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
+ l -= 4;
+ if (l > 0) {
+ tcg_gen_addi_i64(o->addr1, o->addr1, 4);
+ }
+ }
+ if (l >= 2) {
+ tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
+ l -= 2;
+ if (l > 0) {
+ tcg_gen_addi_i64(o->addr1, o->addr1, 2);
+ }
+ }
+ if (l) {
+ tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
+ }
+ gen_op_movi_cc(s, 0);
+ return NO_EXIT;
+ }
+
+ /* But in general we'll defer to a helper. */
+ o->in2 = get_address(s, 0, b2, d2);
+ t32 = tcg_const_i32(l);
potential_page_fault(s);
- gen_helper_xc(cc_op, cpu_env, l, o->addr1, o->in2);
- tcg_temp_free_i32(l);
+ gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
+ tcg_temp_free_i32(t32);
set_cc_static(s);
return NO_EXIT;
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 142/147] target-s390: Optmize emitting discards
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (140 preceding siblings ...)
2012-09-28 1:18 ` [Qemu-devel] [PATCH 141/147] target-s390: Optimize XC Richard Henderson
@ 2012-09-28 1:19 ` Richard Henderson
2012-09-28 1:20 ` [Qemu-devel] [PATCH 143/147] target-s390: Tidy comparisons Richard Henderson
` (5 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
While they aren't expensive, they aren't free to process. When we
know that the three cc helper variables are dead, don't kill them.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5b88efb..a68e4a3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -367,25 +367,41 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
return tmp;
}
+static inline bool live_cc_data(DisasContext *s)
+{
+ return (s->cc_op != CC_OP_DYNAMIC
+ && s->cc_op != CC_OP_STATIC
+ && s->cc_op > 3);
+}
+
static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
{
+ if (live_cc_data(s)) {
+ tcg_gen_discard_i64(cc_src);
+ tcg_gen_discard_i64(cc_dst);
+ tcg_gen_discard_i64(cc_vr);
+ }
s->cc_op = CC_OP_CONST0 + val;
}
static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
{
- tcg_gen_discard_i64(cc_src);
+ if (live_cc_data(s)) {
+ tcg_gen_discard_i64(cc_src);
+ tcg_gen_discard_i64(cc_vr);
+ }
tcg_gen_mov_i64(cc_dst, dst);
- tcg_gen_discard_i64(cc_vr);
s->cc_op = op;
}
static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
TCGv_i64 dst)
{
+ if (live_cc_data(s)) {
+ tcg_gen_discard_i64(cc_vr);
+ }
tcg_gen_mov_i64(cc_src, src);
tcg_gen_mov_i64(cc_dst, dst);
- tcg_gen_discard_i64(cc_vr);
s->cc_op = op;
}
@@ -421,9 +437,11 @@ static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
/* CC value is in env->cc_op */
static void set_cc_static(DisasContext *s)
{
- tcg_gen_discard_i64(cc_src);
- tcg_gen_discard_i64(cc_dst);
- tcg_gen_discard_i64(cc_vr);
+ if (live_cc_data(s)) {
+ tcg_gen_discard_i64(cc_src);
+ tcg_gen_discard_i64(cc_dst);
+ tcg_gen_discard_i64(cc_vr);
+ }
s->cc_op = CC_OP_STATIC;
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 143/147] target-s390: Tidy comparisons
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (141 preceding siblings ...)
2012-09-28 1:19 ` [Qemu-devel] [PATCH 142/147] target-s390: Optmize emitting discards Richard Henderson
@ 2012-09-28 1:20 ` Richard Henderson
2012-09-28 1:21 ` [Qemu-devel] [PATCH 144/147] target-s390: Optimize ADDU/SUBU CC testing Richard Henderson
` (4 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:20 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
After full conversion, we can audit the uses of LTGT cc ops
and see that none of the instructions can ever set CC=3.
Thus we can extend the table to treat that bit as ignored.
This fixes a regression wrt the pre-conversion translation
in which NE was used for both m=6 and m=7.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 39 +++++++++++++++++----------------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a68e4a3..11f7f36 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -577,30 +577,29 @@ static void account_inline_branch(DisasContext *s, int cc_op)
}
/* 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. */
+ For such, CC=3 should not be possible. */
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_GT, TCG_COND_GT, /* | | GT | x */
+ TCG_COND_LT, TCG_COND_LT, /* | LT | | x */
+ TCG_COND_NE, TCG_COND_NE, /* | LT | GT | x */
+ TCG_COND_EQ, TCG_COND_EQ, /* EQ | | | x */
+ TCG_COND_GE, TCG_COND_GE, /* EQ | | GT | x */
+ TCG_COND_LE, TCG_COND_LE, /* 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,
+ TCG_COND_NEVER, TCG_COND_NEVER, /* | | x | x */
+ TCG_COND_NEVER, TCG_COND_NEVER,
+ TCG_COND_NE, TCG_COND_NE, /* | NE | x | x */
+ TCG_COND_NE, TCG_COND_NE,
+ TCG_COND_EQ, TCG_COND_EQ, /* EQ | | x | x */
+ TCG_COND_EQ, TCG_COND_EQ,
+ TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | NE | x | x */
+ TCG_COND_ALWAYS, TCG_COND_ALWAYS,
};
/* Interpret MASK in terms of S->CC_OP, and fill in C with all the
@@ -1463,9 +1462,7 @@ static ExitStatus op_cj(DisasContext *s, DisasOps *o)
bool is_imm;
DisasCompare c;
- /* Bit 3 of the m3 field is reserved and should be zero.
- Choose to ignore it wrt the ltgt_cond table above. */
- c.cond = ltgt_cond[m3 & 14];
+ c.cond = ltgt_cond[m3];
if (s->insn->data) {
c.cond = tcg_unsigned_cond(c.cond);
}
@@ -1831,9 +1828,7 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o)
TCGv_i32 t;
TCGCond c;
- /* Bit 3 of the m3 field is reserved and should be zero.
- Choose to ignore it wrt the ltgt_cond table above. */
- c = tcg_invert_cond(ltgt_cond[m3 & 14]);
+ c = tcg_invert_cond(ltgt_cond[m3]);
if (s->insn->data) {
c = tcg_unsigned_cond(c);
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 144/147] target-s390: Optimize ADDU/SUBU CC testing
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (142 preceding siblings ...)
2012-09-28 1:20 ` [Qemu-devel] [PATCH 143/147] target-s390: Tidy comparisons Richard Henderson
@ 2012-09-28 1:21 ` Richard Henderson
2012-09-28 1:22 ` [Qemu-devel] [PATCH 145/147] target-s390: Optimize ADDC/SUBB Richard Henderson
` (3 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:21 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
We can easily generate some masks for logical add/subtract inline.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 11f7f36..de9ae97 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -692,6 +692,49 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
account_inline_branch(s, old_cc_op);
break;
+ case CC_OP_ADDU_32:
+ case CC_OP_ADDU_64:
+ switch (mask) {
+ case 8 | 2: /* vr == 0 */
+ cond = TCG_COND_EQ;
+ break;
+ case 4 | 1: /* vr != 0 */
+ cond = TCG_COND_NE;
+ break;
+ case 8 | 4: /* no carry -> vr >= src */
+ cond = TCG_COND_GEU;
+ break;
+ case 2 | 1: /* carry -> vr < src */
+ cond = TCG_COND_LTU;
+ break;
+ default:
+ goto do_dynamic;
+ }
+ account_inline_branch(s, old_cc_op);
+ break;
+
+ case CC_OP_SUBU_32:
+ case CC_OP_SUBU_64:
+ /* Note that CC=0 is impossible; treat it as dont-care. */
+ switch (mask & 7) {
+ case 2: /* zero -> op1 == op2 */
+ cond = TCG_COND_EQ;
+ break;
+ case 4 | 1: /* !zero -> op1 != op2 */
+ cond = TCG_COND_NE;
+ break;
+ case 4: /* borrow (!carry) -> op1 < op2 */
+ cond = TCG_COND_LTU;
+ break;
+ case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
+ cond = TCG_COND_GEU;
+ break;
+ default:
+ goto do_dynamic;
+ }
+ account_inline_branch(s, old_cc_op);
+ break;
+
default:
do_dynamic:
/* Calculate cc value. */
@@ -719,6 +762,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
break;
case CC_OP_LTGT_32:
case CC_OP_LTUGTU_32:
+ case CC_OP_SUBU_32:
c->is_64 = false;
c->u.s32.a = tcg_temp_new_i32();
tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
@@ -735,6 +779,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
break;
case CC_OP_LTGT_64:
case CC_OP_LTUGTU_64:
+ case CC_OP_SUBU_64:
c->u.s64.a = cc_src;
c->u.s64.b = cc_dst;
c->g1 = c->g2 = true;
@@ -748,6 +793,29 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
break;
+ case CC_OP_ADDU_32:
+ c->is_64 = false;
+ c->u.s32.a = tcg_temp_new_i32();
+ c->u.s32.b = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(c->u.s32.a, cc_vr);
+ if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
+ tcg_gen_movi_i32(c->u.s32.b, 0);
+ } else {
+ tcg_gen_trunc_i64_i32(c->u.s32.b, cc_src);
+ }
+ break;
+
+ case CC_OP_ADDU_64:
+ c->u.s64.a = cc_vr;
+ c->g1 = true;
+ if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
+ c->u.s64.b = tcg_const_i64(0);
+ } else {
+ c->u.s64.b = cc_src;
+ c->g2 = true;
+ }
+ break;
+
case CC_OP_STATIC:
c->is_64 = false;
c->u.s32.a = cc_op;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 145/147] target-s390: Optimize ADDC/SUBB
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (143 preceding siblings ...)
2012-09-28 1:21 ` [Qemu-devel] [PATCH 144/147] target-s390: Optimize ADDU/SUBU CC testing Richard Henderson
@ 2012-09-28 1:22 ` Richard Henderson
2012-09-28 1:23 ` [Qemu-devel] [PATCH 146/147] target-s390: Optimize get_address Richard Henderson
` (2 subsequent siblings)
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:22 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Giving the proper mask to disas_jcc allows us to generate an inline
comparison generating the carry/borrow with setcond.
In the very worst case, when we must use the external helper to compute
a value for CC, we generate (cc > 1) instead of (cc >> 1), which is only
very slightly slower on common cpus.
In the very best case, when the CC comes from a COMPARE insn and the
compiler is using ALCG with zero, everything folds out to become just
the setcond that the compiler wanted.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 56 ++++++++++++++++++++++++++++++++----------------
1 file changed, 37 insertions(+), 19 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index de9ae97..e1888a3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1344,18 +1344,28 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
static ExitStatus op_addc(DisasContext *s, DisasOps *o)
{
- TCGv_i64 cc;
+ DisasCompare cmp;
+ TCGv_i64 carry;
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);
+ /* The carry flag is the msb of CC, therefore the branch mask that would
+ create that comparison is 3. Feeding the generated comparison to
+ setcond produces the carry flag that we desire. */
+ disas_jcc(s, &cmp, 3);
+ carry = tcg_temp_new_i64();
+ if (cmp.is_64) {
+ tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b);
+ } else {
+ TCGv_i32 t = tcg_temp_new_i32();
+ tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
+ tcg_gen_extu_i32_i64(carry, t);
+ tcg_temp_free_i32(t);
+ }
+ free_compare(&cmp);
- tcg_gen_add_i64(o->out, o->out, cc);
- tcg_temp_free_i64(cc);
+ tcg_gen_add_i64(o->out, o->out, carry);
+ tcg_temp_free_i64(carry);
return NO_EXIT;
}
@@ -3397,19 +3407,27 @@ static ExitStatus op_sub(DisasContext *s, DisasOps *o)
static ExitStatus op_subb(DisasContext *s, DisasOps *o)
{
- TCGv_i64 cc;
+ DisasCompare cmp;
+ TCGv_i64 borrow;
- assert(!o->g_in2);
- tcg_gen_not_i64(o->in2, o->in2);
- tcg_gen_add_i64(o->out, o->in1, o->in2);
+ tcg_gen_sub_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);
+ /* The !borrow flag is the msb of CC. Since we want the inverse of
+ that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
+ disas_jcc(s, &cmp, 8 | 4);
+ borrow = tcg_temp_new_i64();
+ if (cmp.is_64) {
+ tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
+ } else {
+ TCGv_i32 t = tcg_temp_new_i32();
+ tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
+ tcg_gen_extu_i32_i64(borrow, t);
+ tcg_temp_free_i32(t);
+ }
+ free_compare(&cmp);
+
+ tcg_gen_sub_i64(o->out, o->out, borrow);
+ tcg_temp_free_i64(borrow);
return NO_EXIT;
}
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 146/147] target-s390: Optimize get_address
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (144 preceding siblings ...)
2012-09-28 1:22 ` [Qemu-devel] [PATCH 145/147] target-s390: Optimize ADDC/SUBB Richard Henderson
@ 2012-09-28 1:23 ` Richard Henderson
2012-09-28 1:24 ` [Qemu-devel] [PATCH 147/147] target-s390: Perform COMPARE AND SWAP inline Richard Henderson
2012-11-16 0:09 ` [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:23 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Don't load the displacement into a register first, add it second
so that tcg_gen_addi_i64 can eliminate zeros. Don't mask the
displacement first so that we don't turn small negative numbers
into large positive numbers.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/translate.c | 44 ++++++++++++++++++--------------------------
1 file changed, 18 insertions(+), 26 deletions(-)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e1888a3..3506493 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -331,37 +331,29 @@ static inline void check_privileged(DisasContext *s)
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
{
- TCGv_i64 tmp;
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ bool need_31 = !(s->tb->flags & FLAG_MASK_64);
- /* 31-bitify the immediate part; register contents are dealt with below */
- if (!(s->tb->flags & FLAG_MASK_64)) {
- d2 &= 0x7fffffffUL;
- }
+ /* Note that d2 is limited to 20 bits, signed. If we crop negative
+ displacements early we create larger immedate addends. */
- if (x2) {
- if (d2) {
- tmp = tcg_const_i64(d2);
- tcg_gen_add_i64(tmp, tmp, regs[x2]);
- } else {
- tmp = load_reg(x2);
- }
- if (b2) {
- tcg_gen_add_i64(tmp, tmp, regs[b2]);
- }
+ /* Note that addi optimizes the imm==0 case. */
+ if (b2 && x2) {
+ tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
+ tcg_gen_addi_i64(tmp, tmp, d2);
} else if (b2) {
- if (d2) {
- tmp = tcg_const_i64(d2);
- tcg_gen_add_i64(tmp, tmp, regs[b2]);
- } else {
- tmp = load_reg(b2);
- }
+ tcg_gen_addi_i64(tmp, regs[b2], d2);
+ } else if (x2) {
+ tcg_gen_addi_i64(tmp, regs[x2], d2);
} else {
- tmp = tcg_const_i64(d2);
+ if (need_31) {
+ d2 &= 0x7fffffff;
+ need_31 = false;
+ }
+ tcg_gen_movi_i64(tmp, d2);
}
-
- /* 31-bit mode mask if there are values loaded from registers */
- if (!(s->tb->flags & FLAG_MASK_64) && (x2 || b2)) {
- tcg_gen_andi_i64(tmp, tmp, 0x7fffffffUL);
+ if (need_31) {
+ tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
}
return tmp;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* [Qemu-devel] [PATCH 147/147] target-s390: Perform COMPARE AND SWAP inline
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (145 preceding siblings ...)
2012-09-28 1:23 ` [Qemu-devel] [PATCH 146/147] target-s390: Optimize get_address Richard Henderson
@ 2012-09-28 1:24 ` Richard Henderson
2012-11-16 0:09 ` [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
147 siblings, 0 replies; 152+ messages in thread
From: Richard Henderson @ 2012-09-28 1:24 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Still no proper solution for CONFIG_USER_ONLY, but the system
version is significantly better.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-s390x/helper.h | 3 -
target-s390x/insn-data.def | 12 ++--
target-s390x/mem_helper.c | 53 ----------------
target-s390x/translate.c | 152 +++++++++++++++++++++++++++++++++++----------
4 files changed, 124 insertions(+), 96 deletions(-)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 9df25ab..f4a5226 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -17,9 +17,6 @@ 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)
-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)
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 480f1fd..b42ebb6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -193,13 +193,13 @@
D(0xec7d, CLGIJ, RIE_c, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
/* 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)
+ D(0xba00, CS, RS_a, Z, r3_32u, r1_32u, new, r1_32, cs, 0, 0)
+ D(0xeb14, CSY, RSY_a, LD, r3_32u, r1_32u, new, r1_32, cs, 0, 0)
+ D(0xeb30, CSG, RSY_a, Z, r3_o, r1_o, new, r1, cs, 0, 1)
/* COMPARE DOUBLE AND SWAP */
- C(0xbb00, CDS, RS_a, Z, r1_D32, a2, new, r1_D32, cds, 0)
- C(0xeb31, CDSY, RSY_a, LD, r1_D32, a2, new, r1_D32, cds, 0)
- C(0xeb3e, CDSG, RSY_a, Z, 0, a2, 0, 0, cdsg, 0)
+ D(0xbb00, CDS, RS_a, Z, r3_D32, r1_D32, new, r1_D32, cs, 0, 1)
+ D(0xeb31, CDSY, RSY_a, LD, r3_D32, r1_D32, new, r1_D32, cs, 0, 1)
+ C(0xeb3e, CDSG, RSY_a, Z, 0, 0, 0, 0, cdsg, 0)
/* COMPARE AND TRAP */
D(0xb972, CRT, RRF_c, GIE, r1_32s, r2_32s, 0, 0, ct, 0, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 2d4da45..065644e 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -448,59 +448,6 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
return d + len;
}
-/* compare and swap 64-bit */
-uint64_t HELPER(csg)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
-{
- /* FIXME: locking? */
- uint64_t v2 = cpu_ldq_data(env, a2);
- if (r1 == v2) {
- cpu_stq_data(env, a2, r3);
- env->cc_op = 0;
- return r1;
- } else {
- env->cc_op = 1;
- return v2;
- }
-}
-
-/* compare double and swap 64-bit */
-uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
- /* FIXME: locking? */
- uint32_t cc;
- uint64_t v2_hi = cpu_ldq_data(env, a2);
- uint64_t v2_lo = cpu_ldq_data(env, a2 + 8);
- uint64_t v1_hi = env->regs[r1];
- uint64_t v1_lo = env->regs[r1 + 1];
-
- if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
- cc = 0;
- cpu_stq_data(env, a2, env->regs[r3]);
- cpu_stq_data(env, a2 + 8, env->regs[r3 + 1]);
- } else {
- cc = 1;
- env->regs[r1] = v2_hi;
- env->regs[r1 + 1] = v2_lo;
- }
-
- return cc;
-}
-
-/* compare and swap 32-bit */
-uint64_t HELPER(cs)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
-{
- /* FIXME: locking? */
- uint32_t v2 = cpu_ldl_data(env, a2);
- if ((uint32_t)r1 == v2) {
- cpu_stl_data(env, a2, (uint32_t)r3);
- env->cc_op = 0;
- return r1;
- } else {
- env->cc_op = 1;
- return v2;
- }
-}
-
static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
uint32_t mask)
{
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3506493..5c7ed95 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1078,8 +1078,9 @@ typedef struct {
#define SPEC_r1_even 1
#define SPEC_r2_even 2
-#define SPEC_r1_f128 4
-#define SPEC_r2_f128 8
+#define SPEC_r3_even 4
+#define SPEC_r1_f128 8
+#define SPEC_r2_f128 16
/* Return values from translate_one, indicating the state of the TB. */
typedef enum {
@@ -1124,9 +1125,9 @@ typedef enum DisasFacility {
struct DisasInsn {
unsigned opc:16;
- DisasFormat fmt:6;
- DisasFacility fac:6;
- unsigned spec:4;
+ DisasFormat fmt:8;
+ DisasFacility fac:8;
+ unsigned spec:8;
const char *name;
@@ -1828,18 +1829,102 @@ static ExitStatus op_cps(DisasContext *s, DisasOps *o)
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]);
+ /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
+ int d2 = get_field(s->fields, d2);
+ int b2 = get_field(s->fields, b2);
+ int is_64 = s->insn->data;
+ TCGv_i64 addr, mem, cc, z;
+
+ /* Note that in1 = R3 (new value) and
+ in2 = (zero-extended) R1 (expected value). */
+
+ /* Load the memory into the (temporary) output. While the PoO only talks
+ about moving the memory to R1 on inequality, if we include equality it
+ means that R1 is equal to the memory in all conditions. */
+ addr = get_address(s, 0, b2, d2);
+ if (is_64) {
+ tcg_gen_qemu_ld64(o->out, addr, get_mem_index(s));
+ } else {
+ tcg_gen_qemu_ld32u(o->out, addr, get_mem_index(s));
+ }
+
+ /* Are the memory and expected values (un)equal? Note that this setcond
+ produces the output CC value, thus the NE sense of the test. */
+ cc = tcg_temp_new_i64();
+ tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in2, o->out);
+
+ /* If the memory and expected values are equal (CC==0), copy R3 to MEM.
+ Recall that we are allowed to unconditionally issue the store (and
+ thus any possible write trap), so (re-)store the original contents
+ of MEM in case of inequality. */
+ z = tcg_const_i64(0);
+ mem = tcg_temp_new_i64();
+ tcg_gen_movcond_i64(TCG_COND_EQ, mem, cc, z, o->in1, o->out);
+ if (is_64) {
+ tcg_gen_qemu_st64(mem, addr, get_mem_index(s));
+ } else {
+ tcg_gen_qemu_st32(mem, addr, get_mem_index(s));
+ }
+ tcg_temp_free_i64(z);
+ tcg_temp_free_i64(mem);
+ tcg_temp_free_i64(addr);
+
+ /* Store CC back to cc_op. Wait until after the store so that any
+ exception gets the old cc_op value. */
+ tcg_gen_trunc_i64_i32(cc_op, cc);
+ tcg_temp_free_i64(cc);
set_cc_static(s);
return NO_EXIT;
}
-static ExitStatus op_csg(DisasContext *s, DisasOps *o)
+static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
{
+ /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
+ int r1 = get_field(s->fields, r1);
int r3 = get_field(s->fields, r3);
- potential_page_fault(s);
- gen_helper_csg(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+ int d2 = get_field(s->fields, d2);
+ int b2 = get_field(s->fields, b2);
+ TCGv_i64 addrh, addrl, memh, meml, outh, outl, cc, z;
+
+ /* Note that R1:R1+1 = expected value and R3:R3+1 = new value. */
+
+ addrh = get_address(s, 0, b2, d2);
+ addrl = get_address(s, 0, b2, d2 + 8);
+ outh = tcg_temp_new_i64();
+ outl = tcg_temp_new_i64();
+
+ tcg_gen_qemu_ld64(outh, addrh, get_mem_index(s));
+ tcg_gen_qemu_ld64(outl, addrl, get_mem_index(s));
+
+ /* Fold the double-word compare with arithmetic. */
+ cc = tcg_temp_new_i64();
+ z = tcg_temp_new_i64();
+ tcg_gen_xor_i64(cc, outh, regs[r1]);
+ tcg_gen_xor_i64(z, outl, regs[r1 + 1]);
+ tcg_gen_or_i64(cc, cc, z);
+ tcg_gen_movi_i64(z, 0);
+ tcg_gen_setcond_i64(TCG_COND_NE, cc, cc, z);
+
+ memh = tcg_temp_new_i64();
+ meml = tcg_temp_new_i64();
+ tcg_gen_movcond_i64(TCG_COND_EQ, memh, cc, z, regs[r3], outh);
+ tcg_gen_movcond_i64(TCG_COND_EQ, meml, cc, z, regs[r3 + 1], outl);
+ tcg_temp_free_i64(z);
+
+ tcg_gen_qemu_st64(memh, addrh, get_mem_index(s));
+ tcg_gen_qemu_st64(meml, addrl, get_mem_index(s));
+ tcg_temp_free_i64(memh);
+ tcg_temp_free_i64(meml);
+ tcg_temp_free_i64(addrh);
+ tcg_temp_free_i64(addrl);
+
+ /* Save back state now that we've passed all exceptions. */
+ tcg_gen_mov_i64(regs[r1], outh);
+ tcg_gen_mov_i64(regs[r1 + 1], outl);
+ tcg_gen_trunc_i64_i32(cc_op, cc);
+ tcg_temp_free_i64(outh);
+ tcg_temp_free_i64(outl);
+ tcg_temp_free_i64(cc);
set_cc_static(s);
return NO_EXIT;
}
@@ -1856,29 +1941,6 @@ static ExitStatus op_csp(DisasContext *s, DisasOps *o)
}
#endif
-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();
@@ -4007,6 +4069,14 @@ static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
}
#define SPEC_in1_r3_32u 0
+static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int r3 = get_field(f, r3);
+ o->in1 = tcg_temp_new_i64();
+ tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
+}
+#define SPEC_in1_r3_D32 SPEC_r3_even
+
static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in1 = load_freg32_i64(get_field(f, r1));
@@ -4121,6 +4191,14 @@ static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
}
#define SPEC_in2_r1_32u 0
+static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+ int r1 = get_field(f, r1);
+ o->in2 = tcg_temp_new_i64();
+ tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
+}
+#define SPEC_in2_r1_D32 SPEC_r1_even
+
static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->in2 = load_reg(get_field(f, r2));
@@ -4580,6 +4658,12 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
excp = PGM_SPECIFICATION;
}
}
+ if (spec & SPEC_r3_even) {
+ r = get_field(&f, r3);
+ if (r & 1) {
+ excp = PGM_SPECIFICATION;
+ }
+ }
if (spec & SPEC_r1_f128) {
r = get_field(&f, r1);
if (r > 13) {
--
1.7.11.4
^ permalink raw reply related [flat|nested] 152+ messages in thread
* Re: [Qemu-devel] [PATCH v2 000/147] target-s390 reorg
2012-09-27 22:39 [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
` (146 preceding siblings ...)
2012-09-28 1:24 ` [Qemu-devel] [PATCH 147/147] target-s390: Perform COMPARE AND SWAP inline Richard Henderson
@ 2012-11-16 0:09 ` Richard Henderson
2012-11-19 11:40 ` Alexander Graf
147 siblings, 1 reply; 152+ messages in thread
From: Richard Henderson @ 2012-11-16 0:09 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
Ping.
I've updated the branch at
git://repo.or.cz/qemu/rth.git s390-reorg
to rebase vs mainline (ce34cf72fe508b27a78f83c184142e8d1e6a048a).
There are minor changes due to Aurel's TCG_CALL_NO_* rewrite, but
is otherwise unchanged.
I can re-post the 140+ patches if required...
r~
On 2012-09-27 15:39, Richard Henderson wrote:
> Tons of changes since v1. I believe I incorproated all of the feedback
> that I received. The patch set is relative to the "TCGCond" patch set
> that I sent out earlier this week. Both trees are available at
>
> git://repo.or.cz/qemu/rth.git tcg-cond
> git://repo.or.cz/qemu/rth.git s390-reorg
>
> This passes the gcc testsuite in userland with no unexpected failures
> (considering anything that touches threads to be "expected"). It boots
> a debian system image as well as (or as poorly as) mainline -- agraf
> and I had a rather long session re those failures on IRC the other day.
>
> Note that patches 2-11 are bug fixes for the *existing* code base. I
> found that I had to fix those in order to be able to properly bisect
> problems in the later patches.
>
> The last 7 patches are new, and improve the generated code for a
> variety of stuff I noticed while staring at dumps. Not that the
> last 25 patches or so made it to the list last time...
>
>
> r~
>
>
> Alexander Graf (1):
> s390x: fix -initrd in virtio machine
>
> Richard Henderson (146):
> tcg: Add TCGV_IS_UNUSED_*
> 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: Register helpers
> target-s390: Fix SACF exit
> target-s390: Fix BCR
> target-s390: Tidy unconditional BRCL
> target-s390: Fix PSW_MASK handling
> 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 HALFWORD, SINGLE
> target-s390: Convert 32-bit MULTIPLY, MULTIPLY LOGICAL
> target-s390: Convert 64-bit MULTIPLY LOGICAL
> 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
> target-s390: Implement LCDFR
> softfloat: Fix uint64_to_float64
> softfloat: Implement uint64_to_float128
> target-s390: Use uint64_to_float128
> target-s390: Implement SET ROUNDING MODE
> target-s390: Implement LOAD/SET FP AND SIGNAL
> target-s390: Fix cpu_clone_regs
> target-s390: Optimize XC
> target-s390: Optmize emitting discards
> target-s390: Tidy comparisons
> target-s390: Optimize ADDU/SUBU CC testing
> target-s390: Optimize ADDC/SUBB
> target-s390: Optimize get_address
> target-s390: Perform COMPARE AND SWAP inline
>
> fpu/softfloat.c | 15 +-
> fpu/softfloat.h | 1 +
> gdbstub.c | 78 +-
> hw/s390-virtio.c | 4 +-
> linux-user/main.c | 140 +-
> linux-user/s390x/syscall.h | 2 +-
> s390-dis.c | 173 +-
> target-s390x/cc_helper.c | 335 +-
> target-s390x/cpu.h | 167 +-
> target-s390x/fpu_helper.c | 960 ++---
> target-s390x/helper.c | 67 +-
> target-s390x/helper.h | 188 +-
> target-s390x/insn-data.def | 813 ++++
> target-s390x/insn-format.def | 55 +
> target-s390x/int_helper.c | 176 +-
> target-s390x/mem_helper.c | 359 +-
> target-s390x/misc_helper.c | 97 +-
> target-s390x/translate.c | 8684 ++++++++++++++++++++----------------------
> tcg/tcg.h | 3 +
> 19 files changed, 6354 insertions(+), 5963 deletions(-)
> create mode 100644 target-s390x/insn-data.def
> create mode 100644 target-s390x/insn-format.def
>
^ permalink raw reply [flat|nested] 152+ messages in thread
* Re: [Qemu-devel] [PATCH v2 000/147] target-s390 reorg
2012-11-16 0:09 ` [Qemu-devel] [PATCH v2 000/147] target-s390 reorg Richard Henderson
@ 2012-11-19 11:40 ` Alexander Graf
0 siblings, 0 replies; 152+ messages in thread
From: Alexander Graf @ 2012-11-19 11:40 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
Hey Richard,
On 16.11.2012, at 01:09, Richard Henderson wrote:
> Ping.
>
> I've updated the branch at
>
> git://repo.or.cz/qemu/rth.git s390-reorg
>
> to rebase vs mainline (ce34cf72fe508b27a78f83c184142e8d1e6a048a).
> There are minor changes due to Aurel's TCG_CALL_NO_* rewrite, but
> is otherwise unchanged.
>
> I can re-post the 140+ patches if required...
I'd like to leave the series out for 1.3, but get it in early in the 1.4 development cycle, so that we can have actual code exposure during the development cycle :).
Fundamentally, I don't object to your changes. I find the new code very hard to read, but considering that after this rewrite you authored 99% of the code base, I'd basically just declare you the maintainer for the s390 tcg target and then you have to worry about that bit yourself ;).
Alex
>
>
> r~
>
> On 2012-09-27 15:39, Richard Henderson wrote:
>> Tons of changes since v1. I believe I incorproated all of the feedback
>> that I received. The patch set is relative to the "TCGCond" patch set
>> that I sent out earlier this week. Both trees are available at
>>
>> git://repo.or.cz/qemu/rth.git tcg-cond
>> git://repo.or.cz/qemu/rth.git s390-reorg
>>
>> This passes the gcc testsuite in userland with no unexpected failures
>> (considering anything that touches threads to be "expected"). It boots
>> a debian system image as well as (or as poorly as) mainline -- agraf
>> and I had a rather long session re those failures on IRC the other day.
>>
>> Note that patches 2-11 are bug fixes for the *existing* code base. I
>> found that I had to fix those in order to be able to properly bisect
>> problems in the later patches.
>>
>> The last 7 patches are new, and improve the generated code for a
>> variety of stuff I noticed while staring at dumps. Not that the
>> last 25 patches or so made it to the list last time...
>>
>>
>> r~
>>
>>
>> Alexander Graf (1):
>> s390x: fix -initrd in virtio machine
>>
>> Richard Henderson (146):
>> tcg: Add TCGV_IS_UNUSED_*
>> 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: Register helpers
>> target-s390: Fix SACF exit
>> target-s390: Fix BCR
>> target-s390: Tidy unconditional BRCL
>> target-s390: Fix PSW_MASK handling
>> 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 HALFWORD, SINGLE
>> target-s390: Convert 32-bit MULTIPLY, MULTIPLY LOGICAL
>> target-s390: Convert 64-bit MULTIPLY LOGICAL
>> 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
>> target-s390: Implement LCDFR
>> softfloat: Fix uint64_to_float64
>> softfloat: Implement uint64_to_float128
>> target-s390: Use uint64_to_float128
>> target-s390: Implement SET ROUNDING MODE
>> target-s390: Implement LOAD/SET FP AND SIGNAL
>> target-s390: Fix cpu_clone_regs
>> target-s390: Optimize XC
>> target-s390: Optmize emitting discards
>> target-s390: Tidy comparisons
>> target-s390: Optimize ADDU/SUBU CC testing
>> target-s390: Optimize ADDC/SUBB
>> target-s390: Optimize get_address
>> target-s390: Perform COMPARE AND SWAP inline
>>
>> fpu/softfloat.c | 15 +-
>> fpu/softfloat.h | 1 +
>> gdbstub.c | 78 +-
>> hw/s390-virtio.c | 4 +-
>> linux-user/main.c | 140 +-
>> linux-user/s390x/syscall.h | 2 +-
>> s390-dis.c | 173 +-
>> target-s390x/cc_helper.c | 335 +-
>> target-s390x/cpu.h | 167 +-
>> target-s390x/fpu_helper.c | 960 ++---
>> target-s390x/helper.c | 67 +-
>> target-s390x/helper.h | 188 +-
>> target-s390x/insn-data.def | 813 ++++
>> target-s390x/insn-format.def | 55 +
>> target-s390x/int_helper.c | 176 +-
>> target-s390x/mem_helper.c | 359 +-
>> target-s390x/misc_helper.c | 97 +-
>> target-s390x/translate.c | 8684 ++++++++++++++++++++----------------------
>> tcg/tcg.h | 3 +
>> 19 files changed, 6354 insertions(+), 5963 deletions(-)
>> create mode 100644 target-s390x/insn-data.def
>> create mode 100644 target-s390x/insn-format.def
>>
>
^ permalink raw reply [flat|nested] 152+ messages in thread