Commit 9a119ff6c1cba1fde88bf6275d6ba40c95d35dce
1 parent
f51bbbfe
ARM TCG conversion 3/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4140 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
65 additions
and
196 deletions
target-arm/op.c
| @@ -317,55 +317,6 @@ void OPPROTO op_clrex(void) | @@ -317,55 +317,6 @@ void OPPROTO op_clrex(void) | ||
| 317 | cpu_unlock(); | 317 | cpu_unlock(); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | -/* shifts */ | ||
| 321 | - | ||
| 322 | -/* T1 based, set C flag */ | ||
| 323 | -void OPPROTO op_shll_T1_im_cc(void) | ||
| 324 | -{ | ||
| 325 | - env->CF = (T1 >> (32 - PARAM1)) & 1; | ||
| 326 | - T1 = T1 << PARAM1; | ||
| 327 | -} | ||
| 328 | - | ||
| 329 | -void OPPROTO op_shrl_T1_im_cc(void) | ||
| 330 | -{ | ||
| 331 | - env->CF = (T1 >> (PARAM1 - 1)) & 1; | ||
| 332 | - T1 = (uint32_t)T1 >> PARAM1; | ||
| 333 | -} | ||
| 334 | - | ||
| 335 | -void OPPROTO op_shrl_T1_0_cc(void) | ||
| 336 | -{ | ||
| 337 | - env->CF = (T1 >> 31) & 1; | ||
| 338 | - T1 = 0; | ||
| 339 | -} | ||
| 340 | - | ||
| 341 | -void OPPROTO op_sarl_T1_im_cc(void) | ||
| 342 | -{ | ||
| 343 | - env->CF = (T1 >> (PARAM1 - 1)) & 1; | ||
| 344 | - T1 = (int32_t)T1 >> PARAM1; | ||
| 345 | -} | ||
| 346 | - | ||
| 347 | -void OPPROTO op_sarl_T1_0_cc(void) | ||
| 348 | -{ | ||
| 349 | - env->CF = (T1 >> 31) & 1; | ||
| 350 | - T1 = (int32_t)T1 >> 31; | ||
| 351 | -} | ||
| 352 | - | ||
| 353 | -void OPPROTO op_rorl_T1_im_cc(void) | ||
| 354 | -{ | ||
| 355 | - int shift; | ||
| 356 | - shift = PARAM1; | ||
| 357 | - env->CF = (T1 >> (shift - 1)) & 1; | ||
| 358 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | ||
| 359 | -} | ||
| 360 | - | ||
| 361 | -void OPPROTO op_rrxl_T1_cc(void) | ||
| 362 | -{ | ||
| 363 | - uint32_t c; | ||
| 364 | - c = T1 & 1; | ||
| 365 | - T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31); | ||
| 366 | - env->CF = c; | ||
| 367 | -} | ||
| 368 | - | ||
| 369 | /* T1 based, use T0 as shift count */ | 320 | /* T1 based, use T0 as shift count */ |
| 370 | 321 | ||
| 371 | void OPPROTO op_shll_T1_T0(void) | 322 | void OPPROTO op_shll_T1_T0(void) |
| @@ -573,83 +524,6 @@ void OPPROTO op_subl_T0_T1_usaturate(void) | @@ -573,83 +524,6 @@ void OPPROTO op_subl_T0_T1_usaturate(void) | ||
| 573 | FORCE_RET(); | 524 | FORCE_RET(); |
| 574 | } | 525 | } |
| 575 | 526 | ||
| 576 | -/* Thumb shift by immediate */ | ||
| 577 | -void OPPROTO op_shll_T0_im_thumb_cc(void) | ||
| 578 | -{ | ||
| 579 | - int shift; | ||
| 580 | - shift = PARAM1; | ||
| 581 | - if (shift != 0) { | ||
| 582 | - env->CF = (T0 >> (32 - shift)) & 1; | ||
| 583 | - T0 = T0 << shift; | ||
| 584 | - } | ||
| 585 | - env->NZF = T0; | ||
| 586 | - FORCE_RET(); | ||
| 587 | -} | ||
| 588 | - | ||
| 589 | -void OPPROTO op_shll_T0_im_thumb(void) | ||
| 590 | -{ | ||
| 591 | - T0 = T0 << PARAM1; | ||
| 592 | - FORCE_RET(); | ||
| 593 | -} | ||
| 594 | - | ||
| 595 | -void OPPROTO op_shrl_T0_im_thumb_cc(void) | ||
| 596 | -{ | ||
| 597 | - int shift; | ||
| 598 | - | ||
| 599 | - shift = PARAM1; | ||
| 600 | - if (shift == 0) { | ||
| 601 | - env->CF = ((uint32_t)T0) >> 31; | ||
| 602 | - T0 = 0; | ||
| 603 | - } else { | ||
| 604 | - env->CF = (T0 >> (shift - 1)) & 1; | ||
| 605 | - T0 = T0 >> shift; | ||
| 606 | - } | ||
| 607 | - env->NZF = T0; | ||
| 608 | - FORCE_RET(); | ||
| 609 | -} | ||
| 610 | - | ||
| 611 | -void OPPROTO op_shrl_T0_im_thumb(void) | ||
| 612 | -{ | ||
| 613 | - int shift; | ||
| 614 | - | ||
| 615 | - shift = PARAM1; | ||
| 616 | - if (shift == 0) { | ||
| 617 | - T0 = 0; | ||
| 618 | - } else { | ||
| 619 | - T0 = T0 >> shift; | ||
| 620 | - } | ||
| 621 | - FORCE_RET(); | ||
| 622 | -} | ||
| 623 | - | ||
| 624 | -void OPPROTO op_sarl_T0_im_thumb_cc(void) | ||
| 625 | -{ | ||
| 626 | - int shift; | ||
| 627 | - | ||
| 628 | - shift = PARAM1; | ||
| 629 | - if (shift == 0) { | ||
| 630 | - T0 = ((int32_t)T0) >> 31; | ||
| 631 | - env->CF = T0 & 1; | ||
| 632 | - } else { | ||
| 633 | - env->CF = (T0 >> (shift - 1)) & 1; | ||
| 634 | - T0 = ((int32_t)T0) >> shift; | ||
| 635 | - } | ||
| 636 | - env->NZF = T0; | ||
| 637 | - FORCE_RET(); | ||
| 638 | -} | ||
| 639 | - | ||
| 640 | -void OPPROTO op_sarl_T0_im_thumb(void) | ||
| 641 | -{ | ||
| 642 | - int shift; | ||
| 643 | - | ||
| 644 | - shift = PARAM1; | ||
| 645 | - if (shift == 0) { | ||
| 646 | - env->CF = T0 & 1; | ||
| 647 | - } else { | ||
| 648 | - T0 = ((int32_t)T0) >> shift; | ||
| 649 | - } | ||
| 650 | - FORCE_RET(); | ||
| 651 | -} | ||
| 652 | - | ||
| 653 | /* exceptions */ | 527 | /* exceptions */ |
| 654 | 528 | ||
| 655 | void OPPROTO op_swi(void) | 529 | void OPPROTO op_swi(void) |
target-arm/translate.c
| @@ -228,12 +228,14 @@ static void gen_add16(TCGv t0, TCGv t1) | @@ -228,12 +228,14 @@ static void gen_add16(TCGv t0, TCGv t1) | ||
| 228 | dead_tmp(t1); | 228 | dead_tmp(t1); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | +#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF)) | ||
| 232 | + | ||
| 231 | /* Set CF to the top bit of var. */ | 233 | /* Set CF to the top bit of var. */ |
| 232 | static void gen_set_CF_bit31(TCGv var) | 234 | static void gen_set_CF_bit31(TCGv var) |
| 233 | { | 235 | { |
| 234 | TCGv tmp = new_tmp(); | 236 | TCGv tmp = new_tmp(); |
| 235 | tcg_gen_shri_i32(tmp, var, 31); | 237 | tcg_gen_shri_i32(tmp, var, 31); |
| 236 | - tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, CF)); | 238 | + gen_set_CF(var); |
| 237 | dead_tmp(tmp); | 239 | dead_tmp(tmp); |
| 238 | } | 240 | } |
| 239 | 241 | ||
| @@ -282,31 +284,67 @@ static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i) | @@ -282,31 +284,67 @@ static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i) | ||
| 282 | dead_tmp(tmp); | 284 | dead_tmp(tmp); |
| 283 | } | 285 | } |
| 284 | 286 | ||
| 285 | -/* Shift by immediate. Includes special handling for shift == 0. */ | ||
| 286 | -static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift) | 287 | +static void shifter_out_im(TCGv var, int shift) |
| 287 | { | 288 | { |
| 288 | - if (shift != 0) { | ||
| 289 | - switch (shiftop) { | ||
| 290 | - case 0: tcg_gen_shli_i32(var, var, shift); break; | ||
| 291 | - case 1: tcg_gen_shri_i32(var, var, shift); break; | ||
| 292 | - case 2: tcg_gen_sari_i32(var, var, shift); break; | ||
| 293 | - case 3: tcg_gen_rori_i32(var, var, shift); break; | ||
| 294 | - } | 289 | + TCGv tmp = new_tmp(); |
| 290 | + if (shift == 0) { | ||
| 291 | + tcg_gen_andi_i32(tmp, var, 1); | ||
| 295 | } else { | 292 | } else { |
| 296 | - TCGv tmp; | 293 | + tcg_gen_shri_i32(tmp, var, shift); |
| 294 | + if (shift != 31); | ||
| 295 | + tcg_gen_andi_i32(tmp, tmp, 1); | ||
| 296 | + } | ||
| 297 | + gen_set_CF(tmp); | ||
| 298 | + dead_tmp(tmp); | ||
| 299 | +} | ||
| 297 | 300 | ||
| 298 | - switch (shiftop) { | ||
| 299 | - case 0: break; | ||
| 300 | - case 1: tcg_gen_movi_i32(var, 0); break; | ||
| 301 | - case 2: tcg_gen_sari_i32(var, var, 31); break; | ||
| 302 | - case 3: /* rrx */ | ||
| 303 | - tcg_gen_shri_i32(var, var, 1); | ||
| 304 | - tmp = new_tmp(); | 301 | +/* Shift by immediate. Includes special handling for shift == 0. */ |
| 302 | +static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) | ||
| 303 | +{ | ||
| 304 | + switch (shiftop) { | ||
| 305 | + case 0: /* LSL */ | ||
| 306 | + if (shift != 0) { | ||
| 307 | + if (flags) | ||
| 308 | + shifter_out_im(var, 32 - shift); | ||
| 309 | + tcg_gen_shli_i32(var, var, shift); | ||
| 310 | + } | ||
| 311 | + break; | ||
| 312 | + case 1: /* LSR */ | ||
| 313 | + if (shift == 0) { | ||
| 314 | + if (flags) { | ||
| 315 | + tcg_gen_shri_i32(var, var, 31); | ||
| 316 | + gen_set_CF(var); | ||
| 317 | + } | ||
| 318 | + tcg_gen_movi_i32(var, 0); | ||
| 319 | + } else { | ||
| 320 | + if (flags) | ||
| 321 | + shifter_out_im(var, shift - 1); | ||
| 322 | + tcg_gen_shri_i32(var, var, shift); | ||
| 323 | + } | ||
| 324 | + break; | ||
| 325 | + case 2: /* ASR */ | ||
| 326 | + if (shift == 0) | ||
| 327 | + shift = 32; | ||
| 328 | + if (flags) | ||
| 329 | + shifter_out_im(var, shift - 1); | ||
| 330 | + if (shift == 32) | ||
| 331 | + shift = 31; | ||
| 332 | + tcg_gen_sari_i32(var, var, shift); | ||
| 333 | + break; | ||
| 334 | + case 3: /* ROR/RRX */ | ||
| 335 | + if (shift != 0) { | ||
| 336 | + if (flags) | ||
| 337 | + shifter_out_im(var, shift - 1); | ||
| 338 | + tcg_gen_rori_i32(var, var, shift); break; | ||
| 339 | + } else { | ||
| 340 | + TCGv tmp = new_tmp(); | ||
| 305 | tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF)); | 341 | tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF)); |
| 342 | + if (flags) | ||
| 343 | + shifter_out_im(var, 0); | ||
| 344 | + tcg_gen_shri_i32(var, var, 1); | ||
| 306 | tcg_gen_shli_i32(tmp, tmp, 31); | 345 | tcg_gen_shli_i32(tmp, tmp, 31); |
| 307 | tcg_gen_or_i32(var, var, tmp); | 346 | tcg_gen_or_i32(var, var, tmp); |
| 308 | dead_tmp(tmp); | 347 | dead_tmp(tmp); |
| 309 | - break; | ||
| 310 | } | 348 | } |
| 311 | } | 349 | } |
| 312 | }; | 350 | }; |
| @@ -392,20 +430,6 @@ const uint8_t table_logic_cc[16] = { | @@ -392,20 +430,6 @@ const uint8_t table_logic_cc[16] = { | ||
| 392 | 1, /* mvn */ | 430 | 1, /* mvn */ |
| 393 | }; | 431 | }; |
| 394 | 432 | ||
| 395 | -static GenOpFunc1 *gen_shift_T1_im_cc[4] = { | ||
| 396 | - gen_op_shll_T1_im_cc, | ||
| 397 | - gen_op_shrl_T1_im_cc, | ||
| 398 | - gen_op_sarl_T1_im_cc, | ||
| 399 | - gen_op_rorl_T1_im_cc, | ||
| 400 | -}; | ||
| 401 | - | ||
| 402 | -static GenOpFunc *gen_shift_T1_0_cc[4] = { | ||
| 403 | - NULL, | ||
| 404 | - gen_op_shrl_T1_0_cc, | ||
| 405 | - gen_op_sarl_T1_0_cc, | ||
| 406 | - gen_op_rrxl_T1_cc, | ||
| 407 | -}; | ||
| 408 | - | ||
| 409 | static GenOpFunc *gen_shift_T1_T0[4] = { | 433 | static GenOpFunc *gen_shift_T1_T0[4] = { |
| 410 | gen_op_shll_T1_T0, | 434 | gen_op_shll_T1_T0, |
| 411 | gen_op_shrl_T1_T0, | 435 | gen_op_shrl_T1_T0, |
| @@ -420,18 +444,6 @@ static GenOpFunc *gen_shift_T1_T0_cc[4] = { | @@ -420,18 +444,6 @@ static GenOpFunc *gen_shift_T1_T0_cc[4] = { | ||
| 420 | gen_op_rorl_T1_T0_cc, | 444 | gen_op_rorl_T1_T0_cc, |
| 421 | }; | 445 | }; |
| 422 | 446 | ||
| 423 | -static GenOpFunc1 *gen_shift_T0_im_thumb_cc[3] = { | ||
| 424 | - gen_op_shll_T0_im_thumb_cc, | ||
| 425 | - gen_op_shrl_T0_im_thumb_cc, | ||
| 426 | - gen_op_sarl_T0_im_thumb_cc, | ||
| 427 | -}; | ||
| 428 | - | ||
| 429 | -static GenOpFunc1 *gen_shift_T0_im_thumb[3] = { | ||
| 430 | - gen_op_shll_T0_im_thumb, | ||
| 431 | - gen_op_shrl_T0_im_thumb, | ||
| 432 | - gen_op_sarl_T0_im_thumb, | ||
| 433 | -}; | ||
| 434 | - | ||
| 435 | /* Set PC and thumb state from T0. Clobbers T0. */ | 447 | /* Set PC and thumb state from T0. Clobbers T0. */ |
| 436 | static inline void gen_bx(DisasContext *s) | 448 | static inline void gen_bx(DisasContext *s) |
| 437 | { | 449 | { |
| @@ -530,7 +542,7 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) | @@ -530,7 +542,7 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) | ||
| 530 | shift = (insn >> 7) & 0x1f; | 542 | shift = (insn >> 7) & 0x1f; |
| 531 | shiftop = (insn >> 5) & 3; | 543 | shiftop = (insn >> 5) & 3; |
| 532 | offset = load_reg(s, rm); | 544 | offset = load_reg(s, rm); |
| 533 | - gen_arm_shift_im(offset, shiftop, shift); | 545 | + gen_arm_shift_im(offset, shiftop, shift, 0); |
| 534 | if (!(insn & (1 << 23))) | 546 | if (!(insn & (1 << 23))) |
| 535 | tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset); | 547 | tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset); |
| 536 | else | 548 | else |
| @@ -5126,15 +5138,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | @@ -5126,15 +5138,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) | ||
| 5126 | shiftop = (insn >> 5) & 3; | 5138 | shiftop = (insn >> 5) & 3; |
| 5127 | if (!(insn & (1 << 4))) { | 5139 | if (!(insn & (1 << 4))) { |
| 5128 | shift = (insn >> 7) & 0x1f; | 5140 | shift = (insn >> 7) & 0x1f; |
| 5129 | - if (logic_cc) { | ||
| 5130 | - if (shift != 0) { | ||
| 5131 | - gen_shift_T1_im_cc[shiftop](shift); | ||
| 5132 | - } else if (shiftop != 0) { | ||
| 5133 | - gen_shift_T1_0_cc[shiftop](); | ||
| 5134 | - } | ||
| 5135 | - } else { | ||
| 5136 | - gen_arm_shift_im(cpu_T[1], shiftop, shift); | ||
| 5137 | - } | 5141 | + gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc); |
| 5138 | } else { | 5142 | } else { |
| 5139 | rs = (insn >> 8) & 0xf; | 5143 | rs = (insn >> 8) & 0xf; |
| 5140 | gen_movl_T0_reg(s, rs); | 5144 | gen_movl_T0_reg(s, rs); |
| @@ -6243,15 +6247,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | @@ -6243,15 +6247,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) | ||
| 6243 | shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); | 6247 | shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); |
| 6244 | conds = (insn & (1 << 20)) != 0; | 6248 | conds = (insn & (1 << 20)) != 0; |
| 6245 | logic_cc = (conds && thumb2_logic_op(op)); | 6249 | logic_cc = (conds && thumb2_logic_op(op)); |
| 6246 | - if (logic_cc) { | ||
| 6247 | - if (shift != 0) { | ||
| 6248 | - gen_shift_T1_im_cc[shiftop](shift); | ||
| 6249 | - } else if (shiftop != 0) { | ||
| 6250 | - gen_shift_T1_0_cc[shiftop](); | ||
| 6251 | - } | ||
| 6252 | - } else { | ||
| 6253 | - gen_arm_shift_im(cpu_T[1], shiftop, shift); | ||
| 6254 | - } | 6250 | + gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc); |
| 6255 | if (gen_thumb2_data_op(s, op, conds, 0)) | 6251 | if (gen_thumb2_data_op(s, op, conds, 0)) |
| 6256 | goto illegal_op; | 6252 | goto illegal_op; |
| 6257 | if (rd != 15) | 6253 | if (rd != 15) |
| @@ -6960,12 +6956,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) | @@ -6960,12 +6956,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) | ||
| 6960 | /* shift immediate */ | 6956 | /* shift immediate */ |
| 6961 | rm = (insn >> 3) & 7; | 6957 | rm = (insn >> 3) & 7; |
| 6962 | shift = (insn >> 6) & 0x1f; | 6958 | shift = (insn >> 6) & 0x1f; |
| 6963 | - gen_movl_T0_reg(s, rm); | ||
| 6964 | - if (s->condexec_mask) | ||
| 6965 | - gen_shift_T0_im_thumb[op](shift); | ||
| 6966 | - else | ||
| 6967 | - gen_shift_T0_im_thumb_cc[op](shift); | ||
| 6968 | - gen_movl_reg_T0(s, rd); | 6959 | + tmp = load_reg(s, rm); |
| 6960 | + gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0); | ||
| 6961 | + if (!s->condexec_mask) | ||
| 6962 | + gen_logic_CC(tmp); | ||
| 6963 | + store_reg(s, rd, tmp); | ||
| 6969 | } | 6964 | } |
| 6970 | break; | 6965 | break; |
| 6971 | case 2: case 3: | 6966 | case 2: case 3: |