Skip to content

Commit

Permalink
target/ppc: Fix for optimized vsl/vsr instructions
Browse files Browse the repository at this point in the history
In previous implementation, invocation of TCG shift function could request
shift of TCG variable by 64 bits when variable 'sh' is 0, which is not
supported in TCG (values can be shifted by 0 to 63 bits). This patch fixes
this by using two separate invocation of TCG shift functions, with maximum
shift amount of 32.

Name of variable 'shifted' is changed to 'carry' so variable naming
is similar to old helper implementation.

Variables 'avrA' and 'avrB' are replaced with variable 'avr'.

Fixes: 4e6d092
Reported-by: "Paul A. Clark" <pc@us.ibm.com>
Reported-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Suggested-by: Aleksandar Markovic <aleksandar.markovic@rt-rk.com>
Signed-off-by: Stefan Brankovic <stefan.brankovic@rt-rk.com>
Message-Id: <1570196639-7025-2-git-send-email-stefan.brankovic@rt-rk.com>
Tested-by: Paul A. Clarke  <pc@us.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
  • Loading branch information
Stefan Brankovic authored and dgibson committed Oct 23, 2019
1 parent e6144bf commit 8d74587
Showing 1 changed file with 40 additions and 44 deletions.
84 changes: 40 additions & 44 deletions target/ppc/translate/vmx-impl.inc.c
Expand Up @@ -590,40 +590,38 @@ static void trans_vsl(DisasContext *ctx)
int VT = rD(ctx->opcode);
int VA = rA(ctx->opcode);
int VB = rB(ctx->opcode);
TCGv_i64 avrA = tcg_temp_new_i64();
TCGv_i64 avrB = tcg_temp_new_i64();
TCGv_i64 avr = tcg_temp_new_i64();
TCGv_i64 sh = tcg_temp_new_i64();
TCGv_i64 shifted = tcg_temp_new_i64();
TCGv_i64 carry = tcg_temp_new_i64();
TCGv_i64 tmp = tcg_temp_new_i64();

/* Place bits 125-127 of vB in sh. */
get_avr64(avrB, VB, false);
tcg_gen_andi_i64(sh, avrB, 0x07ULL);
/* Place bits 125-127 of vB in 'sh'. */
get_avr64(avr, VB, false);
tcg_gen_andi_i64(sh, avr, 0x07ULL);

/*
* Save highest sh bits of lower doubleword element of vA in variable
* shifted and perform shift on lower doubleword.
* Save highest 'sh' bits of lower doubleword element of vA in variable
* 'carry' and perform shift on lower doubleword.
*/
get_avr64(avrA, VA, false);
tcg_gen_subfi_i64(tmp, 64, sh);
tcg_gen_shr_i64(shifted, avrA, tmp);
tcg_gen_andi_i64(shifted, shifted, 0x7fULL);
tcg_gen_shl_i64(avrA, avrA, sh);
set_avr64(VT, avrA, false);
get_avr64(avr, VA, false);
tcg_gen_subfi_i64(tmp, 32, sh);
tcg_gen_shri_i64(carry, avr, 32);
tcg_gen_shr_i64(carry, carry, tmp);
tcg_gen_shl_i64(avr, avr, sh);
set_avr64(VT, avr, false);

/*
* Perform shift on higher doubleword element of vA and replace lowest
* sh bits with shifted.
* 'sh' bits with 'carry'.
*/
get_avr64(avrA, VA, true);
tcg_gen_shl_i64(avrA, avrA, sh);
tcg_gen_or_i64(avrA, avrA, shifted);
set_avr64(VT, avrA, true);
get_avr64(avr, VA, true);
tcg_gen_shl_i64(avr, avr, sh);
tcg_gen_or_i64(avr, avr, carry);
set_avr64(VT, avr, true);

tcg_temp_free_i64(avrA);
tcg_temp_free_i64(avrB);
tcg_temp_free_i64(avr);
tcg_temp_free_i64(sh);
tcg_temp_free_i64(shifted);
tcg_temp_free_i64(carry);
tcg_temp_free_i64(tmp);
}

Expand All @@ -639,39 +637,37 @@ static void trans_vsr(DisasContext *ctx)
int VT = rD(ctx->opcode);
int VA = rA(ctx->opcode);
int VB = rB(ctx->opcode);
TCGv_i64 avrA = tcg_temp_new_i64();
TCGv_i64 avrB = tcg_temp_new_i64();
TCGv_i64 avr = tcg_temp_new_i64();
TCGv_i64 sh = tcg_temp_new_i64();
TCGv_i64 shifted = tcg_temp_new_i64();
TCGv_i64 carry = tcg_temp_new_i64();
TCGv_i64 tmp = tcg_temp_new_i64();

/* Place bits 125-127 of vB in sh. */
get_avr64(avrB, VB, false);
tcg_gen_andi_i64(sh, avrB, 0x07ULL);
/* Place bits 125-127 of vB in 'sh'. */
get_avr64(avr, VB, false);
tcg_gen_andi_i64(sh, avr, 0x07ULL);

/*
* Save lowest sh bits of higher doubleword element of vA in variable
* shifted and perform shift on higher doubleword.
* Save lowest 'sh' bits of higher doubleword element of vA in variable
* 'carry' and perform shift on higher doubleword.
*/
get_avr64(avrA, VA, true);
tcg_gen_subfi_i64(tmp, 64, sh);
tcg_gen_shl_i64(shifted, avrA, tmp);
tcg_gen_andi_i64(shifted, shifted, 0xfe00000000000000ULL);
tcg_gen_shr_i64(avrA, avrA, sh);
set_avr64(VT, avrA, true);
get_avr64(avr, VA, true);
tcg_gen_subfi_i64(tmp, 32, sh);
tcg_gen_shli_i64(carry, avr, 32);
tcg_gen_shl_i64(carry, carry, tmp);
tcg_gen_shr_i64(avr, avr, sh);
set_avr64(VT, avr, true);
/*
* Perform shift on lower doubleword element of vA and replace highest
* sh bits with shifted.
* 'sh' bits with 'carry'.
*/
get_avr64(avrA, VA, false);
tcg_gen_shr_i64(avrA, avrA, sh);
tcg_gen_or_i64(avrA, avrA, shifted);
set_avr64(VT, avrA, false);
get_avr64(avr, VA, false);
tcg_gen_shr_i64(avr, avr, sh);
tcg_gen_or_i64(avr, avr, carry);
set_avr64(VT, avr, false);

tcg_temp_free_i64(avrA);
tcg_temp_free_i64(avrB);
tcg_temp_free_i64(avr);
tcg_temp_free_i64(sh);
tcg_temp_free_i64(shifted);
tcg_temp_free_i64(carry);
tcg_temp_free_i64(tmp);
}

Expand Down

0 comments on commit 8d74587

Please sign in to comment.