|
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