|
| 1 | +#include "arm64.h" |
| 2 | +#include <stdbool.h> |
| 3 | + |
| 4 | +uint32_t generate_movk(uint8_t x, uint16_t val, uint16_t lsl) |
| 5 | +{ |
| 6 | + uint32_t base = 0b11110010100000000000000000000000; |
| 7 | + |
| 8 | + uint32_t hw = 0; |
| 9 | + if (lsl == 16) { |
| 10 | + hw = 0b01 << 21; |
| 11 | + } |
| 12 | + else if (lsl == 32) { |
| 13 | + hw = 0b10 << 21; |
| 14 | + } |
| 15 | + else if (lsl == 48) { |
| 16 | + hw = 0b11 << 21; |
| 17 | + } |
| 18 | + |
| 19 | + uint32_t imm16 = (uint32_t)val << 5; |
| 20 | + uint32_t rd = x & 0x1F; |
| 21 | + |
| 22 | + return base | hw | imm16 | rd; |
| 23 | +} |
| 24 | + |
| 25 | +uint32_t generate_br(uint8_t x) |
| 26 | +{ |
| 27 | + uint32_t base = 0b11010110000111110000000000000000; |
| 28 | + uint32_t rn = ((uint32_t)x & 0x1F) << 5; |
| 29 | + return base | rn; |
| 30 | +} |
| 31 | + |
| 32 | +bool decode_adrp(uint32_t inst, uint8_t *rd_out, int32_t *imm_out) |
| 33 | +{ |
| 34 | + if ((inst & 0x9F000000) != 0x90000000) return false; |
| 35 | + |
| 36 | + uint32_t mask_immlo = 0b01100000000000000000000000000000; |
| 37 | + uint32_t mask_immhi = 0b00000000111111111111111111100000; |
| 38 | + uint32_t mask_rd = 0b00000000000000000000000000011111; |
| 39 | + |
| 40 | + int32_t imm = (((inst & mask_immlo) >> 29) | ((inst & mask_immhi) >> 3)) << 12; |
| 41 | + uint8_t rd = inst & mask_rd; |
| 42 | + |
| 43 | + if (rd_out) *rd_out = rd; |
| 44 | + if (imm_out) *imm_out = imm; |
| 45 | + |
| 46 | + return true; |
| 47 | +} |
| 48 | + |
| 49 | +bool decode_ldr_imm(uint32_t inst, uint16_t *imm_out, uint8_t *rn_out, uint8_t *rt_out) |
| 50 | +{ |
| 51 | + if ((inst & 0xBFC00000) != 0xB9400000) return false; |
| 52 | + // TODO: Support non unsigned instructions |
| 53 | + |
| 54 | + uint32_t mask_imm12 = 0b00000000001111111111110000000000; |
| 55 | + uint32_t mask_rn = 0b00000000000000000000001111100000; |
| 56 | + uint32_t mask_rt = 0b00000000000000000000000000011111; |
| 57 | + |
| 58 | + uint8_t rt = (inst & mask_rt); |
| 59 | + uint8_t rn = (inst & mask_rn) >> 5; |
| 60 | + uint16_t imm12 = (inst & mask_imm12) >> 10; |
| 61 | + |
| 62 | + uint32_t bit_is_64_bit = 0b01000000000000000000000000000000; |
| 63 | + if (inst & bit_is_64_bit) { |
| 64 | + imm12 *= 8; |
| 65 | + } |
| 66 | + else { |
| 67 | + imm12 *= 4; |
| 68 | + } |
| 69 | + |
| 70 | + if (imm_out) *imm_out = imm12; |
| 71 | + if (rn_out) *rn_out = rn; |
| 72 | + if (rt_out) *rt_out = rt; |
| 73 | + |
| 74 | + return true; |
| 75 | +} |
| 76 | + |
| 77 | +bool decode_adrp_ldr(uint32_t adrp_inst, uint32_t ldr_inst, uint64_t pc, uint64_t *dst_out) |
| 78 | +{ |
| 79 | + int32_t adrp_imm = 0; |
| 80 | + if (!decode_adrp(adrp_inst, NULL, &adrp_imm)) return false; |
| 81 | + |
| 82 | + uint16_t ldr_imm = 0; |
| 83 | + if (!decode_ldr_imm(ldr_inst, &ldr_imm, NULL, NULL)) return false; |
| 84 | + |
| 85 | + uint64_t pc_page = pc - (pc % 0x1000); |
| 86 | + uint64_t dst = (pc_page + adrp_imm) + ldr_imm; |
| 87 | + if (dst_out) *dst_out = dst; |
| 88 | + return true; |
| 89 | +} |
| 90 | + |
| 91 | +/*bool decode_ldr(uint32_t inst, uint8_t *rt_out, uint8_t *rn_out, uint8_t *rm_out) |
| 92 | +{ |
| 93 | + if ((inst & 0xFFE00C00) != 0xF8600800) return false; |
| 94 | + |
| 95 | + uint32_t mask_rm = 0b00000000000111110000000000000000; |
| 96 | + uint32_t mask_option = 0b00000000000000001110000000000000; |
| 97 | + uint32_t mask_s = 0b00000000000000000001000000000000; |
| 98 | + uint32_t mask_rn = 0b00000000000000000000001111100000; |
| 99 | + uint32_t mask_rt = 0b00000000000000000000000000011111; |
| 100 | + |
| 101 | + uint8_t rt = inst & mask_rt; |
| 102 | + uint8_t rn = inst & mask_rn >> 5; |
| 103 | + uint8_t rm = inst & mask_rm >> 16; |
| 104 | + bool s = inst & mask_s >> 12; |
| 105 | + uint8_t option = inst & mask_option >> 13; |
| 106 | + |
| 107 | + printf("rt=%d, rn=%d, rm=%d, s=%d, option=%X\n", rt, rn, rm, s, option); |
| 108 | + |
| 109 | + return true; |
| 110 | +}*/ |
0 commit comments