Commit 868314358ea3f3009fb72d2867dc73af54338ae7
1 parent
c96402b1
Add zero extension (pseudo-)ops.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4424 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
61 additions
and
14 deletions
target-arm/translate.c
| @@ -221,8 +221,8 @@ static void store_reg(DisasContext *s, int reg, TCGv var) | @@ -221,8 +221,8 @@ static void store_reg(DisasContext *s, int reg, TCGv var) | ||
| 221 | #define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im) | 221 | #define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im) |
| 222 | 222 | ||
| 223 | /* Value extensions. */ | 223 | /* Value extensions. */ |
| 224 | -#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff) | ||
| 225 | -#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff) | 224 | +#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) |
| 225 | +#define gen_uxth(var) tcg_gen_ext16u_i32(var, var) | ||
| 226 | #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) | 226 | #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) |
| 227 | #define gen_sxth(var) tcg_gen_ext16s_i32(var, var) | 227 | #define gen_sxth(var) tcg_gen_ext16s_i32(var, var) |
| 228 | 228 | ||
| @@ -1446,7 +1446,7 @@ static void gen_op_iwmmxt_setpsr_nz(void) | @@ -1446,7 +1446,7 @@ static void gen_op_iwmmxt_setpsr_nz(void) | ||
| 1446 | static inline void gen_op_iwmmxt_addl_M0_wRn(int rn) | 1446 | static inline void gen_op_iwmmxt_addl_M0_wRn(int rn) |
| 1447 | { | 1447 | { |
| 1448 | iwmmxt_load_reg(cpu_V1, rn); | 1448 | iwmmxt_load_reg(cpu_V1, rn); |
| 1449 | - tcg_gen_andi_i64(cpu_V1, cpu_V1, 0xffffffffu); | 1449 | + tcg_gen_ext32u_i64(cpu_V1, cpu_V1); |
| 1450 | tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); | 1450 | tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); |
| 1451 | } | 1451 | } |
| 1452 | 1452 | ||
| @@ -2704,7 +2704,7 @@ static void gen_neon_dup_u8(TCGv var, int shift) | @@ -2704,7 +2704,7 @@ static void gen_neon_dup_u8(TCGv var, int shift) | ||
| 2704 | TCGv tmp = new_tmp(); | 2704 | TCGv tmp = new_tmp(); |
| 2705 | if (shift) | 2705 | if (shift) |
| 2706 | tcg_gen_shri_i32(var, var, shift); | 2706 | tcg_gen_shri_i32(var, var, shift); |
| 2707 | - tcg_gen_andi_i32(var, var, 0xff); | 2707 | + tcg_gen_ext8u_i32(var, var); |
| 2708 | tcg_gen_shli_i32(tmp, var, 8); | 2708 | tcg_gen_shli_i32(tmp, var, 8); |
| 2709 | tcg_gen_or_i32(var, var, tmp); | 2709 | tcg_gen_or_i32(var, var, tmp); |
| 2710 | tcg_gen_shli_i32(tmp, var, 16); | 2710 | tcg_gen_shli_i32(tmp, var, 16); |
| @@ -2715,7 +2715,7 @@ static void gen_neon_dup_u8(TCGv var, int shift) | @@ -2715,7 +2715,7 @@ static void gen_neon_dup_u8(TCGv var, int shift) | ||
| 2715 | static void gen_neon_dup_low16(TCGv var) | 2715 | static void gen_neon_dup_low16(TCGv var) |
| 2716 | { | 2716 | { |
| 2717 | TCGv tmp = new_tmp(); | 2717 | TCGv tmp = new_tmp(); |
| 2718 | - tcg_gen_andi_i32(var, var, 0xffff); | 2718 | + tcg_gen_ext16u_i32(var, var); |
| 2719 | tcg_gen_shli_i32(tmp, var, 16); | 2719 | tcg_gen_shli_i32(tmp, var, 16); |
| 2720 | tcg_gen_or_i32(var, var, tmp); | 2720 | tcg_gen_or_i32(var, var, tmp); |
| 2721 | dead_tmp(tmp); | 2721 | dead_tmp(tmp); |
| @@ -5862,7 +5862,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | @@ -5862,7 +5862,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | ||
| 5862 | } else { | 5862 | } else { |
| 5863 | /* MOVT */ | 5863 | /* MOVT */ |
| 5864 | tmp = load_reg(s, rd); | 5864 | tmp = load_reg(s, rd); |
| 5865 | - tcg_gen_andi_i32(tmp, tmp, 0xffff); | 5865 | + tcg_gen_ext16u_i32(tmp, tmp); |
| 5866 | tcg_gen_ori_i32(tmp, tmp, val << 16); | 5866 | tcg_gen_ori_i32(tmp, tmp, val << 16); |
| 5867 | } | 5867 | } |
| 5868 | store_reg(s, rd, tmp); | 5868 | store_reg(s, rd, tmp); |
| @@ -6378,10 +6378,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | @@ -6378,10 +6378,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | ||
| 6378 | if (insn & (1 << 6)) { | 6378 | if (insn & (1 << 6)) { |
| 6379 | /* pkhtb */ | 6379 | /* pkhtb */ |
| 6380 | tcg_gen_andi_i32(tmp, tmp, 0xffff0000); | 6380 | tcg_gen_andi_i32(tmp, tmp, 0xffff0000); |
| 6381 | - tcg_gen_andi_i32(tmp2, tmp2, 0xffff); | 6381 | + tcg_gen_ext16u_i32(tmp2, tmp2); |
| 6382 | } else { | 6382 | } else { |
| 6383 | /* pkhbt */ | 6383 | /* pkhbt */ |
| 6384 | - tcg_gen_andi_i32(tmp, tmp, 0xffff); | 6384 | + tcg_gen_ext16u_i32(tmp, tmp); |
| 6385 | tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); | 6385 | tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); |
| 6386 | } | 6386 | } |
| 6387 | tcg_gen_or_i32(tmp, tmp, tmp2); | 6387 | tcg_gen_or_i32(tmp, tmp, tmp2); |
| @@ -7700,7 +7700,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | @@ -7700,7 +7700,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | ||
| 7700 | if (insn & (1 << 23)) { | 7700 | if (insn & (1 << 23)) { |
| 7701 | /* movt */ | 7701 | /* movt */ |
| 7702 | tmp = load_reg(s, rd); | 7702 | tmp = load_reg(s, rd); |
| 7703 | - tcg_gen_andi_i32(tmp, tmp, 0xffff); | 7703 | + tcg_gen_ext16u_i32(tmp, tmp); |
| 7704 | tcg_gen_ori_i32(tmp, tmp, imm << 16); | 7704 | tcg_gen_ori_i32(tmp, tmp, imm << 16); |
| 7705 | } else { | 7705 | } else { |
| 7706 | /* movw */ | 7706 | /* movw */ |
target-cris/translate.c
| @@ -1165,11 +1165,10 @@ static inline void t_gen_sext(TCGv d, TCGv s, int size) | @@ -1165,11 +1165,10 @@ static inline void t_gen_sext(TCGv d, TCGv s, int size) | ||
| 1165 | 1165 | ||
| 1166 | static inline void t_gen_zext(TCGv d, TCGv s, int size) | 1166 | static inline void t_gen_zext(TCGv d, TCGv s, int size) |
| 1167 | { | 1167 | { |
| 1168 | - /* TCG-FIXME: this is not optimal. Many archs have fast zext insns. */ | ||
| 1169 | if (size == 1) | 1168 | if (size == 1) |
| 1170 | - tcg_gen_andi_i32(d, s, 0xff); | 1169 | + tcg_gen_ext8u_i32(d, s); |
| 1171 | else if (size == 2) | 1170 | else if (size == 2) |
| 1172 | - tcg_gen_andi_i32(d, s, 0xffff); | 1171 | + tcg_gen_ext16u_i32(d, s); |
| 1173 | else | 1172 | else |
| 1174 | tcg_gen_mov_tl(d, s); | 1173 | tcg_gen_mov_tl(d, s); |
| 1175 | } | 1174 | } |
tcg/README
| @@ -260,10 +260,13 @@ t0 = t1 | @@ -260,10 +260,13 @@ t0 = t1 | ||
| 260 | Move t1 to t0 (both operands must have the same type). | 260 | Move t1 to t0 (both operands must have the same type). |
| 261 | 261 | ||
| 262 | * ext8s_i32/i64 t0, t1 | 262 | * ext8s_i32/i64 t0, t1 |
| 263 | +ext8u_i32/i64 t0, t1 | ||
| 263 | ext16s_i32/i64 t0, t1 | 264 | ext16s_i32/i64 t0, t1 |
| 265 | +ext16u_i32/i64 t0, t1 | ||
| 264 | ext32s_i64 t0, t1 | 266 | ext32s_i64 t0, t1 |
| 267 | +ext32u_i64 t0, t1 | ||
| 265 | 268 | ||
| 266 | -8, 16 or 32 bit sign extension (both operands must have the same type) | 269 | +8, 16 or 32 bit sign/zero extension (both operands must have the same type) |
| 267 | 270 | ||
| 268 | * bswap16_i32 t0, t1 | 271 | * bswap16_i32 t0, t1 |
| 269 | 272 |
tcg/tcg-op.h
| @@ -980,6 +980,18 @@ static inline void tcg_gen_ext16s_i32(TCGv ret, TCGv arg) | @@ -980,6 +980,18 @@ static inline void tcg_gen_ext16s_i32(TCGv ret, TCGv arg) | ||
| 980 | #endif | 980 | #endif |
| 981 | } | 981 | } |
| 982 | 982 | ||
| 983 | +/* These are currently just for convenience. | ||
| 984 | + We assume a target will recognise these automatically . */ | ||
| 985 | +static inline void tcg_gen_ext8u_i32(TCGv ret, TCGv arg) | ||
| 986 | +{ | ||
| 987 | + tcg_gen_andi_i32(ret, arg, 0xffu); | ||
| 988 | +} | ||
| 989 | + | ||
| 990 | +static inline void tcg_gen_ext16u_i32(TCGv ret, TCGv arg) | ||
| 991 | +{ | ||
| 992 | + tcg_gen_andi_i32(ret, arg, 0xffffu); | ||
| 993 | +} | ||
| 994 | + | ||
| 983 | /* Note: we assume the two high bytes are set to zero */ | 995 | /* Note: we assume the two high bytes are set to zero */ |
| 984 | static inline void tcg_gen_bswap16_i32(TCGv ret, TCGv arg) | 996 | static inline void tcg_gen_bswap16_i32(TCGv ret, TCGv arg) |
| 985 | { | 997 | { |
| @@ -1040,6 +1052,24 @@ static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg) | @@ -1040,6 +1052,24 @@ static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg) | ||
| 1040 | tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31); | 1052 | tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31); |
| 1041 | } | 1053 | } |
| 1042 | 1054 | ||
| 1055 | +static inline void tcg_gen_ext8u_i64(TCGv ret, TCGv arg) | ||
| 1056 | +{ | ||
| 1057 | + tcg_gen_ext8u_i32(ret, arg); | ||
| 1058 | + tcg_gen_movi_i32(TCGV_HIGH(ret), 0); | ||
| 1059 | +} | ||
| 1060 | + | ||
| 1061 | +static inline void tcg_gen_ext16u_i64(TCGv ret, TCGv arg) | ||
| 1062 | +{ | ||
| 1063 | + tcg_gen_ext16u_i32(ret, arg); | ||
| 1064 | + tcg_gen_movi_i32(TCGV_HIGH(ret), 0); | ||
| 1065 | +} | ||
| 1066 | + | ||
| 1067 | +static inline void tcg_gen_ext32u_i64(TCGv ret, TCGv arg) | ||
| 1068 | +{ | ||
| 1069 | + tcg_gen_mov_i32(ret, arg); | ||
| 1070 | + tcg_gen_movi_i32(TCGV_HIGH(ret), 0); | ||
| 1071 | +} | ||
| 1072 | + | ||
| 1043 | static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) | 1073 | static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) |
| 1044 | { | 1074 | { |
| 1045 | tcg_gen_mov_i32(ret, arg); | 1075 | tcg_gen_mov_i32(ret, arg); |
| @@ -1100,6 +1130,21 @@ static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg) | @@ -1100,6 +1130,21 @@ static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg) | ||
| 1100 | #endif | 1130 | #endif |
| 1101 | } | 1131 | } |
| 1102 | 1132 | ||
| 1133 | +static inline void tcg_gen_ext8u_i64(TCGv ret, TCGv arg) | ||
| 1134 | +{ | ||
| 1135 | + tcg_gen_andi_i64(ret, arg, 0xffu); | ||
| 1136 | +} | ||
| 1137 | + | ||
| 1138 | +static inline void tcg_gen_ext16u_i64(TCGv ret, TCGv arg) | ||
| 1139 | +{ | ||
| 1140 | + tcg_gen_andi_i64(ret, arg, 0xffffu); | ||
| 1141 | +} | ||
| 1142 | + | ||
| 1143 | +static inline void tcg_gen_ext32u_i64(TCGv ret, TCGv arg) | ||
| 1144 | +{ | ||
| 1145 | + tcg_gen_andi_i64(ret, arg, 0xffffffffu); | ||
| 1146 | +} | ||
| 1147 | + | ||
| 1103 | /* Note: we assume the target supports move between 32 and 64 bit | 1148 | /* Note: we assume the target supports move between 32 and 64 bit |
| 1104 | registers. This will probably break MIPS64 targets. */ | 1149 | registers. This will probably break MIPS64 targets. */ |
| 1105 | static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) | 1150 | static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) |
| @@ -1111,7 +1156,7 @@ static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) | @@ -1111,7 +1156,7 @@ static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) | ||
| 1111 | registers */ | 1156 | registers */ |
| 1112 | static inline void tcg_gen_extu_i32_i64(TCGv ret, TCGv arg) | 1157 | static inline void tcg_gen_extu_i32_i64(TCGv ret, TCGv arg) |
| 1113 | { | 1158 | { |
| 1114 | - tcg_gen_andi_i64(ret, arg, 0xffffffff); | 1159 | + tcg_gen_andi_i64(ret, arg, 0xffffffffu); |
| 1115 | } | 1160 | } |
| 1116 | 1161 | ||
| 1117 | /* Note: we assume the target supports move between 32 and 64 bit | 1162 | /* Note: we assume the target supports move between 32 and 64 bit |