target-mips: add MSA VEC/2R format instructions
add MSA VEC/2R format instructions Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
This commit is contained in:
		
							parent
							
								
									7d05b9c86f
								
							
						
					
					
						commit
						cbe50b9a8e
					
				| @ -900,3 +900,15 @@ DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) | ||||
| DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) | ||||
| DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) | ||||
| DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) | ||||
| 
 | ||||
| DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) | ||||
| DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) | ||||
|  | ||||
| @ -114,6 +114,34 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, | ||||
|     msa_move_v(pwd, pwx); | ||||
| } | ||||
| 
 | ||||
| #define MSA_FN_VECTOR(FUNC, DEST, OPERATION)                            \ | ||||
| void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws,   \ | ||||
|         uint32_t wt)                                                    \ | ||||
| {                                                                       \ | ||||
|     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \ | ||||
|     wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \ | ||||
|     wr_t *pwt = &(env->active_fpu.fpr[wt].wr);                          \ | ||||
|     uint32_t i;                                                         \ | ||||
|     for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {                      \ | ||||
|         DEST = OPERATION;                                               \ | ||||
|     }                                                                   \ | ||||
| } | ||||
| 
 | ||||
| MSA_FN_VECTOR(and_v, pwd->d[i], pws->d[i] & pwt->d[i]) | ||||
| MSA_FN_VECTOR(or_v, pwd->d[i], pws->d[i] | pwt->d[i]) | ||||
| MSA_FN_VECTOR(nor_v, pwd->d[i], ~(pws->d[i] | pwt->d[i])) | ||||
| MSA_FN_VECTOR(xor_v, pwd->d[i], pws->d[i] ^ pwt->d[i]) | ||||
| MSA_FN_VECTOR(bmnz_v, pwd->d[i], | ||||
|         BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) | ||||
| MSA_FN_VECTOR(bmz_v, pwd->d[i], | ||||
|         BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) | ||||
| MSA_FN_VECTOR(bsel_v, pwd->d[i], | ||||
|         BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) | ||||
| #undef BIT_MOVE_IF_NOT_ZERO | ||||
| #undef BIT_MOVE_IF_ZERO | ||||
| #undef BIT_SELECT | ||||
| #undef MSA_FN_VECTOR | ||||
| 
 | ||||
| static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) | ||||
| { | ||||
|     return arg1 + arg2; | ||||
| @ -1359,6 +1387,118 @@ void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws) | ||||
|     msa_move_v(pwd, pws); | ||||
| } | ||||
| 
 | ||||
| static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg) | ||||
| { | ||||
|     uint64_t x; | ||||
| 
 | ||||
|     x = UNSIGNED(arg, df); | ||||
| 
 | ||||
|     x = (x & 0x5555555555555555ULL) + ((x >>  1) & 0x5555555555555555ULL); | ||||
|     x = (x & 0x3333333333333333ULL) + ((x >>  2) & 0x3333333333333333ULL); | ||||
|     x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >>  4) & 0x0F0F0F0F0F0F0F0FULL); | ||||
|     x = (x & 0x00FF00FF00FF00FFULL) + ((x >>  8) & 0x00FF00FF00FF00FFULL); | ||||
|     x = (x & 0x0000FFFF0000FFFFULL) + ((x >> 16) & 0x0000FFFF0000FFFFULL); | ||||
|     x = (x & 0x00000000FFFFFFFFULL) + ((x >> 32)); | ||||
| 
 | ||||
|     return x; | ||||
| } | ||||
| 
 | ||||
| static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg) | ||||
| { | ||||
|     uint64_t x, y; | ||||
|     int n, c; | ||||
| 
 | ||||
|     x = UNSIGNED(arg, df); | ||||
|     n = DF_BITS(df); | ||||
|     c = DF_BITS(df) / 2; | ||||
| 
 | ||||
|     do { | ||||
|         y = x >> c; | ||||
|         if (y != 0) { | ||||
|             n = n - c; | ||||
|             x = y; | ||||
|         } | ||||
|         c = c >> 1; | ||||
|     } while (c != 0); | ||||
| 
 | ||||
|     return n - x; | ||||
| } | ||||
| 
 | ||||
