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 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 329 /*** Integer shift ***/
358 330 void OPPROTO op_srli_T1 (void)
359 331 {
... ... @@ -1062,73 +1034,6 @@ void OPPROTO op_602_mfrom (void)
1062 1034 #endif
1063 1035  
1064 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 1037 void OPPROTO op_load_dcr (void)
1133 1038 {
1134 1039 do_load_dcr();
... ...
target-ppc/op_helper.c
... ... @@ -1510,18 +1510,6 @@ void do_op_602_mfrom (void)
1510 1510  
1511 1511 /*****************************************************************************/
1512 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 1514 /* XXX: to be improved to check access rights when in user-mode */
1527 1515 void do_load_dcr (void)
... ...
target-ppc/op_helper.h
... ... @@ -144,7 +144,6 @@ void do_440_tlbwe (int word);
144 144 #endif
145 145  
146 146 /* PowerPC 4xx specific helpers */
147   -void do_405_check_sat (void);
148 147 void do_load_dcr (void);
149 148 void do_store_dcr (void);
150 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 5214 int opc2, int opc3,
5215 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 5222 switch (opc3 & 0x0D) {
5220 5223 case 0x05:
5221 5224 /* macchw - macchw. - macchwo - macchwo. */
... ... @@ -5223,13 +5226,17 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5223 5226 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5224 5227 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5225 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 5232 break;
5228 5233 case 0x04:
5229 5234 /* macchwu - macchwu. - macchwuo - macchwuo. */
5230 5235 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5231 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 5240 break;
5234 5241 case 0x01:
5235 5242 /* machhw - machhw. - machhwo - machhwo. */
... ... @@ -5237,13 +5244,19 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5237 5244 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5238 5245 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5239 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 5251 break;
5242 5252 case 0x00:
5243 5253 /* machhwu - machhwu. - machhwuo - machhwuo. */
5244 5254 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5245 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 5260 break;
5248 5261 case 0x0D:
5249 5262 /* maclhw - maclhw. - maclhwo - maclhwo. */
... ... @@ -5251,43 +5264,70 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5251 5264 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5252 5265 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5253 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 5269 break;
5256 5270 case 0x0C:
5257 5271 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5258 5272 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5259 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 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 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 5328 if (unlikely(Rc) != 0) {
5289 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  
... ...