Commit 182608d44cc64bfec3f82e7895b7572db60b7c92

Authored by aurel32
1 parent 74637406

target-ppc: convert 405 MAC instructions to TCG

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5591 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/op.c
@@ -326,34 +326,6 @@ void OPPROTO op_store_fpscr (void) @@ -326,34 +326,6 @@ void OPPROTO op_store_fpscr (void)
326 RETURN(); 326 RETURN();
327 } 327 }
328 328
329 -/*** Integer arithmetic ***/  
330 -/* add */  
331 -void OPPROTO op_check_addo (void)  
332 -{  
333 - int ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &  
334 - ((uint32_t)T2 ^ (uint32_t)T0)) >> 31;  
335 - if (ov) {  
336 - env->xer |= (1 << XER_OV) | (1 << XER_SO);  
337 - } else {  
338 - env->xer &= ~(1 << XER_OV);  
339 - }  
340 - RETURN();  
341 -}  
342 -  
343 -#if defined(TARGET_PPC64)  
344 -void OPPROTO op_check_addo_64 (void)  
345 -{  
346 - int ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &  
347 - ((uint64_t)T2 ^ (uint64_t)T0)) >> 63;  
348 - if (ov) {  
349 - env->xer |= (1 << XER_OV) | (1 << XER_SO);  
350 - } else {  
351 - env->xer &= ~(1 << XER_OV);  
352 - }  
353 - RETURN();  
354 -}  
355 -#endif  
356 -  
357 /*** Integer shift ***/ 329 /*** Integer shift ***/
358 void OPPROTO op_srli_T1 (void) 330 void OPPROTO op_srli_T1 (void)
359 { 331 {
@@ -1062,73 +1034,6 @@ void OPPROTO op_602_mfrom (void) @@ -1062,73 +1034,6 @@ void OPPROTO op_602_mfrom (void)
1062 #endif 1034 #endif
1063 1035
1064 /* PowerPC 4xx specific micro-ops */ 1036 /* PowerPC 4xx specific micro-ops */
1065 -void OPPROTO op_405_add_T0_T2 (void)  
1066 -{  
1067 - T0 = (int32_t)T0 + (int32_t)T2;  
1068 - RETURN();  
1069 -}  
1070 -  
1071 -void OPPROTO op_405_mulchw (void)  
1072 -{  
1073 - T0 = ((int16_t)T0) * ((int16_t)(T1 >> 16));  
1074 - RETURN();  
1075 -}  
1076 -  
1077 -void OPPROTO op_405_mulchwu (void)  
1078 -{  
1079 - T0 = ((uint16_t)T0) * ((uint16_t)(T1 >> 16));  
1080 - RETURN();  
1081 -}  
1082 -  
1083 -void OPPROTO op_405_mulhhw (void)  
1084 -{  
1085 - T0 = ((int16_t)(T0 >> 16)) * ((int16_t)(T1 >> 16));  
1086 - RETURN();  
1087 -}  
1088 -  
1089 -void OPPROTO op_405_mulhhwu (void)  
1090 -{  
1091 - T0 = ((uint16_t)(T0 >> 16)) * ((uint16_t)(T1 >> 16));  
1092 - RETURN();  
1093 -}  
1094 -  
1095 -void OPPROTO op_405_mullhw (void)  
1096 -{  
1097 - T0 = ((int16_t)T0) * ((int16_t)T1);  
1098 - RETURN();  
1099 -}  
1100 -  
1101 -void OPPROTO op_405_mullhwu (void)  
1102 -{  
1103 - T0 = ((uint16_t)T0) * ((uint16_t)T1);  
1104 - RETURN();  
1105 -}  
1106 -  
1107 -void OPPROTO op_405_check_sat (void)  
1108 -{  
1109 - do_405_check_sat();  
1110 - RETURN();  
1111 -}  
1112 -  
1113 -void OPPROTO op_405_check_ovu (void)  
1114 -{  
1115 - if (likely(T0 >= T2)) {  
1116 - env->xer &= ~(1 << XER_OV);  
1117 - } else {  
1118 - env->xer |= (1 << XER_OV) | (1 << XER_SO);  
1119 - }  
1120 - RETURN();  
1121 -}  
1122 -  
1123 -void OPPROTO op_405_check_satu (void)  
1124 -{  
1125 - if (unlikely(T0 < T2)) {  
1126 - /* Saturate result */  
1127 - T0 = UINT32_MAX;  
1128 - }  
1129 - RETURN();  
1130 -}  
1131 -  
1132 void OPPROTO op_load_dcr (void) 1037 void OPPROTO op_load_dcr (void)
1133 { 1038 {
1134 do_load_dcr(); 1039 do_load_dcr();
target-ppc/op_helper.c
@@ -1510,18 +1510,6 @@ void do_op_602_mfrom (void) @@ -1510,18 +1510,6 @@ void do_op_602_mfrom (void)
1510 1510
1511 /*****************************************************************************/ 1511 /*****************************************************************************/
1512 /* Embedded PowerPC specific helpers */ 1512 /* Embedded PowerPC specific helpers */
1513 -void do_405_check_sat (void)  
1514 -{  
1515 - if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||  
1516 - !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {  
1517 - /* Saturate result */  
1518 - if (T2 >> 31) {  
1519 - T0 = INT32_MIN;  
1520 - } else {  
1521 - T0 = INT32_MAX;  
1522 - }  
1523 - }  
1524 -}  
1525 1513
1526 /* XXX: to be improved to check access rights when in user-mode */ 1514 /* XXX: to be improved to check access rights when in user-mode */
1527 void do_load_dcr (void) 1515 void do_load_dcr (void)
target-ppc/op_helper.h
@@ -144,7 +144,6 @@ void do_440_tlbwe (int word); @@ -144,7 +144,6 @@ void do_440_tlbwe (int word);
144 #endif 144 #endif
145 145
146 /* PowerPC 4xx specific helpers */ 146 /* PowerPC 4xx specific helpers */
147 -void do_405_check_sat (void);  
148 void do_load_dcr (void); 147 void do_load_dcr (void);
149 void do_store_dcr (void); 148 void do_store_dcr (void);
150 #if !defined(CONFIG_USER_ONLY) 149 #if !defined(CONFIG_USER_ONLY)
target-ppc/translate.c
@@ -5214,8 +5214,11 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, @@ -5214,8 +5214,11 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5214 int opc2, int opc3, 5214 int opc2, int opc3,
5215 int ra, int rb, int rt, int Rc) 5215 int ra, int rb, int rt, int Rc)
5216 { 5216 {
5217 - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[ra]);  
5218 - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]); 5217 + TCGv t0, t1;
  5218 +
  5219 + t0 = tcg_temp_local_new(TCG_TYPE_TL);
  5220 + t1 = tcg_temp_local_new(TCG_TYPE_TL);
  5221 +
5219 switch (opc3 & 0x0D) { 5222 switch (opc3 & 0x0D) {
5220 case 0x05: 5223 case 0x05:
5221 /* macchw - macchw. - macchwo - macchwo. */ 5224 /* macchw - macchw. - macchwo - macchwo. */
@@ -5223,13 +5226,17 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, @@ -5223,13 +5226,17 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5223 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */ 5226 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5224 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */ 5227 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5225 /* mulchw - mulchw. */ 5228 /* mulchw - mulchw. */
5226 - gen_op_405_mulchw(); 5229 + tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
  5230 + tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
  5231 + tcg_gen_ext16s_tl(t1, t1);
5227 break; 5232 break;
5228 case 0x04: 5233 case 0x04:
5229 /* macchwu - macchwu. - macchwuo - macchwuo. */ 5234 /* macchwu - macchwu. - macchwuo - macchwuo. */
5230 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */ 5235 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5231 /* mulchwu - mulchwu. */ 5236 /* mulchwu - mulchwu. */
5232 - gen_op_405_mulchwu(); 5237 + tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
  5238 + tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
  5239 + tcg_gen_ext16u_tl(t1, t1);
5233 break; 5240 break;
5234 case 0x01: 5241 case 0x01:
5235 /* machhw - machhw. - machhwo - machhwo. */ 5242 /* machhw - machhw. - machhwo - machhwo. */
@@ -5237,13 +5244,19 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, @@ -5237,13 +5244,19 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5237 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */ 5244 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5238 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */ 5245 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5239 /* mulhhw - mulhhw. */ 5246 /* mulhhw - mulhhw. */
5240 - gen_op_405_mulhhw(); 5247 + tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
  5248 + tcg_gen_ext16s_tl(t0, t0);
  5249 + tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
  5250 + tcg_gen_ext16s_tl(t1, t1);
5241 break; 5251 break;
5242 case 0x00: 5252 case 0x00:
5243 /* machhwu - machhwu. - machhwuo - machhwuo. */ 5253 /* machhwu - machhwu. - machhwuo - machhwuo. */
5244 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */ 5254 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5245 /* mulhhwu - mulhhwu. */ 5255 /* mulhhwu - mulhhwu. */
5246 - gen_op_405_mulhhwu(); 5256 + tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
  5257 + tcg_gen_ext16u_tl(t0, t0);
  5258 + tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
  5259 + tcg_gen_ext16u_tl(t1, t1);
5247 break; 5260 break;
5248 case 0x0D: 5261 case 0x0D:
5249 /* maclhw - maclhw. - maclhwo - maclhwo. */ 5262 /* maclhw - maclhw. - maclhwo - maclhwo. */
@@ -5251,43 +5264,70 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx, @@ -5251,43 +5264,70 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5251 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */ 5264 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5252 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */ 5265 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5253 /* mullhw - mullhw. */ 5266 /* mullhw - mullhw. */
5254 - gen_op_405_mullhw(); 5267 + tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
  5268 + tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
5255 break; 5269 break;
5256 case 0x0C: 5270 case 0x0C:
5257 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */ 5271 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5258 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */ 5272 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5259 /* mullhwu - mullhwu. */ 5273 /* mullhwu - mullhwu. */
5260 - gen_op_405_mullhwu(); 5274 + tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
  5275 + tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
5261 break; 5276 break;
5262 } 5277 }
5263 - if (opc2 & 0x02) {  
5264 - /* nmultiply-and-accumulate (0x0E) */  
5265 - tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);  
5266 - }  
5267 if (opc2 & 0x04) { 5278 if (opc2 & 0x04) {
5268 - /* (n)multiply-and-accumulate (0x0C - 0x0E) */  
5269 - tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rt]);  
5270 - tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);  
5271 - gen_op_405_add_T0_T2();  
5272 - }  
5273 - if (opc3 & 0x10) {  
5274 - /* Check overflow */  
5275 - if (opc3 & 0x01)  
5276 - gen_op_check_addo();  
5277 - else  
5278 - gen_op_405_check_ovu();  
5279 - }  
5280 - if (opc3 & 0x02) {  
5281 - /* Saturate */  
5282 - if (opc3 & 0x01)  
5283 - gen_op_405_check_sat();  
5284 - else  
5285 - gen_op_405_check_satu(); 5279 + /* (n)multiply-and-accumulate (0x0C / 0x0E) */
  5280 + tcg_gen_mul_tl(t1, t0, t1);
  5281 + if (opc2 & 0x02) {
  5282 + /* nmultiply-and-accumulate (0x0E) */
  5283 + tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
  5284 + } else {
  5285 + /* multiply-and-accumulate (0x0C) */
  5286 + tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
  5287 + }
  5288 +
  5289 + if (opc3 & 0x12) {
  5290 + /* Check overflow and/or saturate */
  5291 + int l1 = gen_new_label();
  5292 +
  5293 + if (opc3 & 0x10) {
  5294 + /* Start with XER OV disabled, the most likely case */
  5295 + tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
  5296 + }
  5297 + if (opc3 & 0x01) {
  5298 + /* Signed */
  5299 + tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
  5300 + tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
  5301 + tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
  5302 + tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
  5303 + if (opc3 & 0x02) {
  5304 + /* Saturate */
  5305 + tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
  5306 + tcg_gen_xori_tl(t0, t0, 0x7fffffff);
  5307 + }
  5308 + } else {
  5309 + /* Unsigned */
  5310 + tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
  5311 + if (opc3 & 0x02) {
  5312 + /* Saturate */
  5313 + tcg_gen_movi_tl(t0, UINT32_MAX);
  5314 + }
  5315 + }
  5316 + if (opc3 & 0x10) {
  5317 + /* Check overflow */
  5318 + tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
  5319 + }
  5320 + gen_set_label(l1);
  5321 + tcg_gen_mov_tl(cpu_gpr[rt], t0);
  5322 + }
  5323 + } else {
  5324 + tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
5286 } 5325 }
5287 - tcg_gen_mov_tl(cpu_gpr[rt], cpu_T[0]); 5326 + tcg_temp_free(t0);
  5327 + tcg_temp_free(t1);
5288 if (unlikely(Rc) != 0) { 5328 if (unlikely(Rc) != 0) {
5289 /* Update Rc0 */ 5329 /* Update Rc0 */
5290 - gen_set_Rc0(ctx, cpu_T[0]); 5330 + gen_set_Rc0(ctx, cpu_gpr[rt]);
5291 } 5331 }
5292 } 5332 }
5293 5333