| static inline int64_t msa_nloc_df(uint32_t df, int64_t arg) | ||||
| { | ||||
|     return msa_nlzc_df(df, UNSIGNED((~arg), df)); | ||||
| } | ||||
| 
 | ||||
| void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd, | ||||
|                         uint32_t rs) | ||||
| { | ||||
|     wr_t *pwd = &(env->active_fpu.fpr[wd].wr); | ||||
|     uint32_t i; | ||||
| 
 | ||||
|     switch (df) { | ||||
|     case DF_BYTE: | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { | ||||
|             pwd->b[i] = (int8_t)env->active_tc.gpr[rs]; | ||||
|         } | ||||
|         break; | ||||
|     case DF_HALF: | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { | ||||
|             pwd->h[i] = (int16_t)env->active_tc.gpr[rs]; | ||||
|         } | ||||
|         break; | ||||
|     case DF_WORD: | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { | ||||
|             pwd->w[i] = (int32_t)env->active_tc.gpr[rs]; | ||||
|         } | ||||
|         break; | ||||
|     case DF_DOUBLE: | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { | ||||
|             pwd->d[i] = (int64_t)env->active_tc.gpr[rs]; | ||||
|         } | ||||
|        break; | ||||
|     default: | ||||
|         assert(0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #define MSA_UNOP_DF(func) \ | ||||
| void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df,         \ | ||||
|                               uint32_t wd, uint32_t ws)                 \ | ||||
| {                                                                       \ | ||||
|     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \ | ||||
|     wr_t *pws = &(env->active_fpu.fpr[ws].wr);                          \ | ||||
|     uint32_t i;                                                         \ | ||||
|                                                                         \ | ||||
|     switch (df) {                                                       \ | ||||
|     case DF_BYTE:                                                       \ | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {                    \ | ||||
|             pwd->b[i] = msa_ ## func ## _df(df, pws->b[i]);             \ | ||||
|         }                                                               \ | ||||
|         break;                                                          \ | ||||
|     case DF_HALF:                                                       \ | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {                    \ | ||||
|             pwd->h[i] = msa_ ## func ## _df(df, pws->h[i]);             \ | ||||
|         }                                                               \ | ||||
|         break;                                                          \ | ||||
|     case DF_WORD:                                                       \ | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {                    \ | ||||
|             pwd->w[i] = msa_ ## func ## _df(df, pws->w[i]);             \ | ||||
|         }                                                               \ | ||||
|         break;                                                          \ | ||||
|     case DF_DOUBLE:                                                     \ | ||||
|         for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {                  \ | ||||
|             pwd->d[i] = msa_ ## func ## _df(df, pws->d[i]);             \ | ||||
|         }                                                               \ | ||||
|         break;                                                          \ | ||||
|     default:                                                            \ | ||||
|         assert(0);                                                      \ | ||||
|     }                                                                   \ | ||||
| } | ||||
| 
 | ||||
| MSA_UNOP_DF(nlzc) | ||||
| MSA_UNOP_DF(nloc) | ||||
| MSA_UNOP_DF(pcnt) | ||||
| 
 | ||||
| #define FLOAT_ONE32 make_float32(0x3f8 << 20) | ||||
| #define FLOAT_ONE64 make_float64(0x3ffULL << 52) | ||||
| 
 | ||||
|  | ||||
| @ -18053,6 +18053,116 @@ static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx) | ||||
|     tcg_temp_free_i32(tdf); | ||||
| } | ||||
| 
 | ||||
| static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx) | ||||
| { | ||||
| #define MASK_MSA_2R(op)     (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \ | ||||
|                             (op & (0x7 << 18))) | ||||
|     uint8_t wt = (ctx->opcode >> 16) & 0x1f; | ||||
|     uint8_t ws = (ctx->opcode >> 11) & 0x1f; | ||||
|     uint8_t wd = (ctx->opcode >> 6) & 0x1f; | ||||
|     uint8_t df = (ctx->opcode >> 16) & 0x3; | ||||
|     TCGv_i32 twd = tcg_const_i32(wd); | ||||
|     TCGv_i32 tws = tcg_const_i32(ws); | ||||
|     TCGv_i32 twt = tcg_const_i32(wt); | ||||
|     TCGv_i32 tdf = tcg_const_i32(df); | ||||
| 
 | ||||
