mirror of https://github.com/xemu-project/xemu.git
tcg/arm: Support bswap flags
Combine the three bswap16 routines, and differentiate via the flags. Use the correct flags combination from the load/store routines, and pass along the constant parameter from tcg_out_op. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
8fcfc6bff6
commit
2ec89a78a5
|
@ -1013,50 +1013,71 @@ static inline void tcg_out_ext16u(TCGContext *s, int cond,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
|
static void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn, int flags)
|
||||||
{
|
{
|
||||||
if (use_armv6_instructions) {
|
if (use_armv6_instructions) {
|
||||||
/* revsh */
|
if (flags & TCG_BSWAP_OS) {
|
||||||
tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
|
/* revsh */
|
||||||
} else {
|
tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
|
||||||
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
return;
|
||||||
TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
|
}
|
||||||
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
|
||||||
TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_ASR(16));
|
|
||||||
tcg_out_dat_reg(s, cond, ARITH_ORR,
|
|
||||||
rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
|
|
||||||
{
|
|
||||||
if (use_armv6_instructions) {
|
|
||||||
/* rev16 */
|
/* rev16 */
|
||||||
tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
|
tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
|
||||||
} else {
|
if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
||||||
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
/* uxth */
|
||||||
TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
|
tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rd);
|
||||||
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
}
|
||||||
TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSR(16));
|
return;
|
||||||
tcg_out_dat_reg(s, cond, ARITH_ORR,
|
|
||||||
rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* swap the two low bytes assuming that the two high input bytes and the
|
if (flags == 0) {
|
||||||
two high output bit can hold any value. */
|
/*
|
||||||
static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
|
* For stores, no input or output extension:
|
||||||
{
|
* rn = xxAB
|
||||||
if (use_armv6_instructions) {
|
* lsr tmp, rn, #8 tmp = 0xxA
|
||||||
/* rev16 */
|
* and tmp, tmp, #0xff tmp = 000A
|
||||||
tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
|
* orr rd, tmp, rn, lsl #8 rd = xABA
|
||||||
} else {
|
*/
|
||||||
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
||||||
TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
|
TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
|
||||||
tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
|
tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
|
||||||
tcg_out_dat_reg(s, cond, ARITH_ORR,
|
tcg_out_dat_reg(s, cond, ARITH_ORR,
|
||||||
rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
|
rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Byte swap, leaving the result at the top of the register.
|
||||||
|
* We will then shift down, zero or sign-extending.
|
||||||
|
*/
|
||||||
|
if (flags & TCG_BSWAP_IZ) {
|
||||||
|
/*
|
||||||
|
* rn = 00AB
|
||||||
|
* ror tmp, rn, #8 tmp = B00A
|
||||||
|
* orr tmp, tmp, tmp, lsl #16 tmp = BA00
|
||||||
|
*/
|
||||||
|
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
||||||
|
TCG_REG_TMP, 0, rn, SHIFT_IMM_ROR(8));
|
||||||
|
tcg_out_dat_reg(s, cond, ARITH_ORR,
|
||||||
|
TCG_REG_TMP, TCG_REG_TMP, TCG_REG_TMP,
|
||||||
|
SHIFT_IMM_LSL(16));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* rn = xxAB
|
||||||
|
* and tmp, rn, #0xff00 tmp = 00A0
|
||||||
|
* lsl tmp, tmp, #8 tmp = 0A00
|
||||||
|
* orr tmp, tmp, rn, lsl #24 tmp = BA00
|
||||||
|
*/
|
||||||
|
tcg_out_dat_rI(s, cond, ARITH_AND, TCG_REG_TMP, rn, 0xff00, 1);
|
||||||
|
tcg_out_dat_reg(s, cond, ARITH_MOV,
|
||||||
|
TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSL(8));
|
||||||
|
tcg_out_dat_reg(s, cond, ARITH_ORR,
|
||||||
|
TCG_REG_TMP, TCG_REG_TMP, rn, SHIFT_IMM_LSL(24));
|
||||||
|
}
|
||||||
|
tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, TCG_REG_TMP,
|
||||||
|
(flags & TCG_BSWAP_OS
|
||||||
|
? SHIFT_IMM_ASR(8) : SHIFT_IMM_LSR(8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
|
static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
|
||||||
|
@ -1705,13 +1726,15 @@ static inline void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
|
||||||
case MO_UW:
|
case MO_UW:
|
||||||
tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
|
tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap16(s, COND_AL, datalo, datalo);
|
tcg_out_bswap16(s, COND_AL, datalo, datalo,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OZ);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MO_SW:
|
case MO_SW:
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
|
tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
|
||||||
tcg_out_bswap16s(s, COND_AL, datalo, datalo);
|
tcg_out_bswap16(s, COND_AL, datalo, datalo,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OS);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
|
tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
|
||||||
}
|
}
|
||||||
|
@ -1766,13 +1789,15 @@ static inline void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc,
|
||||||
case MO_UW:
|
case MO_UW:
|
||||||
tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
|
tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap16(s, COND_AL, datalo, datalo);
|
tcg_out_bswap16(s, COND_AL, datalo, datalo,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OZ);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MO_SW:
|
case MO_SW:
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
|
tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
|
||||||
tcg_out_bswap16s(s, COND_AL, datalo, datalo);
|
tcg_out_bswap16(s, COND_AL, datalo, datalo,
|
||||||
|
TCG_BSWAP_IZ | TCG_BSWAP_OS);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
|
tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
|
||||||
}
|
}
|
||||||
|
@ -1862,7 +1887,7 @@ static inline void tcg_out_qemu_st_index(TCGContext *s, int cond, MemOp opc,
|
||||||
break;
|
break;
|
||||||
case MO_16:
|
case MO_16:
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap16st(s, cond, TCG_REG_R0, datalo);
|
tcg_out_bswap16(s, cond, TCG_REG_R0, datalo, 0);
|
||||||
tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
|
tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_st16_r(s, cond, datalo, addrlo, addend);
|
tcg_out_st16_r(s, cond, datalo, addrlo, addend);
|
||||||
|
@ -1907,7 +1932,7 @@ static inline void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc,
|
||||||
break;
|
break;
|
||||||
case MO_16:
|
case MO_16:
|
||||||
if (bswap) {
|
if (bswap) {
|
||||||
tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
|
tcg_out_bswap16(s, COND_AL, TCG_REG_R0, datalo, 0);
|
||||||
tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
|
tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
|
tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
|
||||||
|
@ -2245,7 +2270,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_bswap16_i32:
|
case INDEX_op_bswap16_i32:
|
||||||
tcg_out_bswap16(s, COND_AL, args[0], args[1]);
|
tcg_out_bswap16(s, COND_AL, args[0], args[1], args[2]);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_bswap32_i32:
|
case INDEX_op_bswap32_i32:
|
||||||
tcg_out_bswap32(s, COND_AL, args[0], args[1]);
|
tcg_out_bswap32(s, COND_AL, args[0], args[1]);
|
||||||
|
|
Loading…
Reference in New Issue