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 | 221 | #define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im) |
| 222 | 222 | |
| 223 | 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 | 226 | #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) |
| 227 | 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 | 1446 | static inline void gen_op_iwmmxt_addl_M0_wRn(int rn) |
| 1447 | 1447 | { |
| 1448 | 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 | 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 | 2704 | TCGv tmp = new_tmp(); |
| 2705 | 2705 | if (shift) |
| 2706 | 2706 | tcg_gen_shri_i32(var, var, shift); |
| 2707 | - tcg_gen_andi_i32(var, var, 0xff); | |
| 2707 | + tcg_gen_ext8u_i32(var, var); | |
| 2708 | 2708 | tcg_gen_shli_i32(tmp, var, 8); |
| 2709 | 2709 | tcg_gen_or_i32(var, var, tmp); |
| 2710 | 2710 | tcg_gen_shli_i32(tmp, var, 16); |
| ... | ... | @@ -2715,7 +2715,7 @@ static void gen_neon_dup_u8(TCGv var, int shift) |
| 2715 | 2715 | static void gen_neon_dup_low16(TCGv var) |
| 2716 | 2716 | { |
| 2717 | 2717 | TCGv tmp = new_tmp(); |
| 2718 | - tcg_gen_andi_i32(var, var, 0xffff); | |
| 2718 | + tcg_gen_ext16u_i32(var, var); | |
| 2719 | 2719 | tcg_gen_shli_i32(tmp, var, 16); |
| 2720 | 2720 | tcg_gen_or_i32(var, var, tmp); |
| 2721 | 2721 | dead_tmp(tmp); |
| ... | ... | @@ -5862,7 +5862,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5862 | 5862 | } else { |
| 5863 | 5863 | /* MOVT */ |
| 5864 | 5864 | tmp = load_reg(s, rd); |
| 5865 | - tcg_gen_andi_i32(tmp, tmp, 0xffff); | |
| 5865 | + tcg_gen_ext16u_i32(tmp, tmp); | |
| 5866 | 5866 | tcg_gen_ori_i32(tmp, tmp, val << 16); |
| 5867 | 5867 | } |
| 5868 | 5868 | store_reg(s, rd, tmp); |
| ... | ... | @@ -6378,10 +6378,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6378 | 6378 | if (insn & (1 << 6)) { |
| 6379 | 6379 | /* pkhtb */ |
| 6380 | 6380 | tcg_gen_andi_i32(tmp, tmp, 0xffff0000); |
| 6381 | - tcg_gen_andi_i32(tmp2, tmp2, 0xffff); | |
| 6381 | + tcg_gen_ext16u_i32(tmp2, tmp2); | |
| 6382 | 6382 | } else { |
| 6383 | 6383 | /* pkhbt */ |
| 6384 | - tcg_gen_andi_i32(tmp, tmp, 0xffff); | |
| 6384 | + tcg_gen_ext16u_i32(tmp, tmp); | |
| 6385 | 6385 | tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); |
| 6386 | 6386 | } |
| 6387 | 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 | 7700 | if (insn & (1 << 23)) { |
| 7701 | 7701 | /* movt */ |
| 7702 | 7702 | tmp = load_reg(s, rd); |
| 7703 | - tcg_gen_andi_i32(tmp, tmp, 0xffff); | |
| 7703 | + tcg_gen_ext16u_i32(tmp, tmp); | |
| 7704 | 7704 | tcg_gen_ori_i32(tmp, tmp, imm << 16); |
| 7705 | 7705 | } else { |
| 7706 | 7706 | /* movw */ | ... | ... |
target-cris/translate.c
| ... | ... | @@ -1165,11 +1165,10 @@ static inline void t_gen_sext(TCGv d, TCGv s, int size) |
| 1165 | 1165 | |
| 1166 | 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 | 1168 | if (size == 1) |
| 1170 | - tcg_gen_andi_i32(d, s, 0xff); | |
| 1169 | + tcg_gen_ext8u_i32(d, s); | |
| 1171 | 1170 | else if (size == 2) |
| 1172 | - tcg_gen_andi_i32(d, s, 0xffff); | |
| 1171 | + tcg_gen_ext16u_i32(d, s); | |
| 1173 | 1172 | else |
| 1174 | 1173 | tcg_gen_mov_tl(d, s); |
| 1175 | 1174 | } | ... | ... |
tcg/README
| ... | ... | @@ -260,10 +260,13 @@ t0 = t1 |
| 260 | 260 | Move t1 to t0 (both operands must have the same type). |
| 261 | 261 | |
| 262 | 262 | * ext8s_i32/i64 t0, t1 |
| 263 | +ext8u_i32/i64 t0, t1 | |
| 263 | 264 | ext16s_i32/i64 t0, t1 |
| 265 | +ext16u_i32/i64 t0, t1 | |
| 264 | 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 | 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 | 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 | 995 | /* Note: we assume the two high bytes are set to zero */ |
| 984 | 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 | 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 | 1073 | static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg) |
| 1044 | 1074 | { |
| 1045 | 1075 | tcg_gen_mov_i32(ret, arg); |
| ... | ... | @@ -1100,6 +1130,21 @@ static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg) |
| 1100 | 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 | 1148 | /* Note: we assume the target supports move between 32 and 64 bit |
| 1104 | 1149 | registers. This will probably break MIPS64 targets. */ |
| 1105 | 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 | 1156 | registers */ |
| 1112 | 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 | 1162 | /* Note: we assume the target supports move between 32 and 64 bit | ... | ... |