|
55 | 55 |
|
56 | 56 | #define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base))
|
57 | 57 | #define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12))
|
| 58 | + |
| 59 | +#define OP_LDRH_W_HI(reg_base) (0xf8b0 | (reg_base)) |
| 60 | +#define OP_LDRH_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12)) |
58 | 61 | #endif
|
59 | 62 |
|
60 | 63 | static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {
|
@@ -449,46 +452,67 @@ static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uin
|
449 | 452 | }
|
450 | 453 | #endif
|
451 | 454 |
|
| 455 | +#if !MICROPY_EMIT_THUMB_ARMV7M |
| 456 | +// emits code for: reg_dest = reg_base + offset << offset_shift |
| 457 | +static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint offset_shift) { |
| 458 | + if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) { |
| 459 | + if (offset << offset_shift < 256) { |
| 460 | + if (reg_dest != reg_base) { |
| 461 | + asm_thumb_mov_reg_reg(as, reg_dest, reg_base); |
| 462 | + } |
| 463 | + asm_thumb_add_rlo_i8(as, reg_dest, offset << offset_shift); |
| 464 | + } else if (UNSIGNED_FIT8(offset) && reg_dest != reg_base) { |
| 465 | + asm_thumb_mov_rlo_i8(as, reg_dest, offset); |
| 466 | + asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, offset_shift); |
| 467 | + asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base); |
| 468 | + } else if (reg_dest != reg_base) { |
| 469 | + asm_thumb_mov_rlo_i16(as, reg_dest, offset << offset_shift); |
| 470 | + asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest); |
| 471 | + } else { |
| 472 | + uint reg_other = reg_dest ^ 7; |
| 473 | + asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other))); |
| 474 | + asm_thumb_mov_rlo_i16(as, reg_other, offset << offset_shift); |
| 475 | + asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other); |
| 476 | + asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other))); |
| 477 | + } |
| 478 | + } else { |
| 479 | + assert(0); // should never be called for ARMV6M |
| 480 | + } |
| 481 | +} |
| 482 | +#endif |
| 483 | + |
452 | 484 | void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) {
|
453 | 485 | if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) {
|
454 | 486 | asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset);
|
455 | 487 | } else {
|
456 | 488 | #if MICROPY_EMIT_THUMB_ARMV7M
|
457 | 489 | asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset);
|
458 | 490 | #else
|
459 |
| - word_offset -= 31; |
460 |
| - if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) { |
461 |
| - if (UNSIGNED_FIT8(word_offset) && (word_offset < 64 || reg_dest != reg_base)) { |
462 |
| - if (word_offset < 64) { |
463 |
| - if (reg_dest != reg_base) { |
464 |
| - asm_thumb_mov_reg_reg(as, reg_dest, reg_base); |
465 |
| - } |
466 |
| - asm_thumb_add_rlo_i8(as, reg_dest, word_offset * 4); |
467 |
| - } else { |
468 |
| - asm_thumb_mov_rlo_i8(as, reg_dest, word_offset); |
469 |
| - asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, 2); |
470 |
| - asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base); |
471 |
| - } |
472 |
| - } else { |
473 |
| - if (reg_dest != reg_base) { |
474 |
| - asm_thumb_mov_rlo_i16(as, reg_dest, word_offset * 4); |
475 |
| - asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest); |
476 |
| - } else { |
477 |
| - uint reg_other = reg_dest ^ 7; |
478 |
| - asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other))); |
479 |
| - asm_thumb_mov_rlo_i16(as, reg_other, word_offset * 4); |
480 |
| - asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other); |
481 |
| - asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other))); |
482 |
| - } |
483 |
| - } |
484 |
| - } else { |
485 |
| - assert(0); // should never be called for ARMV6M |
486 |
| - } |
| 491 | + asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, word_offset - 31, 2); |
487 | 492 | asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_dest, 31);
|
488 | 493 | #endif
|
489 | 494 | }
|
490 | 495 | }
|
491 | 496 |
|
| 497 | +#if MICROPY_EMIT_THUMB_ARMV7M |
| 498 | +static inline void asm_thumb_ldrh_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) { |
| 499 | + asm_thumb_op32(as, OP_LDRH_W_HI(reg_base), OP_LDRH_W_LO(reg_dest, uint16_offset * 2)); |
| 500 | +} |
| 501 | +#endif |
| 502 | + |
| 503 | +void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) { |
| 504 | + if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(uint16_offset)) { |
| 505 | + asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_base, uint16_offset); |
| 506 | + } else { |
| 507 | + #if MICROPY_EMIT_THUMB_ARMV7M |
| 508 | + asm_thumb_ldrh_reg_reg_i12(as, reg_dest, reg_base, uint16_offset); |
| 509 | + #else |
| 510 | + asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, uint16_offset - 31, 1); |
| 511 | + asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_dest, 31); |
| 512 | + #endif |
| 513 | + } |
| 514 | +} |
| 515 | + |
492 | 516 | // this could be wrong, because it should have a range of +/- 16MiB...
|
493 | 517 | #define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
|
494 | 518 | #define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
|
|
0 commit comments