|     switch (MASK_MSA_2R(ctx->opcode)) { | ||||
|     case OPC_FILL_df: | ||||
| #if !defined(TARGET_MIPS64) | ||||
|         /* Double format valid only for MIPS64 */ | ||||
|         if (df == DF_DOUBLE) { | ||||
|             generate_exception(ctx, EXCP_RI); | ||||
|             break; | ||||
|         } | ||||
| #endif | ||||
|         gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */ | ||||
|         break; | ||||
|     case OPC_PCNT_df: | ||||
|         gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws); | ||||
|         break; | ||||
|     case OPC_NLOC_df: | ||||
|         gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws); | ||||
|         break; | ||||
|     case OPC_NLZC_df: | ||||
|         gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws); | ||||
|         break; | ||||
|     default: | ||||
|         MIPS_INVAL("MSA instruction"); | ||||
|         generate_exception(ctx, EXCP_RI); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     tcg_temp_free_i32(twd); | ||||
|     tcg_temp_free_i32(tws); | ||||
|     tcg_temp_free_i32(twt); | ||||
|     tcg_temp_free_i32(tdf); | ||||
| } | ||||
| 
 | ||||
| static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx) | ||||
| { | ||||
| #define MASK_MSA_VEC(op)    (MASK_MSA_MINOR(op) | (op & (0x1f << 21))) | ||||
|     uint8_t wt = (ctx->opcode >> 16) & 0x1f; | ||||
|     uint8_t ws = (ctx->opcode >> 11) & 0x1f; | ||||
|     uint8_t wd = (ctx->opcode >> 6) & 0x1f; | ||||
|     TCGv_i32 twd = tcg_const_i32(wd); | ||||
|     TCGv_i32 tws = tcg_const_i32(ws); | ||||
|     TCGv_i32 twt = tcg_const_i32(wt); | ||||
| 
 | ||||
|     switch (MASK_MSA_VEC(ctx->opcode)) { | ||||
|     case OPC_AND_V: | ||||
|         gen_helper_msa_and_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     case OPC_OR_V: | ||||
|         gen_helper_msa_or_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     case OPC_NOR_V: | ||||
|         gen_helper_msa_nor_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     case OPC_XOR_V: | ||||
|         gen_helper_msa_xor_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     case OPC_BMNZ_V: | ||||
|         gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     case OPC_BMZ_V: | ||||
|         gen_helper_msa_bmz_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     case OPC_BSEL_V: | ||||
|         gen_helper_msa_bsel_v(cpu_env, twd, tws, twt); | ||||
|         break; | ||||
|     default: | ||||
|         MIPS_INVAL("MSA instruction"); | ||||
|         generate_exception(ctx, EXCP_RI); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     tcg_temp_free_i32(twd); | ||||
|     tcg_temp_free_i32(tws); | ||||
|     tcg_temp_free_i32(twt); | ||||
| } | ||||
| 
 | ||||
| static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx) | ||||
| { | ||||
|     switch (MASK_MSA_VEC(ctx->opcode)) { | ||||
|     case OPC_AND_V: | ||||
|     case OPC_OR_V: | ||||
|     case OPC_NOR_V: | ||||
|     case OPC_XOR_V: | ||||
|     case OPC_BMNZ_V: | ||||
|     case OPC_BMZ_V: | ||||
|     case OPC_BSEL_V: | ||||
|         gen_msa_vec_v(env, ctx); | ||||
|         break; | ||||
|     case OPC_MSA_2R: | ||||
|         gen_msa_2r(env, ctx); | ||||
|         break; | ||||
|     default: | ||||
|         MIPS_INVAL("MSA instruction"); | ||||
|         generate_exception(ctx, EXCP_RI); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void gen_msa(CPUMIPSState *env, DisasContext *ctx) | ||||
| { | ||||
|     uint32_t opcode = ctx->opcode; | ||||
| @ -18092,6 +18202,9 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) | ||||
|     case OPC_MSA_3RF_1C: | ||||
|         gen_msa_3rf(env, ctx); | ||||
|         break; | ||||
|     case OPC_MSA_VEC: | ||||
|         gen_msa_vec(env, ctx); | ||||
|         break; | ||||
|     default: | ||||
|         MIPS_INVAL("MSA instruction"); | ||||
|         generate_exception(ctx, EXCP_RI); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Yongbok Kim
						Yongbok Kim