s390 translator bug fixes
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJU0THzAAoJEK0ScMxN0CebpTEIAKv2k1iE/Mj5YeE6ZygepQXg iNe28daFU2XXFKv+DNS0ptPnt+M1NLbFcuyXTOhWnQnpc+Z82i2TecxgqqCMrp4f JjW56WxJR8H7Gdc6CesCigld2QNXOprniEMxZwkCy8KEZa32D22WKb9E/CHOFzeS 3+YqiYlnj52DAm8oS+hVapf0tm+qJLGfgDFEU1MJLCtAVNE5DJclguzi05//W5Go Jx0LClvED5a0rRN4vYFXHRMB9H6QTsG5/HtvYLR5wBUCk6SBcx/2domHSXYKiEfN LS1DjLYArXwjzI3Fr232po8VX3pcG0QrG71kYh9v8GXcvxDUNtQ69DV7p8ZRxZ0= =RqeH -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-tg-s390-20150203' into staging s390 translator bug fixes # gpg: Signature made Tue 03 Feb 2015 20:39:15 GMT using RSA key ID 4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" * remotes/rth/tags/pull-tg-s390-20150203: target-s390x: fix and optimize slb* and slbg* computation of carry/borrow flag target-s390x: support OC and NC in the EX instruction disas/s390.c: Remove unused variables target-s390x: Mark check_privileged() as !CONFIG_USER_ONLY target-s390: Implement ECAG target-s390: Implement LURA, LURAG, STURG target-s390: Fix STURA target-s390: Fix STIDP target-s390: Implement EPSW target-s390: Implement SAM specification exception Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						ec6f25e788
					
				
							
								
								
									
										35
									
								
								disas/s390.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								disas/s390.c
									
									
									
									
									
								
							@ -106,10 +106,6 @@ struct s390_opcode
 | 
				
			|||||||
static const struct s390_opcode s390_opcodes[];
 | 
					static const struct s390_opcode s390_opcodes[];
 | 
				
			||||||
static const int                s390_num_opcodes;
 | 
					static const int                s390_num_opcodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* A opcode format table for the .insn pseudo mnemonic.  */
 | 
					 | 
				
			||||||
static const struct s390_opcode s390_opformats[];
 | 
					 | 
				
			||||||
static const int                s390_num_opformats;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Values defined for the flags field of a struct powerpc_opcode.  */
 | 
					/* Values defined for the flags field of a struct powerpc_opcode.  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The operands table is an array of struct s390_operand.  */
 | 
					/* The operands table is an array of struct s390_operand.  */
 | 
				
			||||||
@ -844,37 +840,6 @@ static const struct s390_operand s390_operands[] =
 | 
				
			|||||||
#define MASK_SIY_DRI     { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
 | 
					#define MASK_SIY_DRI     { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
 | 
				
			||||||
