mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-30 19:15:42 +00:00 
			
		
		
		
	s390x/tcg: Implement VECTOR GALOIS FIELD MULTIPLY SUM (AND ACCUMULATE)
A galois field multiplication in field 2 is like binary multiplication, however instead of doing ordinary binary additions, xor's are performed. So no carries are considered. Implement all variants via helpers. s390_vec_sar() and s390_vec_shr() will be reused later on. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com>
This commit is contained in:
		
							parent
							
								
									44951e6b03
								
							
						
					
					
						commit
						697a45d695
					
				| @ -154,6 +154,14 @@ DEF_HELPER_FLAGS_3(gvec_vclz8, TCG_CALL_NO_RWG, void, ptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_3(gvec_vclz16, TCG_CALL_NO_RWG, void, ptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_3(gvec_vctz8, TCG_CALL_NO_RWG, void, ptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_3(gvec_vctz16, TCG_CALL_NO_RWG, void, ptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_4(gvec_vgfm8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_4(gvec_vgfm16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_4(gvec_vgfm32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_4(gvec_vgfm64, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_5(gvec_vgfma8, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_5(gvec_vgfma16, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_5(gvec_vgfma32, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) | ||||
| DEF_HELPER_FLAGS_5(gvec_vgfma64, TCG_CALL_NO_RWG, void, ptr, cptr, cptr, cptr, i32) | ||||
| 
 | ||||
| #ifndef CONFIG_USER_ONLY | ||||
| DEF_HELPER_3(servc, i32, env, i64, i64) | ||||
|  | ||||
| @ -1090,6 +1090,10 @@ | ||||
|     F(0xe752, VCTZ,    VRR_a, V,   0, 0, 0, 0, vctz, 0, IF_VEC) | ||||
| /* VECTOR EXCLUSIVE OR */ | ||||
|     F(0xe76d, VX,      VRR_c, V,   0, 0, 0, 0, vx, 0, IF_VEC) | ||||
| /* VECTOR GALOIS FIELD MULTIPLY SUM */ | ||||
|     F(0xe7b4, VGFM,    VRR_c, V,   0, 0, 0, 0, vgfm, 0, IF_VEC) | ||||
| /* VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE */ | ||||
|     F(0xe7bc, VGFMA,   VRR_d, V,   0, 0, 0, 0, vgfma, 0, IF_VEC) | ||||
| 
 | ||||
| #ifndef CONFIG_USER_ONLY | ||||
| /* COMPARE AND SWAP AND PURGE */ | ||||
|  | ||||
| @ -1483,3 +1483,41 @@ static DisasJumpType op_vx(DisasContext *s, DisasOps *o) | ||||
|                  get_field(s->fields, v3)); | ||||
|     return DISAS_NEXT; | ||||
| } | ||||
| 
 | ||||
| static DisasJumpType op_vgfm(DisasContext *s, DisasOps *o) | ||||
| { | ||||
|     const uint8_t es = get_field(s->fields, m4); | ||||
|     static const GVecGen3 g[4] = { | ||||
|         { .fno = gen_helper_gvec_vgfm8, }, | ||||
|         { .fno = gen_helper_gvec_vgfm16, }, | ||||
|         { .fno = gen_helper_gvec_vgfm32, }, | ||||
|         { .fno = gen_helper_gvec_vgfm64, }, | ||||
|     }; | ||||
| 
 | ||||
|     if (es > ES_64) { | ||||
|         gen_program_exception(s, PGM_SPECIFICATION); | ||||
|         return DISAS_NORETURN; | ||||
|     } | ||||
|     gen_gvec_3(get_field(s->fields, v1), get_field(s->fields, v2), | ||||
|                get_field(s->fields, v3), &g[es]); | ||||
|     return DISAS_NEXT; | ||||
| } | ||||
| 
 | ||||
| static DisasJumpType op_vgfma(DisasContext *s, DisasOps *o) | ||||
| { | ||||
|     const uint8_t es = get_field(s->fields, m5); | ||||
|     static const GVecGen4 g[4] = { | ||||
|         { .fno = gen_helper_gvec_vgfma8, }, | ||||
|         { .fno = gen_helper_gvec_vgfma16, }, | ||||
|         { .fno = gen_helper_gvec_vgfma32, }, | ||||
|         { .fno = gen_helper_gvec_vgfma64, }, | ||||
|     }; | ||||
| 
 | ||||
|     if (es > ES_64) { | ||||
|         gen_program_exception(s, PGM_SPECIFICATION); | ||||
|         return DISAS_NORETURN; | ||||
|     } | ||||
|     gen_gvec_4(get_field(s->fields, v1), get_field(s->fields, v2), | ||||
|                get_field(s->fields, v3), get_field(s->fields, v4), &g[es]); | ||||
|     return DISAS_NEXT; | ||||
| } | ||||
|  | ||||
| @ -15,6 +15,59 @@ | ||||
| #include "vec.h" | ||||
| #include "exec/helper-proto.h" | ||||
| 
 | ||||
| static bool s390_vec_is_zero(const S390Vector *v) | ||||
| { | ||||
|     return !v->doubleword[0] && !v->doubleword[1]; | ||||
| } | ||||
| 
 | ||||
| static void s390_vec_xor(S390Vector *res, const S390Vector *a, | ||||
|                          const S390Vector *b) | ||||
| { | ||||
|     res->doubleword[0] = a->doubleword[0] ^ b->doubleword[0]; | ||||
|     res->doubleword[1] = a->doubleword[1] ^ b->doubleword[1]; | ||||
| } | ||||
| 
 | ||||
| static void s390_vec_shl(S390Vector *d, const S390Vector *a, uint64_t count) | ||||
| { | ||||
|     uint64_t tmp; | ||||
| 
 | ||||
|     g_assert(count < 128); | ||||
|     if (count == 0) { | ||||
|         d->doubleword[0] = a->doubleword[0]; | ||||
|         d->doubleword[1] = a->doubleword[1]; | ||||
|     } else if (count == 64) { | ||||
|         d->doubleword[0] = a->doubleword[1]; | ||||
|         d->doubleword[1] = 0; | ||||
|     } else if (count < 64) { | ||||
|         tmp = extract64(a->doubleword[1], 64 - count, count); | ||||
|         d->doubleword[1] = a->doubleword[1] << count; | ||||
|         d->doubleword[0] = (a->doubleword[0] << count) | tmp; | ||||
|     } else { | ||||
|         d->doubleword[0] = a->doubleword[1] << (count - 64); | ||||
|         d->doubleword[1] = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void s390_vec_shr(S390Vector *d, const S390Vector *a, uint64_t count) | ||||
| { | ||||
|     uint64_t tmp; | ||||
| 
 | ||||
|     g_assert(count < 128); | ||||
|     if (count == 0) { | ||||
|         d->doubleword[0] = a->doubleword[0]; | ||||
|         d->doubleword[1] = a->doubleword[1]; | ||||
|     } else if (count == 64) { | ||||
|         d->doubleword[1] = a->doubleword[0]; | ||||
|         d->doubleword[0] = 0; | ||||
|     } else if (count < 64) { | ||||
|         tmp = a->doubleword[1] >> count; | ||||
|         d->doubleword[1] = deposit64(tmp, 64 - count, count, a->doubleword[0]); | ||||
|         d->doubleword[0] = a->doubleword[0] >> count; | ||||
|     } else { | ||||
|         d->doubleword[1] = a->doubleword[0] >> (count - 64); | ||||
|         d->doubleword[0] = 0; | ||||
|     } | ||||
| } | ||||
| #define DEF_VAVG(BITS)                                                         \ | ||||
| void HELPER(gvec_vavg##BITS)(void *v1, const void *v2, const void *v3,         \ | ||||
|                              uint32_t desc)                                    \ | ||||
| @ -74,3 +127,117 @@ void HELPER(gvec_vctz##BITS)(void *v1, const void *v2, uint32_t desc)          \ | ||||
| } | ||||
| DEF_VCTZ(8) | ||||
| DEF_VCTZ(16) | ||||
| 
 | ||||
| /* like binary multiplication, but XOR instead of addition */ | ||||
| #define DEF_GALOIS_MULTIPLY(BITS, TBITS)                                       \ | ||||
| static uint##TBITS##_t galois_multiply##BITS(uint##TBITS##_t a,                \ | ||||
|                                              uint##TBITS##_t b)                \ | ||||
| {                                                                              \ | ||||
|     uint##TBITS##_t res = 0;                                                   \ | ||||
|                                                                                \ | ||||
|     while (b) {                                                                \ | ||||
|         if (b & 0x1) {                                                         \ | ||||
|             res = res ^ a;                                                     \ | ||||
|         }                                                                      \ | ||||
|         a = a << 1;                                                            \ | ||||
|         b = b >> 1;                                                            \ | ||||
|     }                                                                          \ | ||||
|     return res;                                                                \ | ||||
| } | ||||
| DEF_GALOIS_MULTIPLY(8, 16) | ||||
| DEF_GALOIS_MULTIPLY(16, 32) | ||||
| DEF_GALOIS_MULTIPLY(32, 64) | ||||
| 
 | ||||
| static S390Vector galois_multiply64(uint64_t a, uint64_t b) | ||||
| { | ||||
|     S390Vector res = {}; | ||||
|     S390Vector va = { | ||||
|         .doubleword[1] = a, | ||||
|     }; | ||||
|     S390Vector vb = { | ||||
|         .doubleword[1] = b, | ||||
|     }; | ||||
| 
 | ||||
|     while (!s390_vec_is_zero(&vb)) { | ||||
|         if (vb.doubleword[1] & 0x1) { | ||||
|             s390_vec_xor(&res, &res, &va); | ||||
|         } | ||||
|         s390_vec_shl(&va, &va, 1); | ||||
|         s390_vec_shr(&vb, &vb, 1); | ||||
|     } | ||||
|     return res; | ||||
| } | ||||
| 
 | ||||
| #define DEF_VGFM(BITS, TBITS)                                                  \ | ||||
| void HELPER(gvec_vgfm##BITS)(void *v1, const void *v2, const void *v3,         \ | ||||
|                              uint32_t desc)                                    \ | ||||
| {                                                                              \ | ||||
|     int i;                                                                     \ | ||||
|                                                                                \ | ||||
|     for (i = 0; i < (128 / TBITS); i++) {                                      \ | ||||
|         uint##BITS##_t a = s390_vec_read_element##BITS(v2, i * 2);             \ | ||||
|         uint##BITS##_t b = s390_vec_read_element##BITS(v3, i * 2);             \ | ||||
|         uint##TBITS##_t d = galois_multiply##BITS(a, b);                       \ | ||||
|                                                                                \ | ||||
|         a = s390_vec_read_element##BITS(v2, i * 2 + 1);                        \ | ||||
|         b = s390_vec_read_element##BITS(v3, i * 2 + 1);                        \ | ||||
|         d = d ^ galois_multiply32(a, b);                                       \ | ||||
|         s390_vec_write_element##TBITS(v1, i, d);                               \ | ||||
|     }                                                                          \ | ||||
| } | ||||
| DEF_VGFM(8, 16) | ||||
| DEF_VGFM(16, 32) | ||||
| DEF_VGFM(32, 64) | ||||
| 
 | ||||
| void HELPER(gvec_vgfm64)(void *v1, const void *v2, const void *v3, | ||||
|                          uint32_t desc) | ||||
| { | ||||
|     S390Vector tmp1, tmp2; | ||||
|     uint64_t a, b; | ||||
| 
 | ||||
|     a = s390_vec_read_element64(v2, 0); | ||||
|     b = s390_vec_read_element64(v3, 0); | ||||
|     tmp1 = galois_multiply64(a, b); | ||||
|     a = s390_vec_read_element64(v2, 1); | ||||
|     b = s390_vec_read_element64(v3, 1); | ||||
|     tmp2 = galois_multiply64(a, b); | ||||
|     s390_vec_xor(v1, &tmp1, &tmp2); | ||||
| } | ||||
| 
 | ||||
| #define DEF_VGFMA(BITS, TBITS)                                                 \ | ||||
| void HELPER(gvec_vgfma##BITS)(void *v1, const void *v2, const void *v3,        \ | ||||
|                               const void *v4, uint32_t desc)                   \ | ||||
| {                                                                              \ | ||||
|     int i;                                                                     \ | ||||
|                                                                                \ | ||||
|     for (i = 0; i < (128 / TBITS); i++) {                                      \ | ||||
|         uint##BITS##_t a = s390_vec_read_element##BITS(v2, i * 2);             \ | ||||
|         uint##BITS##_t b = s390_vec_read_element##BITS(v3, i * 2);             \ | ||||
|         uint##TBITS##_t d = galois_multiply##BITS(a, b);                       \ | ||||
|                                                                                \ | ||||
|         a = s390_vec_read_element##BITS(v2, i * 2 + 1);                        \ | ||||
|         b = s390_vec_read_element##BITS(v3, i * 2 + 1);                        \ | ||||
|         d = d ^ galois_multiply32(a, b);                                       \ | ||||
|         d = d ^ s390_vec_read_element##TBITS(v4, i);                           \ | ||||
|         s390_vec_write_element##TBITS(v1, i, d);                               \ | ||||
|     }                                                                          \ | ||||
| } | ||||
| DEF_VGFMA(8, 16) | ||||
| DEF_VGFMA(16, 32) | ||||
| DEF_VGFMA(32, 64) | ||||
| 
 | ||||
| void HELPER(gvec_vgfma64)(void *v1, const void *v2, const void *v3, | ||||
|                           const void *v4, uint32_t desc) | ||||
| { | ||||
|     S390Vector tmp1, tmp2; | ||||
|     uint64_t a, b; | ||||
| 
 | ||||
|     a = s390_vec_read_element64(v2, 0); | ||||
|     b = s390_vec_read_element64(v3, 0); | ||||
|     tmp1 = galois_multiply64(a, b); | ||||
|     a = s390_vec_read_element64(v2, 1); | ||||
|     b = s390_vec_read_element64(v3, 1); | ||||
|     tmp2 = galois_multiply64(a, b); | ||||
|     s390_vec_xor(&tmp1, &tmp1, &tmp2); | ||||
|     s390_vec_xor(v1, &tmp1, v4); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 David Hildenbrand
						David Hildenbrand