summaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorTom Musta <tommusta@gmail.com>2014-02-10 11:25:09 -0600
committerAlexander Graf <agraf@suse.de>2014-03-05 03:06:48 +0100
commitf5bc1bfa35af5288fe43f459696e712474dafc66 (patch)
tree3e0539f30117085137d5085266f60ce106e38871 /target-ppc
parent3f34cf910cbc4e77d25a300d8c290ae50bdcc2ed (diff)
downloadqemu-f5bc1bfa35af5288fe43f459696e712474dafc66.tar.gz
target-ppc: Fix xxpermdi When T==A or T==B
The existing implementation of xxpermdi is defective if the target VSR is also a source VSR. This patch fixes the defect in this case but also preserves the simpler, two TCG operation implementation when the target is not once of the two sources. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/translate.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8885490aa8..655aca6568 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -7332,15 +7332,40 @@ static void gen_xxpermdi(DisasContext *ctx)
return;
}
- if ((DM(ctx->opcode) & 2) == 0) {
- tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
- } else {
- tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
- }
- if ((DM(ctx->opcode) & 1) == 0) {
- tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
+ if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) ||
+ (xT(ctx->opcode) == xB(ctx->opcode)))) {
+ TCGv_i64 xh, xl;
+
+ xh = tcg_temp_new_i64();
+ xl = tcg_temp_new_i64();
+
+ if ((DM(ctx->opcode) & 2) == 0) {
+ tcg_gen_mov_i64(xh, cpu_vsrh(xA(ctx->opcode)));
+ } else {
+ tcg_gen_mov_i64(xh, cpu_vsrl(xA(ctx->opcode)));
+ }
+ if ((DM(ctx->opcode) & 1) == 0) {
+ tcg_gen_mov_i64(xl, cpu_vsrh(xB(ctx->opcode)));
+ } else {
+ tcg_gen_mov_i64(xl, cpu_vsrl(xB(ctx->opcode)));
+ }
+
+ tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xh);
+ tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xl);
+
+ tcg_temp_free_i64(xh);
+ tcg_temp_free_i64(xl);
} else {
- tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
+ if ((DM(ctx->opcode) & 2) == 0) {
+ tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode)));
+ } else {
+ tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode)));
+ }
+ if ((DM(ctx->opcode) & 1) == 0) {
+ tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode)));
+ } else {
+ tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode)));
+ }
}
}