/* QEMU-END */
 | 
					/* QEMU-END */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The opcode formats table (blueprints for .insn pseudo mnemonic).  */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct s390_opcode s390_opformats[] =
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
  { "e",	OP8(0x00LL),	MASK_E,		INSTR_E,	3, 0 },
 | 
					 | 
				
			||||||
  { "ri",	OP8(0x00LL),	MASK_RI_RI,	INSTR_RI_RI,	3, 0 },
 | 
					 | 
				
			||||||
  { "rie",	OP8(0x00LL),	MASK_RIE_RRP,	INSTR_RIE_RRP,	3, 0 },
 | 
					 | 
				
			||||||
  { "ril",	OP8(0x00LL),	MASK_RIL_RP,	INSTR_RIL_RP,	3, 0 },
 | 
					 | 
				
			||||||
  { "rilu",	OP8(0x00LL),	MASK_RIL_RU,	INSTR_RIL_RU,	3, 0 },
 | 
					 | 
				
			||||||
  { "rr",	OP8(0x00LL),	MASK_RR_RR,	INSTR_RR_RR,	3, 0 },
 | 
					 | 
				
			||||||
  { "rre",	OP8(0x00LL),	MASK_RRE_RR,	INSTR_RRE_RR,	3, 0 },
 | 
					 | 
				
			||||||
  { "rrf",	OP8(0x00LL),	MASK_RRF_RURR,	INSTR_RRF_RURR,	3, 0 },
 | 
					 | 
				
			||||||
  { "rs",	OP8(0x00LL),	MASK_RS_RRRD,	INSTR_RS_RRRD,	3, 0 },
 | 
					 | 
				
			||||||
  { "rse",	OP8(0x00LL),	MASK_RSE_RRRD,	INSTR_RSE_RRRD,	3, 0 },
 | 
					 | 
				
			||||||
  { "rsi",	OP8(0x00LL),	MASK_RSI_RRP,	INSTR_RSI_RRP,	3, 0 },
 | 
					 | 
				
			||||||
  { "rsy",	OP8(0x00LL),	MASK_RSY_RRRD,	INSTR_RSY_RRRD,	3, 3 },
 | 
					 | 
				
			||||||
  { "rx",	OP8(0x00LL),	MASK_RX_RRRD,	INSTR_RX_RRRD,	3, 0 },
 | 
					 | 
				
			||||||
  { "rxe",	OP8(0x00LL),	MASK_RXE_RRRD,	INSTR_RXE_RRRD,	3, 0 },
 | 
					 | 
				
			||||||
  { "rxf",	OP8(0x00LL),	MASK_RXF_RRRDR,	INSTR_RXF_RRRDR,3, 0 },
 | 
					 | 
				
			||||||
  { "rxy",	OP8(0x00LL),	MASK_RXY_RRRD,	INSTR_RXY_RRRD,	3, 3 },
 | 
					 | 
				
			||||||
  { "s",	OP8(0x00LL),	MASK_S_RD,	INSTR_S_RD,	3, 0 },
 | 
					 | 
				
			||||||
  { "si",	OP8(0x00LL),	MASK_SI_URD,	INSTR_SI_URD,	3, 0 },
 | 
					 | 
				
			||||||
  { "siy",	OP8(0x00LL),	MASK_SIY_URD,	INSTR_SIY_URD,	3, 3 },
 | 
					 | 
				
			||||||
  { "ss",	OP8(0x00LL),	MASK_SS_RRRDRD,	INSTR_SS_RRRDRD,3, 0 },
 | 
					 | 
				
			||||||
  { "sse",	OP8(0x00LL),	MASK_SSE_RDRD,	INSTR_SSE_RDRD,	3, 0 },
 | 
					 | 
				
			||||||
  { "ssf",	OP8(0x00LL),	MASK_SSF_RRDRD,	INSTR_SSF_RRDRD,3, 0 },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const int s390_num_opformats =
 | 
					 | 
				
			||||||
  sizeof (s390_opformats) / sizeof (s390_opformats[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* include "s390-opc.tab" generated from opcodes/s390-opc.txt rev 1.17 */
 | 
					/* include "s390-opc.tab" generated from opcodes/s390-opc.txt rev 1.17 */
 | 
				
			||||||
/* The opcode table. This file was generated by s390-mkopc.
 | 
					/* The opcode table. This file was generated by s390-mkopc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -179,16 +179,11 @@ static uint32_t cc_calc_subu_64(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)
 | 
					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);
 | 
					 | 
				
			||||||
    int borrow_out;
 | 
					    int borrow_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* If a2 was ULONG_MAX, and borrow_in, then a2 is logically 65 bits,
 | 
					    if (ar != a1 - a2) {	/* difference means borrow-in */
 | 
				
			||||||
       and we must have had borrow out.  */
 | 
					        borrow_out = (a2 >= a1);
 | 
				
			||||||
    if (borrow_in && a2 == (uint64_t)-1) {
 | 
					 | 
				
			||||||
        borrow_out = 1;
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        a2 += borrow_in;
 | 
					 | 
				
			||||||
        borrow_out = (a2 > a1);
 | 
					        borrow_out = (a2 > a1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -285,16 +280,11 @@ static uint32_t cc_calc_subu_32(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)
 | 
					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);
 | 
					 | 
				
			||||||
    int borrow_out;
 | 
					    int borrow_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* If a2 was UINT_MAX, and borrow_in, then a2 is logically 65 bits,
 | 
					    if (ar != a1 - a2) {	/* difference means borrow-in */
 | 
				
			||||||
       and we must have had borrow out.  */
 | 
					        borrow_out = (a2 >= a1);
 | 
				
			||||||
    if (borrow_in && a2 == (uint32_t)-1) {
 | 
					 | 
				
			||||||
        borrow_out = 1;
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        a2 += borrow_in;
 | 
					 | 
				
			||||||
        borrow_out = (a2 > a1);
 | 
					        borrow_out = (a2 > a1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,9 @@ typedef struct CPUS390XState {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* reset does memset(0) up to here */
 | 
					    /* reset does memset(0) up to here */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int cpu_num;
 | 
					    uint32_t cpu_num;
 | 
				
			||||||
 | 
					    uint32_t machine_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t *storage_keys;
 | 
					    uint8_t *storage_keys;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint64_t tod_offset;
 | 
					    uint64_t tod_offset;
 | 
				
			||||||
 | 
				
			|||||||
@ -111,5 +111,8 @@ DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64)
 | 
				
			|||||||
DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 | 
					DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 | 
				
			||||||
DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
 | 
					DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
 | 
				
			||||||
DEF_HELPER_2(lra, i64, env, i64)
 | 
					DEF_HELPER_2(lra, i64, env, i64)
 | 
				
			||||||
 | 
					DEF_HELPER_FLAGS_2(lura, TCG_CALL_NO_WG, i64, env, i64)
 | 
				
			||||||
 | 
					DEF_HELPER_FLAGS_2(lurag, TCG_CALL_NO_WG, i64, env, i64)
 | 
				
			||||||
DEF_HELPER_FLAGS_3(stura, TCG_CALL_NO_WG, void, env, i64, i64)
 | 
					DEF_HELPER_FLAGS_3(stura, TCG_CALL_NO_WG, void, env, i64, i64)
 | 
				
			||||||
 | 
					DEF_HELPER_FLAGS_3(sturg, TCG_CALL_NO_WG, void, env, i64, i64)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -285,8 +285,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* EXTRACT ACCESS */
 | 
					/* EXTRACT ACCESS */
 | 
				
			||||||
    C(0xb24f, EAR,     RRE,   Z,   0, 0, new, r1_32, ear, 0)
 | 
					    C(0xb24f, EAR,     RRE,   Z,   0, 0, new, r1_32, ear, 0)
 | 
				
			||||||
 | 
					/* EXTRACT CPU ATTRIBUTE */
 | 
				
			||||||
 | 
					    C(0xeb4c, ECAG,    RSY_a, GIE, 0, a2, r1, 0, ecag, 0)
 | 
				
			||||||
/* EXTRACT FPC */
 | 
					/* EXTRACT FPC */
 | 
				
			||||||
    C(0xb38c, EFPC,    RRE,   Z,   0, 0, new, r1_32, efpc, 0)
 | 
					    C(0xb38c, EFPC,    RRE,   Z,   0, 0, new, r1_32, efpc, 0)
 | 
				
			||||||
 | 
					/* EXTRACT PSW */
 | 
				
			||||||
 | 
					    C(0xb98d, EPSW,    RRE,   Z,   0, 0, 0, 0, epsw, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* FIND LEFTMOST ONE */
 | 
					/* FIND LEFTMOST ONE */
 | 
				
			||||||
    C(0xb983, FLOGR,   RRE,   EI,  0, r2_o, r1_P, 0, flogr, 0)
 | 
					    C(0xb983, FLOGR,   RRE,   EI,  0, r2_o, r1_P, 0, flogr, 0)
 | 
				
			||||||
@ -566,6 +570,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* SET ACCESS */
 | 
					/* SET ACCESS */
 | 
				
			||||||
    C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 | 
					    C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 | 
				
			||||||
 | 
					/* SET ADDRESSING MODE */
 | 
				
			||||||
 | 
					    D(0x010c, SAM24,   E,     Z,   0, 0, 0, 0, sam, 0, 0)
 | 
				
			||||||
 | 
					    D(0x010d, SAM31,   E,     Z,   0, 0, 0, 0, sam, 0, 1)
 | 
				
			||||||
 | 
					    D(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, sam, 0, 3)
 | 
				
			||||||
/* SET FPC */
 | 
					/* SET FPC */
 | 
				
			||||||
    C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
 | 
					    C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
 | 
				
			||||||
/* SET FPC AND SIGNAL */
 | 
					/* SET FPC AND SIGNAL */
 | 
				
			||||||
@ -733,6 +741,9 @@
 | 
				
			|||||||
    C(0xb100, LRA,     RX_a,  Z,   0, a2, r1, 0, lra, 0)
 | 
					    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(0xe313, LRAY,    RXY_a, LD,  0, a2, r1, 0, lra, 0)
 | 
				
			||||||
    C(0xe303, LRAG,    RXY_a, Z,   0, a2, r1, 0, lra, 0)
 | 
					    C(0xe303, LRAG,    RXY_a, Z,   0, a2, r1, 0, lra, 0)
 | 
				
			||||||
 | 
					/* LOAD USING REAL ADDRESS */
 | 
				
			||||||
 | 
					    C(0xb24b, LURA,    RRE,   Z,   0, r2, new, r1_32, lura, 0)
 | 
				
			||||||
 | 
					    C(0xb905, LURAG,   RRE,   Z,   0, r2, r1, 0, lurag, 0)
 | 
				
			||||||
/* MOVE TO PRIMARY */
 | 
					/* MOVE TO PRIMARY */
 | 
				
			||||||
    C(0xda00, MVCP,    SS_d,  Z,   la1, a2, 0, 0, mvcp, 0)
 | 
					    C(0xda00, MVCP,    SS_d,  Z,   la1, a2, 0, 0, mvcp, 0)
 | 
				
			||||||
/* MOVE TO SECONDARY */
 | 
					/* MOVE TO SECONDARY */
 | 
				
			||||||
@ -743,10 +754,6 @@
 | 
				
			|||||||
    C(0xb22a, RRBE,    RRE,   Z,   0, r2_o, 0, 0, rrbe, 0)
 | 
					    C(0xb22a, RRBE,    RRE,   Z,   0, r2_o, 0, 0, rrbe, 0)
 | 
				
			||||||
/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
 | 
					/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
 | 
				
			||||||
    C(0xb220, SERVC,   RRE,   Z,   r1_o, r2_o, 0, 0, servc, 0)
 | 
					    C(0xb220, SERVC,   RRE,   Z,   r1_o, r2_o, 0, 0, servc, 0)
 | 
				
			||||||
/* SET ADDRESSING MODE */
 | 
					 | 
				
			||||||
    D(0x010c, SAM24,   E,     Z,   0, 0, 0, 0, sam, 0, 0)
 | 
					 | 
				
			||||||
    D(0x010d, SAM31,   E,     Z,   0, 0, 0, 0, sam, 0, 1)
 | 
					 | 
				
			||||||
    D(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, sam, 0, 3)
 | 
					 | 
				
			||||||
/* SET ADDRESS SPACE CONTROL FAST */
 | 
					/* SET ADDRESS SPACE CONTROL FAST */
 | 
				
			||||||
    C(0xb279, SACF,    S,     Z,   0, a2, 0, 0, sacf, 0)
 | 
					    C(0xb279, SACF,    S,     Z,   0, a2, 0, 0, sacf, 0)
 | 
				
			||||||
/* SET CLOCK */
 | 
					/* SET CLOCK */
 | 
				
			||||||
@ -794,6 +801,7 @@
 | 
				
			|||||||
    C(0xad00, STOSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 | 
					    C(0xad00, STOSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 | 
				
			||||||
/* STORE USING REAL ADDRESS */
 | 
					/* STORE USING REAL ADDRESS */
 | 
				
			||||||
    C(0xb246, STURA,   RRE,   Z,   r1_o, r2_o, 0, 0, stura, 0)
 | 
					    C(0xb246, STURA,   RRE,   Z,   r1_o, r2_o, 0, 0, stura, 0)
 | 
				
			||||||
 | 
					    C(0xb925, STURG,   RRE,   Z,   r1_o, r2_o, 0, 0, sturg, 0)
 | 
				
			||||||
/* TEST PROTECTION */
 | 
					/* TEST PROTECTION */
 | 
				
			||||||
    C(0xe501, TPROT,   SSE,   Z,   la1, a2, 0, 0, tprot, 0)
 | 
					    C(0xe501, TPROT,   SSE,   Z,   la1, a2, 0, 0, tprot, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -490,10 +490,18 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
 | 
				
			|||||||
            helper_mvc(env, l, get_address(env, 0, b1, d1),
 | 
					            helper_mvc(env, l, get_address(env, 0, b1, d1),
 | 
				
			||||||
                       get_address(env, 0, b2, d2));
 | 
					                       get_address(env, 0, b2, d2));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case 0x400:
 | 
				
			||||||
 | 
					            cc = helper_nc(env, l, get_address(env, 0, b1, d1),
 | 
				
			||||||
 | 
					                            get_address(env, 0, b2, d2));
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        case 0x500:
 | 
					        case 0x500:
 | 
				
			||||||
            cc = helper_clc(env, l, get_address(env, 0, b1, d1),
 | 
					            cc = helper_clc(env, l, get_address(env, 0, b1, d1),
 | 
				
			||||||
                            get_address(env, 0, b2, d2));
 | 
					                            get_address(env, 0, b2, d2));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case 0x600:
 | 
				
			||||||
 | 
					            cc = helper_oc(env, l, get_address(env, 0, b1, d1),
 | 
				
			||||||
 | 
					                            get_address(env, 0, b2, d2));
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        case 0x700:
 | 
					        case 0x700:
 | 
				
			||||||
            cc = helper_xc(env, l, get_address(env, 0, b1, d1),
 | 
					            cc = helper_xc(env, l, get_address(env, 0, b1, d1),
 | 
				
			||||||
                           get_address(env, 0, b2, d2));
 | 
					                           get_address(env, 0, b2, d2));
 | 
				
			||||||
@ -1034,12 +1042,34 @@ void HELPER(ptlb)(CPUS390XState *env)
 | 
				
			|||||||
    tlb_flush(CPU(cpu), 1);
 | 
					    tlb_flush(CPU(cpu), 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* load using real address */
 | 
				
			||||||
 | 
					uint64_t HELPER(lura)(CPUS390XState *env, uint64_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CPUState *cs = CPU(s390_env_get_cpu(env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (uint32_t)ldl_phys(cs->as, get_address(env, 0, 0, addr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t HELPER(lurag)(CPUS390XState *env, uint64_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CPUState *cs = CPU(s390_env_get_cpu(env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ldq_phys(cs->as, get_address(env, 0, 0, addr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* store using real address */
 | 
					/* store using real address */
 | 
				
			||||||
void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
 | 
					void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CPUState *cs = CPU(s390_env_get_cpu(env));
 | 
					    CPUState *cs = CPU(s390_env_get_cpu(env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stw_phys(cs->as, get_address(env, 0, 0, addr), (uint32_t)v1);
 | 
					    stl_phys(cs->as, get_address(env, 0, 0, addr), (uint32_t)v1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(sturg)(CPUS390XState *env, uint64_t addr, uint64_t v1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CPUState *cs = CPU(s390_env_get_cpu(env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    stq_phys(cs->as, get_address(env, 0, 0, addr), v1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* load real address */
 | 
					/* load real address */
 | 
				
			||||||
 | 
				
			|||||||
@ -317,12 +317,14 @@ static inline void gen_illegal_opcode(DisasContext *s)
 | 
				
			|||||||
    gen_program_exception(s, PGM_SPECIFICATION);
 | 
					    gen_program_exception(s, PGM_SPECIFICATION);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void check_privileged(DisasContext *s)
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					static void check_privileged(DisasContext *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
 | 
					    if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
 | 
				
			||||||
        gen_program_exception(s, PGM_PRIVILEGED);
 | 
					        gen_program_exception(s, PGM_PRIVILEGED);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
 | 
					static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -2045,12 +2047,37 @@ static ExitStatus op_ear(DisasContext *s, DisasOps *o)
 | 
				
			|||||||
    return NO_EXIT;
 | 
					    return NO_EXIT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ExitStatus op_ecag(DisasContext *s, DisasOps *o)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* No cache information provided.  */
 | 
				
			||||||
 | 
					    tcg_gen_movi_i64(o->out, -1);
 | 
				
			||||||
 | 
					    return NO_EXIT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
 | 
					    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
 | 
				
			||||||
    return NO_EXIT;
 | 
					    return NO_EXIT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ExitStatus op_epsw(DisasContext *s, DisasOps *o)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int r1 = get_field(s->fields, r1);
 | 
				
			||||||
 | 
					    int r2 = get_field(s->fields, r2);
 | 
				
			||||||
 | 
					    TCGv_i64 t = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Note the "subsequently" in the PoO, which implies a defined result
 | 
				
			||||||
 | 
					       if r1 == r2.  Thus we cannot defer these writes to an output hook.  */
 | 
				
			||||||
 | 
					    tcg_gen_shri_i64(t, psw_mask, 32);
 | 
				
			||||||
 | 
					    store_reg32_i64(r1, t);
 | 
				
			||||||
 | 
					    if (r2 != 0) {
 | 
				
			||||||
 | 
					        store_reg32_i64(r2, psw_mask);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tcg_temp_free_i64(t);
 | 
				
			||||||
 | 
					    return NO_EXIT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_ex(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_ex(DisasContext *s, DisasOps *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
 | 
					    /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
 | 
				
			||||||
@ -2460,6 +2487,24 @@ static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
 | 
				
			|||||||
    return NO_EXIT;
 | 
					    return NO_EXIT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					static ExitStatus op_lura(DisasContext *s, DisasOps *o)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    check_privileged(s);
 | 
				
			||||||
 | 
					    potential_page_fault(s);
 | 
				
			||||||
 | 
					    gen_helper_lura(o->out, cpu_env, o->in2);
 | 
				
			||||||
 | 
					    return NO_EXIT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ExitStatus op_lurag(DisasContext *s, DisasOps *o)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    check_privileged(s);
 | 
				
			||||||
 | 
					    potential_page_fault(s);
 | 
				
			||||||
 | 
					    gen_helper_lurag(o->out, cpu_env, o->in2);
 | 
				
			||||||
 | 
					    return NO_EXIT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    o->out = o->in2;
 | 
					    o->out = o->in2;
 | 
				
			||||||
@ -2925,19 +2970,42 @@ static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
 | 
				
			|||||||
    /* Addressing mode has changed, so end the block.  */
 | 
					    /* Addressing mode has changed, so end the block.  */
 | 
				
			||||||
    return EXIT_PC_STALE;
 | 
					    return EXIT_PC_STALE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_sam(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_sam(DisasContext *s, DisasOps *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int sam = s->insn->data;
 | 
					    int sam = s->insn->data;
 | 
				
			||||||
    TCGv_i64 tsam = tcg_const_i64(sam);
 | 
					    TCGv_i64 tsam;
 | 
				
			||||||
 | 
					    uint64_t mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Overwrite PSW_MASK_64 and PSW_MASK_32 */
 | 
					    switch (sam) {
 | 
				
			||||||
 | 
					    case 0:
 | 
				
			||||||
 | 
					        mask = 0xffffff;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
					        mask = 0x7fffffff;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        mask = -1;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Bizzare but true, we check the address of the current insn for the
 | 
				
			||||||
 | 
					       specification exception, not the next to be executed.  Thus the PoO
 | 
				
			||||||
 | 
					       documents that Bad Things Happen two bytes before the end.  */
 | 
				
			||||||
 | 
					    if (s->pc & ~mask) {
 | 
				
			||||||
 | 
					        gen_program_exception(s, PGM_SPECIFICATION);
 | 
				
			||||||
 | 
					        return EXIT_NORETURN;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    s->next_pc &= mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tsam = tcg_const_i64(sam);
 | 
				
			||||||
    tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2);
 | 
					    tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    tcg_temp_free_i64(tsam);
 | 
					    tcg_temp_free_i64(tsam);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Always exit the TB, since we (may have) changed execution mode.  */
 | 
				
			||||||
    return EXIT_PC_STALE;
 | 
					    return EXIT_PC_STALE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_sar(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_sar(DisasContext *s, DisasOps *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -3221,8 +3289,14 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    TCGv_i64 t1 = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    check_privileged(s);
 | 
					    check_privileged(s);
 | 
				
			||||||
    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
 | 
					    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
 | 
				
			||||||
 | 
					    tcg_gen_ld32u_i64(t1, cpu_env, offsetof(CPUS390XState, machine_type));
 | 
				
			||||||
 | 
					    tcg_gen_deposit_i64(o->out, o->out, t1, 32, 32);
 | 
				
			||||||
 | 
					    tcg_temp_free_i64(t1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return NO_EXIT;
 | 
					    return NO_EXIT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3317,6 +3391,14 @@ static ExitStatus op_stura(DisasContext *s, DisasOps *o)
 | 
				
			|||||||
    gen_helper_stura(cpu_env, o->in2, o->in1);
 | 
					    gen_helper_stura(cpu_env, o->in2, o->in1);
 | 
				
			||||||
    return NO_EXIT;
 | 
					    return NO_EXIT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ExitStatus op_sturg(DisasContext *s, DisasOps *o)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    check_privileged(s);
 | 
				
			||||||
 | 
					    potential_page_fault(s);
 | 
				
			||||||
 | 
					    gen_helper_sturg(cpu_env, o->in2, o->in1);
 | 
				
			||||||
 | 
					    return NO_EXIT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ExitStatus op_st8(DisasContext *s, DisasOps *o)
 | 
					static ExitStatus op_st8(DisasContext *s, DisasOps *o)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user