/ deps / KittyMemoryEx / KittyAsm.cpp
KittyAsm.cpp
  1  #include "KittyAsm.hpp"
  2  
  3  // refs to
  4  // https://github.com/CAS-Atlantic/AArch64-Encoding
  5  // https://github.com/bminor/binutils-gdb
  6  // https://github.com/capstone-engine/capstone
  7  // https://github.com/qemu/QEMU
  8  // https://reverseengineering.stackexchange.com/questions/15418/getting-function-address-by-reading-adrp-and-add-instruction-values
  9  // https://stackoverflow.com/questions/41906688/what-are-the-semantics-of-adrp-and-adrl-instructions-in-arm-assembly
 10  
 11  namespace KittyAsm
 12  {
 13      uint32_t bits(uint32_t v, int hi, int lo)
 14      {
 15          if (hi < lo)
 16              return 0u;
 17  
 18          int width = hi - lo + 1;
 19          if (width >= 32)
 20              return v >> lo;
 21  
 22          uint32_t mask = (width == 32) ? 0xFFFFFFFFu : ((1u << width) - 1u);
 23          return (v >> lo) & mask;
 24      }
 25  } // namespace KittyAsm
 26  
 27  using namespace KittyAsm;
 28  
 29  namespace KittyArm32
 30  {
 31      EKittyInsnTypeArm32 decodeInsnType(uint32_t instr)
 32      {
 33          if ((instr & 0x0C000000) == 0x00000000)
 34          {
 35              if ((instr & 0x01E00000) == 0x00800000)
 36                  return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::ADR : EKittyInsnTypeArm32::ADD;
 37  
 38              if ((instr & 0x01E00000) == 0x00400000)
 39                  return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::ADR : EKittyInsnTypeArm32::SUB;
 40  
 41              if ((instr & 0x01E00000) == 0x01A00000)
 42                  return EKittyInsnTypeArm32::MOV;
 43          }
 44  
 45          if ((instr & 0x0FF00000) == 0x02800000)
 46              return EKittyInsnTypeArm32::LDR_LITERAL;
 47  
 48          if ((instr & 0x0C500000) == 0x04100000)
 49              return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::LDR_LITERAL : EKittyInsnTypeArm32::LDR;
 50  
 51          if ((instr & 0x0C500000) == 0x04000000)
 52              return EKittyInsnTypeArm32::STR;
 53  
 54          if ((instr & 0x0C500000) == 0x04500000)
 55              return bits(instr, 19, 16) == 15 ? EKittyInsnTypeArm32::LDR_LITERAL : EKittyInsnTypeArm32::LDRB;
 56  
 57          if ((instr & 0x0C500000) == 0x04400000)
 58              return EKittyInsnTypeArm32::STRB;
 59  
 60          if ((instr & 0x0F1000F0) == 0x011000B0)
 61              return EKittyInsnTypeArm32::LDRH;
 62  
 63          if ((instr & 0x0F1000F0) == 0x010000B0)
 64              return EKittyInsnTypeArm32::STRH;
 65  
 66          if ((instr & 0x0F1000F0) == 0x011000D0)
 67              return EKittyInsnTypeArm32::LDRSB;
 68  
 69          if ((instr & 0x0F1000F0) == 0x011000F0)
 70              return EKittyInsnTypeArm32::LDRSH;
 71  
 72          if ((instr & 0x0F000000) == 0x0A000000)
 73              return bits(instr, 31, 28) == 0xE ? EKittyInsnTypeArm32::B : EKittyInsnTypeArm32::B_COND;
 74  
 75          if ((instr & 0x0F000000) == 0x0B000000)
 76              return EKittyInsnTypeArm32::BL;
 77  
 78          return EKittyInsnTypeArm32::UNKNOWN;
 79      }
 80  
 81      KittyInsnArm32 decodeInsn(uint32_t instr, uint32_t address)
 82      {
 83          KittyInsnArm32 insn{};
 84  
 85          EKittyInsnTypeArm32 insn_type = decodeInsnType(instr);
 86          if (insn_type == EKittyInsnTypeArm32::UNKNOWN)
 87              return insn;
 88  
 89          insn.bytes = instr;
 90          insn.address = address;
 91          insn.type = insn_type;
 92          insn.typeStr = typeToString(insn_type);
 93  
 94          switch (insn_type)
 95          {
 96          case EKittyInsnTypeArm32::UNKNOWN:
 97              return insn;
 98  
 99          case EKittyInsnTypeArm32::ADD:
100          case EKittyInsnTypeArm32::SUB:
101          case EKittyInsnTypeArm32::MOV:
102          case EKittyInsnTypeArm32::ADR:
103          {
104              bool I = bit(instr, 25);
105              uint32_t rn = bits(instr, 19, 16);
106              uint32_t rd = bits(instr, 15, 12);
107              uint32_t imm12 = bits(instr, 11, 0);
108              uint32_t imm8 = bits(imm12, 7, 0);
109              uint32_t rot = bits(imm12, 11, 8) * 2u;
110              uint32_t imm32 = ror32(imm8, rot);
111              insn.rd = regName(rd);
112  
113              if (insn_type != EKittyInsnTypeArm32::MOV)
114                  insn.rn = regName(rn);
115  
116              if (!I)
117                  insn.rt = regName(imm12);
118              else
119                  insn.immediate = I ? imm32 : 0;
120  
121              if (rn == 15)
122                  insn.target = address + 8u + insn.immediate;
123  
124              break;
125          }
126  
127          case EKittyInsnTypeArm32::LDRH:
128          case EKittyInsnTypeArm32::LDRSH:
129          case EKittyInsnTypeArm32::LDRSB:
130          case EKittyInsnTypeArm32::STRH:
131          {
132              bool U = bit(instr, 23);
133              uint32_t rn = bits(instr, 19, 16);
134              uint32_t rd = bits(instr, 15, 12);
135              uint32_t immH = bits(instr, 11, 8);
136              uint32_t immL = bits(instr, 3, 0);
137              uint32_t offset = (immH << 4) | immL;
138              insn.rd = regName(rd);
139              insn.rn = regName(rn);
140              insn.immediate = U ? offset : -((int32_t)offset);
141              break;
142          }
143  
144          case EKittyInsnTypeArm32::LDR:
145          case EKittyInsnTypeArm32::LDRB:
146          case EKittyInsnTypeArm32::STR:
147          case EKittyInsnTypeArm32::STRB:
148          case EKittyInsnTypeArm32::LDR_LITERAL:
149          {
150              bool U = bit(instr, 23);
151              uint32_t rn = bits(instr, 19, 16);
152              uint32_t rd = bits(instr, 15, 12);
153              uint32_t imm12 = bits(instr, 11, 0);
154              insn.rd = regName(rd);
155              insn.rn = regName(rn);
156              insn.immediate = U ? imm12 : -((int32_t)imm12);
157              // PC
158              if (rn == 15)
159              {
160                  insn.target = address + 8u + insn.immediate;
161              }
162              break;
163          }
164  
165          case EKittyInsnTypeArm32::B:
166          case EKittyInsnTypeArm32::BL:
167          case EKittyInsnTypeArm32::B_COND:
168          {
169              uint32_t cond = bits(instr, 31, 28);
170              uint32_t imm24 = bits(instr, 23, 0);
171              int32_t simm = signExtend(imm24, 24) << 2;
172              insn.immediate = simm;
173              insn.target = address + 8u + simm;
174              if (insn_type == EKittyInsnTypeArm32::B_COND)
175              {
176                  insn.cond = branchCondName(cond);
177              }
178              break;
179          }
180          }
181  
182          return insn;
183      }
184  
185      std::string typeToString(EKittyInsnTypeArm32 t)
186      {
187  #define CASE(x)                                                                                                        \
188      case EKittyInsnTypeArm32::x:                                                                                       \
189          return #x;
190          switch (t)
191          {
192              CASE(UNKNOWN)
193              CASE(ADR)
194              CASE(ADD)
195              CASE(SUB)
196              CASE(MOV)
197              CASE(LDR)
198              CASE(STR)
199              CASE(LDRB)
200              CASE(STRB)
201              CASE(LDRH)
202              CASE(STRH)
203              CASE(LDRSH)
204              CASE(LDRSB)
205              CASE(LDR_LITERAL)
206              CASE(B)
207              CASE(BL)
208              CASE(B_COND)
209          }
210  #undef CASE
211          return "UNKNOWN";
212      }
213  } // namespace KittyArm32
214  
215  namespace KittyArm64
216  {
217      EKittyInsnTypeArm64 decodeInsnType(uint32_t instr)
218      {
219          // ADR
220          if ((instr & 0x9F000000u) == 0x10000000u)
221          {
222              return EKittyInsnTypeArm64::ADR;
223          }
224          // ADRP
225          if ((instr & 0x9F000000u) == 0x90000000u)
226          {
227              return EKittyInsnTypeArm64::ADRP;
228          }
229  
230          // ADD
231          if ((instr & 0xFF000000u) == 0x11000000u || (instr & 0xFF000000u) == 0x91000000u)
232          {
233              return EKittyInsnTypeArm64::ADD;
234          }
235          // SUB
236          if ((instr & 0xFF000000u) == 0x51000000u || (instr & 0xFF000000u) == 0xD1000000u)
237          {
238              return EKittyInsnTypeArm64::SUB;
239          }
240  
241          // MOVZ
242          if ((instr & 0x7F800000u) == 0x52800000u)
243          {
244              return EKittyInsnTypeArm64::MOVZ;
245          }
246          // MOVK
247          if ((instr & 0x7F800000u) == 0x72800000u)
248          {
249              return EKittyInsnTypeArm64::MOVK;
250          }
251          // MOVN
252          if ((instr & 0x7F800000u) == 0x12800000u)
253          {
254              return EKittyInsnTypeArm64::MOVN;
255          }
256  
257          // Load/Store (immediate offset)
258          {
259              if ((instr & 0xFFC00000) == 0xF9400000)
260                  return EKittyInsnTypeArm64::LDR;
261              if ((instr & 0xFFC00000) == 0xF9000000)
262                  return EKittyInsnTypeArm64::STR;
263              if ((instr & 0xFFC00000) == 0xB9400000)
264                  return EKittyInsnTypeArm64::LDRW;
265              if ((instr & 0xFFC00000) == 0xB9000000)
266                  return EKittyInsnTypeArm64::STRW;
267  
268              if ((instr & 0xFFC00000) == 0x39400000)
269                  return EKittyInsnTypeArm64::LDRB;
270              if ((instr & 0xFFC00000) == 0x39000000)
271                  return EKittyInsnTypeArm64::STRB;
272  
273              if ((instr & 0xFFC00000) == 0x79400000)
274                  return EKittyInsnTypeArm64::LDRH;
275              if ((instr & 0xFFC00000) == 0x79000000)
276                  return EKittyInsnTypeArm64::STRH;
277  
278              if ((instr & 0xFFC00000) == 0x39C00000 || (instr & 0xFFC00000) == 0x39800000)
279                  return EKittyInsnTypeArm64::LDRSB;
280              if ((instr & 0xFFC00000) == 0x79C00000 || (instr & 0xFFC00000) == 0x79800000)
281                  return EKittyInsnTypeArm64::LDRSH;
282              if ((instr & 0xFFC00000) == 0xB9800000)
283                  return EKittyInsnTypeArm64::LDRSW;
284          }
285  
286          // Load/Store (post-indexed)
287          {
288              if ((instr & 0xFFC00C00) == 0xB8400400 || (instr & 0xFFC00C00) == 0xF8400400)
289                  return EKittyInsnTypeArm64::LDR_POST;
290              if ((instr & 0xFFC00C00) == 0xB8000400 || (instr & 0xFFC00C00) == 0xF8000400)
291                  return EKittyInsnTypeArm64::STR_POST;
292  
293              if ((instr & 0xFFC00C00) == 0x38400400)
294                  return EKittyInsnTypeArm64::LDRB_POST;
295              if ((instr & 0xFFC00C00) == 0x38000400)
296                  return EKittyInsnTypeArm64::STRB_POST;
297  
298              if ((instr & 0xFFC00C00) == 0x78400400)
299                  return EKittyInsnTypeArm64::LDRH_POST;
300              if ((instr & 0xFFC00C00) == 0x78000400)
301                  return EKittyInsnTypeArm64::STRH_POST;
302  
303              if ((instr & 0xFFC00C00) == 0x38C00400 || (instr & 0xFFC00C00) == 0x38800400)
304                  return EKittyInsnTypeArm64::LDRSB_POST;
305              if ((instr & 0xFFC00C00) == 0x78C00400 || (instr & 0xFFC00C00) == 0x78800400)
306                  return EKittyInsnTypeArm64::LDRSH_POST;
307              if ((instr & 0xFFC00C00) == 0xB8800400)
308                  return EKittyInsnTypeArm64::LDRSW_POST;
309          }
310  
311          // Load/Store (pre-indexed)
312          {
313              if ((instr & 0xFFC00C00) == 0xB8400C00 || (instr & 0xFFC00C00) == 0xF8400C00)
314                  return EKittyInsnTypeArm64::LDR_PRE;
315              if ((instr & 0xFFC00C00) == 0xB8000C00 || (instr & 0xFFC00C00) == 0xF8000C00)
316                  return EKittyInsnTypeArm64::STR_PRE;
317  
318              if ((instr & 0xFFC00C00) == 0x38400C00)
319                  return EKittyInsnTypeArm64::LDRB_PRE;
320              if ((instr & 0xFFC00C00) == 0x38000C00)
321                  return EKittyInsnTypeArm64::STRB_PRE;
322  
323              if ((instr & 0xFFC00C00) == 0x78400C00)
324                  return EKittyInsnTypeArm64::LDRH_PRE;
325              if ((instr & 0xFFC00C00) == 0x78000C00)
326                  return EKittyInsnTypeArm64::STRH_PRE;
327  
328              if ((instr & 0xFFC00C00) == 0x38C00C00 || (instr & 0xFFC00C00) == 0x38800C00)
329                  return EKittyInsnTypeArm64::LDRSB_PRE;
330              if ((instr & 0xFFC00C00) == 0x78C00C00 || (instr & 0xFFC00C00) == 0x78800C00)
331                  return EKittyInsnTypeArm64::LDRSH_PRE;
332              if ((instr & 0xFFC00C00) == 0xB8800C00)
333                  return EKittyInsnTypeArm64::LDRSW_PRE;
334          }
335  
336          // === Load/Store (unscaled)
337          {
338              if ((instr & 0xFFC00000) == 0xF8400000)
339                  return EKittyInsnTypeArm64::LDUR;
340              if ((instr & 0xFFC00000) == 0xF8000000)
341                  return EKittyInsnTypeArm64::STUR;
342              if ((instr & 0xFFC00000) == 0xB8400000)
343                  return EKittyInsnTypeArm64::LDURW;
344              if ((instr & 0xFFC00000) == 0xB8000000)
345                  return EKittyInsnTypeArm64::STURW;
346              if ((instr & 0xFFC00000) == 0x38400000)
347                  return EKittyInsnTypeArm64::LDURB;
348              if ((instr & 0xFFC00000) == 0x38000000)
349                  return EKittyInsnTypeArm64::STURB;
350              if ((instr & 0xFFC00000) == 0x78400000)
351                  return EKittyInsnTypeArm64::LDURH;
352              if ((instr & 0xFFC00000) == 0x78000000)
353                  return EKittyInsnTypeArm64::STURH;
354              if ((instr & 0xFFC00000) == 0xB8800000)
355                  return EKittyInsnTypeArm64::LDURSW;
356              if ((instr & 0xFFC00000) == 0x38800000u || (instr & 0xFFC00000) == 0x38C00000u)
357                  return EKittyInsnTypeArm64::LDURSB;
358              if ((instr & 0xFFC00000) == 0x78800000u || (instr & 0xFFC00000) == 0x78C00000u)
359                  return EKittyInsnTypeArm64::LDURSH;
360          }
361  
362          // Load/Store (Literal)
363          {
364              if ((instr & 0xFFC00000) == 0x18000000)
365                  return EKittyInsnTypeArm64::LDRW_LITERAL;
366              if ((instr & 0xFFC00000) == 0x58000000)
367                  return EKittyInsnTypeArm64::LDR_LITERAL;
368              if ((instr & 0xFFC00000) == 0x98000000)
369                  return EKittyInsnTypeArm64::LDRSW_LITERAL;
370          }
371  
372          // B
373          if ((instr & 0xFC000000u) == 0x14000000u)
374          {
375              return EKittyInsnTypeArm64::B;
376          }
377  
378          // BL
379          if ((instr & 0xFC000000u) == 0x94000000u)
380          {
381              return EKittyInsnTypeArm64::BL;
382          }
383  
384          // B.Cond
385          if ((instr & 0xFF000010u) == 0x54000000u)
386          {
387              return EKittyInsnTypeArm64::B_COND;
388          }
389  
390          // CBZ/CBNZ
391          {
392              if ((instr & 0x7F000000u) == 0x34000000u)
393                  return EKittyInsnTypeArm64::CBZ;
394              if ((instr & 0x7F000000u) == 0x35000000u)
395                  return EKittyInsnTypeArm64::CBNZ;
396          }
397  
398          // TBZ/TBNZ
399          {
400              if ((instr & 0x7F000000u) == 0x36000000u)
401                  return EKittyInsnTypeArm64::TBZ;
402              if ((instr & 0x7F000000u) == 0x37000000u)
403                  return EKittyInsnTypeArm64::TBNZ;
404          }
405  
406          return EKittyInsnTypeArm64::UNKNOWN;
407      }
408  
409      KittyInsnArm64 decodeInsn(uint32_t instr, uint64_t address)
410      {
411          KittyInsnArm64 insn{};
412  
413          EKittyInsnTypeArm64 insn_type = decodeInsnType(instr);
414          if (insn_type == EKittyInsnTypeArm64::UNKNOWN)
415              return insn;
416  
417          insn.bytes = instr;
418          insn.address = address;
419          insn.type = insn_type;
420          insn.typeStr = typeToString(insn_type);
421  
422          switch (insn_type)
423          {
424          case EKittyInsnTypeArm64::UNKNOWN:
425              return insn;
426  
427          case EKittyInsnTypeArm64::ADR:
428          case EKittyInsnTypeArm64::ADRP:
429          {
430              uint32_t rd = bits(instr, 4, 0);
431              uint32_t immlo = bits(instr, 30, 29);
432              uint32_t immhi = bits(instr, 23, 5);
433              uint64_t imm = (uint64_t)((immhi << 2) | immlo);
434              insn.rd = xRegName(rd, false);
435              if (insn_type == EKittyInsnTypeArm64::ADR)
436              {
437  
438                  int64_t simm = signExtend(imm, 21);
439                  insn.immediate = simm;
440                  insn.target = address + simm;
441              }
442              else
443              {
444                  int64_t simm = signExtend(imm, 21) << 12;
445                  insn.immediate = simm;
446                  insn.target = (address & ~0xFFFULL) + simm;
447              }
448              break;
449          }
450  
451          case EKittyInsnTypeArm64::MOVZ:
452          case EKittyInsnTypeArm64::MOVK:
453          case EKittyInsnTypeArm64::MOVN:
454          {
455              bool is64 = bit(instr, 31);
456              uint32_t rd = bits(instr, 4, 0);
457              uint32_t imm16 = bits(instr, 20, 5);
458              uint32_t hw = bits(instr, 22, 21);
459              uint64_t imm = (uint64_t)(imm16 << (hw * 16));
460              insn.rd = is64 ? xRegName(rd, false) : wRegName(rd, false);
461              insn.immediate = insn_type != EKittyInsnTypeArm64::MOVN ? imm : (int64_t)~imm;
462              break;
463          }
464  
465          case EKittyInsnTypeArm64::ADD:
466          case EKittyInsnTypeArm64::SUB:
467          {
468              bool is64 = bit(instr, 31);
469              uint32_t rd = bits(instr, 4, 0);
470              uint32_t rn = bits(instr, 9, 5);
471              uint32_t imm12 = bits(instr, 21, 10);
472              uint32_t sh = bits(instr, 23, 22);
473              uint64_t imm = (uint64_t)(sh == 1 ? imm12 << 12 : imm12);
474              insn.rd = is64 ? xRegName(rd, false) : wRegName(rd, false);
475              insn.rn = is64 ? xRegName(rn, true) : wRegName(rn, true);
476              insn.immediate = imm;
477              break;
478          }
479  
480          // ldr/str uimm12
481          case EKittyInsnTypeArm64::LDR:
482          case EKittyInsnTypeArm64::STR:
483          case EKittyInsnTypeArm64::LDRW:
484          case EKittyInsnTypeArm64::STRW:
485          case EKittyInsnTypeArm64::LDRB:
486          case EKittyInsnTypeArm64::STRB:
487          case EKittyInsnTypeArm64::LDRH:
488          case EKittyInsnTypeArm64::STRH:
489          case EKittyInsnTypeArm64::LDRSB:
490          case EKittyInsnTypeArm64::LDRSH:
491          case EKittyInsnTypeArm64::LDRSW:
492          {
493              uint32_t size = bits(instr, 31, 30);
494              uint32_t rn = bits(instr, 9, 5);
495              uint32_t rt = bits(instr, 4, 0);
496              uint32_t imm12 = bits(instr, 21, 10);
497              uint64_t offset = (uint64_t)(imm12 << size);
498              insn.rn = xRegName(rn, true);
499              insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false);
500              insn.immediate = offset;
501              break;
502          }
503  
504          // ldr/str post/pre indexed imm9
505          case EKittyInsnTypeArm64::LDR_PRE:
506          case EKittyInsnTypeArm64::STR_PRE:
507          case EKittyInsnTypeArm64::LDRB_PRE:
508          case EKittyInsnTypeArm64::STRB_PRE:
509          case EKittyInsnTypeArm64::LDRH_PRE:
510          case EKittyInsnTypeArm64::STRH_PRE:
511          case EKittyInsnTypeArm64::LDRSB_PRE:
512          case EKittyInsnTypeArm64::LDRSH_PRE:
513          case EKittyInsnTypeArm64::LDRSW_PRE:
514          case EKittyInsnTypeArm64::LDR_POST:
515          case EKittyInsnTypeArm64::STR_POST:
516          case EKittyInsnTypeArm64::LDRB_POST:
517          case EKittyInsnTypeArm64::STRB_POST:
518          case EKittyInsnTypeArm64::LDRH_POST:
519          case EKittyInsnTypeArm64::STRH_POST:
520          case EKittyInsnTypeArm64::LDRSB_POST:
521          case EKittyInsnTypeArm64::LDRSH_POST:
522          case EKittyInsnTypeArm64::LDRSW_POST:
523          {
524              uint32_t size = bits(instr, 31, 30);
525              uint32_t rn = bits(instr, 9, 5);
526              uint32_t rt = bits(instr, 4, 0);
527              uint32_t imm9 = bits(instr, 20, 12);
528              int64_t simm = signExtend(imm9, 9);
529              insn.rn = xRegName(rn, true);
530              insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false);
531              insn.immediate = simm;
532              break;
533          }
534  
535          // imm9 unscaled ldr/str
536          case EKittyInsnTypeArm64::LDUR:
537          case EKittyInsnTypeArm64::STUR:
538          case EKittyInsnTypeArm64::LDURW:
539          case EKittyInsnTypeArm64::STURW:
540          case EKittyInsnTypeArm64::LDURB:
541          case EKittyInsnTypeArm64::STURB:
542          case EKittyInsnTypeArm64::LDURH:
543          case EKittyInsnTypeArm64::STURH:
544          case EKittyInsnTypeArm64::LDURSB:
545          case EKittyInsnTypeArm64::LDURSH:
546          case EKittyInsnTypeArm64::LDURSW:
547          {
548              uint32_t size = bits(instr, 31, 30);
549              uint32_t rn = bits(instr, 9, 5);
550              uint32_t rt = bits(instr, 4, 0);
551              uint32_t imm9 = bits(instr, 20, 12);
552              int64_t simm = signExtend(imm9, 9);
553              insn.rn = xRegName(rn, true);
554              insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false);
555              insn.immediate = simm;
556              break;
557          }
558  
559          case EKittyInsnTypeArm64::LDR_LITERAL:
560          case EKittyInsnTypeArm64::LDRW_LITERAL:
561          case EKittyInsnTypeArm64::LDRSW_LITERAL:
562          {
563              uint32_t size = bits(instr, 31, 30);
564              uint32_t rt = bits(instr, 4, 0);
565              uint32_t imm19 = bits(instr, 23, 5);
566              int64_t simm = signExtend(imm19, 19) << 2;
567              insn.rn = "PC";
568              insn.rt = size == 3 ? xRegName(rt, false) : wRegName(rt, false);
569              insn.immediate = simm;
570              insn.target = address + simm;
571              break;
572          }
573  
574          case EKittyInsnTypeArm64::B:
575          case EKittyInsnTypeArm64::BL:
576          {
577              uint32_t imm26 = bits(instr, 25, 0);
578              int64_t simm = signExtend(imm26, 26) << 2;
579              insn.immediate = simm;
580              insn.target = address + simm;
581              break;
582          }
583  
584          case EKittyInsnTypeArm64::B_COND:
585          {
586              uint32_t cond = bits(instr, 3, 0);
587              uint32_t imm19 = bits(instr, 23, 5);
588              int64_t simm = signExtend(imm19, 19) << 2;
589              insn.immediate = simm;
590              insn.target = address + simm;
591              insn.cond = branchCondName(cond);
592              break;
593          }
594  
595          case EKittyInsnTypeArm64::CBZ:
596          case EKittyInsnTypeArm64::CBNZ:
597          {
598              bool is64 = bit(instr, 32);
599              uint32_t imm19 = bits(instr, 23, 5);
600              uint32_t rt = bits(instr, 4, 0);
601              int64_t simm = signExtend(imm19, 19) << 2;
602              insn.rt = is64 ? xRegName(rt, false) : wRegName(rt, false);
603              insn.immediate = simm;
604              insn.target = address + simm;
605              break;
606          }
607  
608          case EKittyInsnTypeArm64::TBZ:
609          case EKittyInsnTypeArm64::TBNZ:
610          {
611              bool is64 = bit(instr, 32);
612              uint32_t rt = bits(instr, 4, 0);
613              uint32_t bit5 = (bits(instr, 31, 31) & 1) << 5;
614              uint32_t bit_lo = bits(instr, 23, 19);
615              uint32_t bitpos = bit5 | bit_lo;
616              uint32_t imm14 = bits(instr, 18, 5);
617              int64_t simm = signExtend(imm14, 14) << 2;
618              insn.rt = is64 ? xRegName(rt, false) : wRegName(rt, false);
619              insn.immediate = simm;
620              insn.bitpos = bitpos;
621              insn.target = address + simm;
622              break;
623          }
624          }
625  
626          return insn;
627      }
628  
629      std::string typeToString(EKittyInsnTypeArm64 t)
630      {
631  #define CASE(x)                                                                                                        \
632      case EKittyInsnTypeArm64::x:                                                                                       \
633          return #x;
634          switch (t)
635          {
636              CASE(UNKNOWN)
637              CASE(ADR)
638              CASE(ADRP)
639              CASE(ADD)
640              CASE(SUB)
641              CASE(MOVZ)
642              CASE(MOVN)
643              CASE(MOVK)
644              CASE(LDR)
645              CASE(STR)
646              CASE(LDRW)
647              CASE(STRW)
648              CASE(LDRB)
649              CASE(STRB)
650              CASE(LDRH)
651              CASE(STRH)
652              CASE(LDRSB)
653              CASE(LDRSH)
654              CASE(LDRSW)
655              CASE(LDR_PRE)
656              CASE(STR_PRE)
657              CASE(LDRB_PRE)
658              CASE(STRB_PRE)
659              CASE(LDRH_PRE)
660              CASE(STRH_PRE)
661              CASE(LDRSB_PRE)
662              CASE(LDRSH_PRE)
663              CASE(LDRSW_PRE)
664              CASE(LDR_POST)
665              CASE(STR_POST)
666              CASE(LDRB_POST)
667              CASE(STRB_POST)
668              CASE(LDRH_POST)
669              CASE(STRH_POST)
670              CASE(LDRSB_POST)
671              CASE(LDRSH_POST)
672              CASE(LDRSW_POST)
673              CASE(LDUR)
674              CASE(STUR)
675              CASE(LDURW)
676              CASE(STURW)
677              CASE(LDURB)
678              CASE(STURB)
679              CASE(LDURH)
680              CASE(STURH)
681              CASE(LDURSB)
682              CASE(LDURSH)
683              CASE(LDURSW)
684              CASE(LDR_LITERAL)
685              CASE(LDRW_LITERAL)
686              CASE(LDRSW_LITERAL)
687              CASE(B)
688              CASE(BL)
689              CASE(B_COND)
690              CASE(CBZ)
691              CASE(CBNZ)
692              CASE(TBZ)
693              CASE(TBNZ)
694          }
695  #undef CASE
696          return "UNKNOWN";
697      }
698  } // namespace KittyArm64