s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY
Use a new CC helper to calculate the CC lazily if needed. While the PoP mentions that "A 32-bit unsigned binary integer" is placed into the first operand, there is no word telling that the other 32 bits (high part) are left untouched. Maybe the other 32-bit are unpredictable. So store 64 bit for now. Bit magic courtesy of Richard. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20190225200318.16102-8-david@redhat.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
		
				
					committed by
					
						 Cornelia Huck
						Cornelia Huck
					
				
			
			
				
	
			
			
			
						parent
						
							86b59624c4
						
					
				
				
					commit
					6d9303322e
				
			| @@ -397,6 +397,11 @@ static uint32_t cc_calc_flogr(uint64_t dst) | ||||
|     return dst ? 2 : 0; | ||||
| } | ||||
|  | ||||
| static uint32_t cc_calc_lcbb(uint64_t dst) | ||||
| { | ||||
|     return dst == 16 ? 0 : 3; | ||||
| } | ||||
|  | ||||
| static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, | ||||
|                                   uint64_t src, uint64_t dst, uint64_t vr) | ||||
| { | ||||
| @@ -506,6 +511,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, | ||||
|     case CC_OP_FLOGR: | ||||
|         r = cc_calc_flogr(dst); | ||||
|         break; | ||||
|     case CC_OP_LCBB: | ||||
|         r = cc_calc_lcbb(dst); | ||||
|         break; | ||||
|  | ||||
|     case CC_OP_NZ_F32: | ||||
|         r = set_cc_nz_f32(dst); | ||||
|   | ||||
| @@ -417,6 +417,7 @@ const char *cc_name(enum cc_op cc_op) | ||||
|         [CC_OP_SLA_32]    = "CC_OP_SLA_32", | ||||
|         [CC_OP_SLA_64]    = "CC_OP_SLA_64", | ||||
|         [CC_OP_FLOGR]     = "CC_OP_FLOGR", | ||||
|         [CC_OP_LCBB]      = "CC_OP_LCBB", | ||||
|     }; | ||||
|  | ||||
|     return cc_names[cc_op]; | ||||
|   | ||||
| @@ -479,6 +479,8 @@ | ||||
|     F(0xb313, LCDBR,   RRE,   Z,   0, f2, new, f1, negf64, f64, IF_BFP) | ||||
|     F(0xb343, LCXBR,   RRE,   Z,   x2h, x2l, new_P, x1, negf128, f128, IF_BFP) | ||||
|     F(0xb373, LCDFR,   RRE,   FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2) | ||||
| /* LOAD COUNT TO BLOCK BOUNDARY */ | ||||
|     C(0xe727, LCBB,    RXE,   V,   la2, 0, r1, 0, lcbb, 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) | ||||
|   | ||||
| @@ -236,6 +236,7 @@ enum cc_op { | ||||
|     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_LCBB,                 /* load count to block boundary */ | ||||
|     CC_OP_MAX | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -557,6 +557,7 @@ static void gen_op_calc_cc(DisasContext *s) | ||||
|     case CC_OP_NZ_F32: | ||||
|     case CC_OP_NZ_F64: | ||||
|     case CC_OP_FLOGR: | ||||
|     case CC_OP_LCBB: | ||||
|         /* 1 argument */ | ||||
|         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy); | ||||
|         break; | ||||
| @@ -3142,6 +3143,23 @@ static DisasJumpType op_lzrb(DisasContext *s, DisasOps *o) | ||||
|     return DISAS_NEXT; | ||||
| } | ||||
|  | ||||
| static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o) | ||||
| { | ||||
|     const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6)); | ||||
|  | ||||
|     if (get_field(s->fields, m3) > 6) { | ||||
|         gen_program_exception(s, PGM_SPECIFICATION); | ||||
|         return DISAS_NORETURN; | ||||
|     } | ||||
|  | ||||
|     tcg_gen_ori_i64(o->addr1, o->addr1, -block_size); | ||||
|     tcg_gen_neg_i64(o->addr1, o->addr1); | ||||
|     tcg_gen_movi_i64(o->out, 16); | ||||
|     tcg_gen_umin_i64(o->out, o->out, o->addr1); | ||||
|     gen_op_update1_cc_i64(s, CC_OP_LCBB, o->out); | ||||
|     return DISAS_NEXT; | ||||
| } | ||||
|  | ||||
| static DisasJumpType op_mov2(DisasContext *s, DisasOps *o) | ||||
| { | ||||
|     o->out = o->in2; | ||||
| @@ -5931,6 +5949,7 @@ enum DisasInsnEnum { | ||||
| #define FAC_ECT         S390_FEAT_EXTRACT_CPU_TIME | ||||
| #define FAC_PCI         S390_FEAT_ZPCI /* z/PCI facility */ | ||||
| #define FAC_AIS         S390_FEAT_ADAPTER_INT_SUPPRESSION | ||||
| #define FAC_V           S390_FEAT_VECTOR /* vector facility */ | ||||
|  | ||||
| static const DisasInsn insn_info[] = { | ||||
| #include "insn-data.def" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user