summaryrefslogtreecommitdiffstats
path: root/tcg/arm/tcg-target.c
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2010-04-09 20:52:48 +0200
committerAurelien Jarno <aurelien@aurel32.net>2010-04-19 07:03:02 +0200
commit9517094f720097b51854ef458ffb1971720dddfa (patch)
tree0b9c04e908d799fdc171887f0925fcfe68dcdce7 /tcg/arm/tcg-target.c
parent293579e55c40d78353ecd3e48d67f744ba579c12 (diff)
downloadhqemu-9517094f720097b51854ef458ffb1971720dddfa.zip
hqemu-9517094f720097b51854ef458ffb1971720dddfa.tar.gz
tcg/arm: add ext16u op
Add an ext16u op, either using the uxth instruction on ARMv6+ or two shifts on previous ARM versions. In both cases the result use the same number or less instructions than the pure TCG version. Also move all sign extension code to separate functions, so that they can be reused in other parts of the code. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'tcg/arm/tcg-target.c')
-rw-r--r--tcg/arm/tcg-target.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 602fdf2..efcefe2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -485,6 +485,48 @@ static inline void tcg_out_smull32(TCGContext *s,
}
}
+static inline void tcg_out_ext8s(TCGContext *s, int cond,
+ int rd, int rn)
+{
+ if (use_armv6_instructions) {
+ /* sxtb */
+ tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
+ } else {
+ tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+ rd, 0, rn, SHIFT_IMM_LSL(24));
+ tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+ rd, 0, rd, SHIFT_IMM_ASR(24));
+ }
+}
+
+static inline void tcg_out_ext16s(TCGContext *s, int cond,
+ int rd, int rn)
+{
+ if (use_armv6_instructions) {
+ /* sxth */
+ tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
+ } else {
+ tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+ rd, 0, rn, SHIFT_IMM_LSL(16));
+ tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+ rd, 0, rd, SHIFT_IMM_ASR(16));
+ }
+}
+
+static inline void tcg_out_ext16u(TCGContext *s, int cond,
+ int rd, int rn)
+{
+ if (use_armv6_instructions) {
+ /* uxth */
+ tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
+ } else {
+ tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+ rd, 0, rn, SHIFT_IMM_LSL(16));
+ tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
+ rd, 0, rd, SHIFT_IMM_LSR(16));
+ }
+}
+
static inline void tcg_out_ld32_12(TCGContext *s, int cond,
int rd, int rn, tcg_target_long im)
{
@@ -1503,26 +1545,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ext8s_i32:
- if (use_armv6_instructions) {
- /* sxtb */
- tcg_out32(s, 0xe6af0070 | (args[0] << 12) | args[1]);
- } else {
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- args[0], 0, args[1], SHIFT_IMM_LSL(24));
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- args[0], 0, args[0], SHIFT_IMM_ASR(24));
- }
+ tcg_out_ext8s(s, COND_AL, args[0], args[1]);
break;
case INDEX_op_ext16s_i32:
- if (use_armv6_instructions) {
- /* sxth */
- tcg_out32(s, 0xe6bf0070 | (args[0] << 12) | args[1]);
- } else {
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- args[0], 0, args[1], SHIFT_IMM_LSL(16));
- tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
- args[0], 0, args[0], SHIFT_IMM_ASR(16));
- }
+ tcg_out_ext16s(s, COND_AL, args[0], args[1]);
+ break;
+ case INDEX_op_ext16u_i32:
+ tcg_out_ext16u(s, COND_AL, args[0], args[1]);
break;
default:
@@ -1604,6 +1633,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
{ INDEX_op_ext8s_i32, { "r", "r" } },
{ INDEX_op_ext16s_i32, { "r", "r" } },
+ { INDEX_op_ext16u_i32, { "r", "r" } },
{ -1 },
};
OpenPOWER on IntegriCloud