Commit 8f01245ee768775d5fa4f1dd0930e7062eb5dc27
1 parent
1497c961
ARM TCG conversion 5/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4142 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
64 additions
and
69 deletions
target-arm/op.c
| ... | ... | @@ -222,29 +222,6 @@ void OPPROTO op_movl_cpsr_T0(void) |
| 222 | 222 | FORCE_RET(); |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | -void OPPROTO op_mul_T0_T1(void) | |
| 226 | -{ | |
| 227 | - T0 = T0 * T1; | |
| 228 | -} | |
| 229 | - | |
| 230 | -/* 64 bit unsigned mul */ | |
| 231 | -void OPPROTO op_mull_T0_T1(void) | |
| 232 | -{ | |
| 233 | - uint64_t res; | |
| 234 | - res = (uint64_t)T0 * (uint64_t)T1; | |
| 235 | - T1 = res >> 32; | |
| 236 | - T0 = res; | |
| 237 | -} | |
| 238 | - | |
| 239 | -/* 64 bit signed mul */ | |
| 240 | -void OPPROTO op_imull_T0_T1(void) | |
| 241 | -{ | |
| 242 | - uint64_t res; | |
| 243 | - res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); | |
| 244 | - T1 = res >> 32; | |
| 245 | - T0 = res; | |
| 246 | -} | |
| 247 | - | |
| 248 | 225 | /* 48 bit signed mul, top 32 bits */ |
| 249 | 226 | void OPPROTO op_imulw_T0_T1(void) |
| 250 | 227 | { |
| ... | ... | @@ -1058,18 +1035,6 @@ void OPPROTO op_pkhbt_T0_T1(void) |
| 1058 | 1035 | { |
| 1059 | 1036 | T0 = (T0 & 0xffff) | (T1 & 0xffff0000); |
| 1060 | 1037 | } |
| 1061 | -void OPPROTO op_rev_T0(void) | |
| 1062 | -{ | |
| 1063 | - T0 = ((T0 & 0xff000000) >> 24) | |
| 1064 | - | ((T0 & 0x00ff0000) >> 8) | |
| 1065 | - | ((T0 & 0x0000ff00) << 8) | |
| 1066 | - | ((T0 & 0x000000ff) << 24); | |
| 1067 | -} | |
| 1068 | - | |
| 1069 | -void OPPROTO op_revh_T0(void) | |
| 1070 | -{ | |
| 1071 | - T0 = (T0 >> 16) | (T0 << 16); | |
| 1072 | -} | |
| 1073 | 1038 | |
| 1074 | 1039 | void OPPROTO op_rev16_T0(void) |
| 1075 | 1040 | { |
| ... | ... | @@ -1099,13 +1064,6 @@ void OPPROTO op_rbit_T0(void) |
| 1099 | 1064 | | ((T0 & 0x11111111) << 3); |
| 1100 | 1065 | } |
| 1101 | 1066 | |
| 1102 | -/* Swap low and high halfwords. */ | |
| 1103 | -void OPPROTO op_swap_half_T1(void) | |
| 1104 | -{ | |
| 1105 | - T1 = (T1 >> 16) | (T1 << 16); | |
| 1106 | - FORCE_RET(); | |
| 1107 | -} | |
| 1108 | - | |
| 1109 | 1067 | /* Dual 16-bit signed multiply. */ |
| 1110 | 1068 | void OPPROTO op_mul_dual_T0_T1(void) |
| 1111 | 1069 | { |
| ... | ... | @@ -1267,22 +1225,6 @@ void OPPROTO op_sbfx_T1(void) |
| 1267 | 1225 | T1 = val >> (32 - width); |
| 1268 | 1226 | } |
| 1269 | 1227 | |
| 1270 | -void OPPROTO op_movtop_T0_im(void) | |
| 1271 | -{ | |
| 1272 | - T0 = (T0 & 0xffff) | PARAM1; | |
| 1273 | -} | |
| 1274 | - | |
| 1275 | -/* Used by table branch instructions. */ | |
| 1276 | -void OPPROTO op_jmp_T0_im(void) | |
| 1277 | -{ | |
| 1278 | - env->regs[15] = PARAM1 + (T0 << 1); | |
| 1279 | -} | |
| 1280 | - | |
| 1281 | -void OPPROTO op_set_condexec(void) | |
| 1282 | -{ | |
| 1283 | - env->condexec_bits = PARAM1; | |
| 1284 | -} | |
| 1285 | - | |
| 1286 | 1228 | void OPPROTO op_sdivl_T0_T1(void) |
| 1287 | 1229 | { |
| 1288 | 1230 | int32_t num; | ... | ... |
target-arm/translate.c
| ... | ... | @@ -204,6 +204,9 @@ static void store_reg(DisasContext *s, int reg, TCGv var) |
| 204 | 204 | |
| 205 | 205 | #define gen_sxtb16(var) gen_helper_sxtb16(var, var) |
| 206 | 206 | #define gen_uxtb16(var) gen_helper_uxtb16(var, var) |
| 207 | +#define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]) | |
| 208 | + | |
| 209 | +#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1]) | |
| 207 | 210 | |
| 208 | 211 | #define gen_op_addl_T0_T1_setq() \ |
| 209 | 212 | gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1]) |
| ... | ... | @@ -216,6 +219,45 @@ static void store_reg(DisasContext *s, int reg, TCGv var) |
| 216 | 219 | #define gen_op_subl_T0_T1_usaturate() \ |
| 217 | 220 | gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]) |
| 218 | 221 | |
| 222 | +/* FIXME: Most targets have native widening multiplication. | |
| 223 | + It would be good to use that instead of a full wide multiply. */ | |
| 224 | +/* Unsigned 32x32->64 multiply. */ | |
| 225 | +static void gen_op_mull_T0_T1(void) | |
| 226 | +{ | |
| 227 | + TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 228 | + TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 229 | + | |
| 230 | + tcg_gen_extu_i32_i64(tmp1, cpu_T[0]); | |
| 231 | + tcg_gen_extu_i32_i64(tmp2, cpu_T[1]); | |
| 232 | + tcg_gen_mul_i64(tmp1, tmp1, tmp2); | |
| 233 | + tcg_gen_trunc_i64_i32(cpu_T[0], tmp1); | |
| 234 | + tcg_gen_shri_i64(tmp1, tmp1, 32); | |
| 235 | + tcg_gen_trunc_i64_i32(cpu_T[1], tmp1); | |
| 236 | +} | |
| 237 | + | |
| 238 | +/* Signed 32x32->64 multiply. */ | |
| 239 | +static void gen_op_imull_T0_T1(void) | |
| 240 | +{ | |
| 241 | + TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 242 | + TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 243 | + | |
| 244 | + tcg_gen_ext_i32_i64(tmp1, cpu_T[0]); | |
| 245 | + tcg_gen_ext_i32_i64(tmp2, cpu_T[1]); | |
| 246 | + tcg_gen_mul_i64(tmp1, tmp1, tmp2); | |
| 247 | + tcg_gen_trunc_i64_i32(cpu_T[0], tmp1); | |
| 248 | + tcg_gen_shri_i64(tmp1, tmp1, 32); | |
| 249 | + tcg_gen_trunc_i64_i32(cpu_T[1], tmp1); | |
| 250 | +} | |
| 251 | + | |
| 252 | +/* Swap low and high halfwords. */ | |
| 253 | +static void gen_swap_half(TCGv var) | |
| 254 | +{ | |
| 255 | + TCGv tmp = new_tmp(); | |
| 256 | + tcg_gen_shri_i32(tmp, var, 16); | |
| 257 | + tcg_gen_shli_i32(var, var, 16); | |
| 258 | + tcg_gen_or_i32(var, var, tmp); | |
| 259 | +} | |
| 260 | + | |
| 219 | 261 | /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. |
| 220 | 262 | tmp = (t0 ^ t1) & 0x8000; |
| 221 | 263 | t0 &= ~0x8000; |
| ... | ... | @@ -2652,7 +2694,11 @@ static inline void |
| 2652 | 2694 | gen_set_condexec (DisasContext *s) |
| 2653 | 2695 | { |
| 2654 | 2696 | if (s->condexec_mask) { |
| 2655 | - gen_op_set_condexec((s->condexec_cond << 4) | (s->condexec_mask >> 1)); | |
| 2697 | + uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); | |
| 2698 | + TCGv tmp = new_tmp(); | |
| 2699 | + tcg_gen_movi_i32(tmp, val); | |
| 2700 | + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, condexec_bits)); | |
| 2701 | + dead_tmp(tmp); | |
| 2656 | 2702 | } |
| 2657 | 2703 | } |
| 2658 | 2704 | |
| ... | ... | @@ -4314,7 +4360,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 4314 | 4360 | NEON_GET_REG(T1, rm, pass * 2 + 1); |
| 4315 | 4361 | switch (size) { |
| 4316 | 4362 | case 0: gen_op_rev_T0(); break; |
| 4317 | - case 1: gen_op_revh_T0(); break; | |
| 4363 | + case 1: gen_swap_half(cpu_T[0]); break; | |
| 4318 | 4364 | case 2: /* no-op */ break; |
| 4319 | 4365 | default: abort(); |
| 4320 | 4366 | } |
| ... | ... | @@ -4325,7 +4371,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 4325 | 4371 | gen_op_movl_T0_T1(); |
| 4326 | 4372 | switch (size) { |
| 4327 | 4373 | case 0: gen_op_rev_T0(); break; |
| 4328 | - case 1: gen_op_revh_T0(); break; | |
| 4374 | + case 1: gen_swap_half(cpu_T[0]); break; | |
| 4329 | 4375 | default: abort(); |
| 4330 | 4376 | } |
| 4331 | 4377 | NEON_SET_REG(T0, rd, pass * 2); |
| ... | ... | @@ -4494,7 +4540,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 4494 | 4540 | case 1: /* VREV32 */ |
| 4495 | 4541 | switch (size) { |
| 4496 | 4542 | case 0: gen_op_rev_T0(); break; |
| 4497 | - case 1: gen_op_revh_T0(); break; | |
| 4543 | + case 1: gen_swap_half(cpu_T[0]); break; | |
| 4498 | 4544 | default: return 1; |
| 4499 | 4545 | } |
| 4500 | 4546 | break; |
| ... | ... | @@ -5574,7 +5620,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5574 | 5620 | gen_movl_reg_T0(s, rd); |
| 5575 | 5621 | } else { |
| 5576 | 5622 | if (insn & (1 << 5)) |
| 5577 | - gen_op_swap_half_T1(); | |
| 5623 | + gen_swap_half(cpu_T[1]); | |
| 5578 | 5624 | gen_op_mul_dual_T0_T1(); |
| 5579 | 5625 | if (insn & (1 << 22)) { |
| 5580 | 5626 | if (insn & (1 << 6)) { |
| ... | ... | @@ -6104,8 +6150,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6104 | 6150 | dead_tmp(tmp); |
| 6105 | 6151 | gen_ldst(ldub, s); |
| 6106 | 6152 | } |
| 6107 | - gen_op_jmp_T0_im(s->pc); | |
| 6108 | - s->is_jmp = DISAS_JUMP; | |
| 6153 | + tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 1); | |
| 6154 | + tcg_gen_addi_i32(cpu_T[0], cpu_T[0], s->pc); | |
| 6155 | + gen_movl_reg_T0(s, 15); | |
| 6109 | 6156 | } else { |
| 6110 | 6157 | /* Load/store exclusive byte/halfword/doubleword. */ |
| 6111 | 6158 | op = (insn >> 4) & 0x3; |
| ... | ... | @@ -6385,7 +6432,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6385 | 6432 | case 2: /* Dual multiply add. */ |
| 6386 | 6433 | case 4: /* Dual multiply subtract. */ |
| 6387 | 6434 | if (op) |
| 6388 | - gen_op_swap_half_T1(); | |
| 6435 | + gen_swap_half(cpu_T[1]); | |
| 6389 | 6436 | gen_op_mul_dual_T0_T1(); |
| 6390 | 6437 | /* This addition cannot overflow. */ |
| 6391 | 6438 | if (insn & (1 << 22)) { |
| ... | ... | @@ -6455,7 +6502,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6455 | 6502 | } else if ((op & 0xe) == 0xc) { |
| 6456 | 6503 | /* Dual multiply accumulate long. */ |
| 6457 | 6504 | if (op & 1) |
| 6458 | - gen_op_swap_half_T1(); | |
| 6505 | + gen_swap_half(cpu_T[1]); | |
| 6459 | 6506 | gen_op_mul_dual_T0_T1(); |
| 6460 | 6507 | if (op & 0x10) { |
| 6461 | 6508 | gen_op_subl_T0_T1(); |
| ... | ... | @@ -6735,7 +6782,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6735 | 6782 | if (insn & (1 << 23)) { |
| 6736 | 6783 | /* movt */ |
| 6737 | 6784 | gen_movl_T0_reg(s, rd); |
| 6738 | - gen_op_movtop_T0_im(imm << 16); | |
| 6785 | + tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0xffff); | |
| 6786 | + tcg_gen_ori_i32(cpu_T[0], cpu_T[0], imm << 16); | |
| 6739 | 6787 | } else { |
| 6740 | 6788 | /* movw */ |
| 6741 | 6789 | gen_op_movl_T0_im(imm); |
| ... | ... | @@ -7600,7 +7648,12 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 7600 | 7648 | /* Reset the conditional execution bits immediately. This avoids |
| 7601 | 7649 | complications trying to do it at the end of the block. */ |
| 7602 | 7650 | if (env->condexec_bits) |
| 7603 | - gen_op_set_condexec(0); | |
| 7651 | + { | |
| 7652 | + TCGv tmp = new_tmp(); | |
| 7653 | + tcg_gen_movi_i32(tmp, 0); | |
| 7654 | + tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, condexec_bits)); | |
| 7655 | + dead_tmp(tmp); | |
| 7656 | + } | |
| 7604 | 7657 | do { |
| 7605 | 7658 | #ifndef CONFIG_USER_ONLY |
| 7606 | 7659 | if (dc->pc >= 0xfffffff0 && IS_M(env)) { | ... | ... |