提交 8d745875 编写于 作者: S Stefan Brankovic 提交者: David Gibson

target/ppc: Fix for optimized vsl/vsr instructions

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: 4e6d0920Reported-by: N"Paul A. Clark" <pc@us.ibm.com>
Reported-by: NMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Suggested-by: NAleksandar Markovic <aleksandar.markovic@rt-rk.com>
Signed-off-by: NStefan Brankovic <stefan.brankovic@rt-rk.com>
Message-Id: <1570196639-7025-2-git-send-email-stefan.brankovic@rt-rk.com>
Tested-by: NPaul A. Clarke  <pc@us.ibm.com>
Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
上级 e6144bf9
...@@ -590,40 +590,38 @@ static void trans_vsl(DisasContext *ctx) ...@@ -590,40 +590,38 @@ static void trans_vsl(DisasContext *ctx)
int VT = rD(ctx->opcode); int VT = rD(ctx->opcode);
int VA = rA(ctx->opcode); int VA = rA(ctx->opcode);
int VB = rB(ctx->opcode); int VB = rB(ctx->opcode);
TCGv_i64 avrA = tcg_temp_new_i64(); TCGv_i64 avr = tcg_temp_new_i64();
TCGv_i64 avrB = tcg_temp_new_i64();
TCGv_i64 sh = 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(); TCGv_i64 tmp = tcg_temp_new_i64();
/* Place bits 125-127 of vB in sh. */ /* Place bits 125-127 of vB in 'sh'. */
get_avr64(avrB, VB, false); get_avr64(avr, VB, false);
tcg_gen_andi_i64(sh, avrB, 0x07ULL); tcg_gen_andi_i64(sh, avr, 0x07ULL);
/* /*
* Save highest sh bits of lower doubleword element of vA in variable * Save highest 'sh' bits of lower doubleword element of vA in variable
* shifted and perform shift on lower doubleword. * 'carry' and perform shift on lower doubleword.
*/ */
get_avr64(avrA, VA, false); get_avr64(avr, VA, false);
tcg_gen_subfi_i64(tmp, 64, sh); tcg_gen_subfi_i64(tmp, 32, sh);
tcg_gen_shr_i64(shifted, avrA, tmp); tcg_gen_shri_i64(carry, avr, 32);
tcg_gen_andi_i64(shifted, shifted, 0x7fULL); tcg_gen_shr_i64(carry, carry, tmp);
tcg_gen_shl_i64(avrA, avrA, sh); tcg_gen_shl_i64(avr, avr, sh);
set_avr64(VT, avrA, false); set_avr64(VT, avr, false);
/* /*
* Perform shift on higher doubleword element of vA and replace lowest * Perform shift on higher doubleword element of vA and replace lowest
* sh bits with shifted. * 'sh' bits with 'carry'.
*/ */
get_avr64(avrA, VA, true); get_avr64(avr, VA, true);
tcg_gen_shl_i64(avrA, avrA, sh); tcg_gen_shl_i64(avr, avr, sh);
tcg_gen_or_i64(avrA, avrA, shifted); tcg_gen_or_i64(avr, avr, carry);
set_avr64(VT, avrA, true); set_avr64(VT, avr, true);
tcg_temp_free_i64(avrA); tcg_temp_free_i64(avr);
tcg_temp_free_i64(avrB);
tcg_temp_free_i64(sh); tcg_temp_free_i64(sh);
tcg_temp_free_i64(shifted); tcg_temp_free_i64(carry);
tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp);
} }
...@@ -639,39 +637,37 @@ static void trans_vsr(DisasContext *ctx) ...@@ -639,39 +637,37 @@ static void trans_vsr(DisasContext *ctx)
int VT = rD(ctx->opcode); int VT = rD(ctx->opcode);
int VA = rA(ctx->opcode); int VA = rA(ctx->opcode);
int VB = rB(ctx->opcode); int VB = rB(ctx->opcode);
TCGv_i64 avrA = tcg_temp_new_i64(); TCGv_i64 avr = tcg_temp_new_i64();
TCGv_i64 avrB = tcg_temp_new_i64();
TCGv_i64 sh = 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(); TCGv_i64 tmp = tcg_temp_new_i64();
/* Place bits 125-127 of vB in sh. */ /* Place bits 125-127 of vB in 'sh'. */
get_avr64(avrB, VB, false); get_avr64(avr, VB, false);
tcg_gen_andi_i64(sh, avrB, 0x07ULL); tcg_gen_andi_i64(sh, avr, 0x07ULL);
/* /*
* Save lowest sh bits of higher doubleword element of vA in variable * Save lowest 'sh' bits of higher doubleword element of vA in variable
* shifted and perform shift on higher doubleword. * 'carry' and perform shift on higher doubleword.
*/ */
get_avr64(avrA, VA, true); get_avr64(avr, VA, true);
tcg_gen_subfi_i64(tmp, 64, sh); tcg_gen_subfi_i64(tmp, 32, sh);
tcg_gen_shl_i64(shifted, avrA, tmp); tcg_gen_shli_i64(carry, avr, 32);
tcg_gen_andi_i64(shifted, shifted, 0xfe00000000000000ULL); tcg_gen_shl_i64(carry, carry, tmp);
tcg_gen_shr_i64(avrA, avrA, sh); tcg_gen_shr_i64(avr, avr, sh);
set_avr64(VT, avrA, true); set_avr64(VT, avr, true);
/* /*
* Perform shift on lower doubleword element of vA and replace highest * Perform shift on lower doubleword element of vA and replace highest
* sh bits with shifted. * 'sh' bits with 'carry'.
*/ */
get_avr64(avrA, VA, false); get_avr64(avr, VA, false);
tcg_gen_shr_i64(avrA, avrA, sh); tcg_gen_shr_i64(avr, avr, sh);
tcg_gen_or_i64(avrA, avrA, shifted); tcg_gen_or_i64(avr, avr, carry);
set_avr64(VT, avrA, false); set_avr64(VT, avr, false);
tcg_temp_free_i64(avrA); tcg_temp_free_i64(avr);
tcg_temp_free_i64(avrB);
tcg_temp_free_i64(sh); tcg_temp_free_i64(sh);
tcg_temp_free_i64(shifted); tcg_temp_free_i64(carry);
tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册