@@ -212,12 +212,120 @@ uint64_t ReadCapstoneReg(HostThreadContext* context, arm64_reg reg) {
212212 return context->x [29 ];
213213 case ARM64_REG_X30:
214214 return context->x [30 ];
215+ case ARM64_REG_W0:
216+ return uint32_t (context->x [0 ]);
217+ case ARM64_REG_W1:
218+ return uint32_t (context->x [1 ]);
219+ case ARM64_REG_W2:
220+ return uint32_t (context->x [2 ]);
221+ case ARM64_REG_W3:
222+ return uint32_t (context->x [3 ]);
223+ case ARM64_REG_W4:
224+ return uint32_t (context->x [4 ]);
225+ case ARM64_REG_W5:
226+ return uint32_t (context->x [5 ]);
227+ case ARM64_REG_W6:
228+ return uint32_t (context->x [6 ]);
229+ case ARM64_REG_W7:
230+ return uint32_t (context->x [7 ]);
231+ case ARM64_REG_W8:
232+ return uint32_t (context->x [8 ]);
233+ case ARM64_REG_W9:
234+ return uint32_t (context->x [9 ]);
235+ case ARM64_REG_W10:
236+ return uint32_t (context->x [10 ]);
237+ case ARM64_REG_W11:
238+ return uint32_t (context->x [11 ]);
239+ case ARM64_REG_W12:
240+ return uint32_t (context->x [12 ]);
241+ case ARM64_REG_W13:
242+ return uint32_t (context->x [13 ]);
243+ case ARM64_REG_W14:
244+ return uint32_t (context->x [14 ]);
245+ case ARM64_REG_W15:
246+ return uint32_t (context->x [15 ]);
247+ case ARM64_REG_W16:
248+ return uint32_t (context->x [16 ]);
249+ case ARM64_REG_W17:
250+ return uint32_t (context->x [17 ]);
251+ case ARM64_REG_W18:
252+ return uint32_t (context->x [18 ]);
253+ case ARM64_REG_W19:
254+ return uint32_t (context->x [19 ]);
255+ case ARM64_REG_W20:
256+ return uint32_t (context->x [20 ]);
257+ case ARM64_REG_W21:
258+ return uint32_t (context->x [21 ]);
259+ case ARM64_REG_W22:
260+ return uint32_t (context->x [22 ]);
261+ case ARM64_REG_W23:
262+ return uint32_t (context->x [23 ]);
263+ case ARM64_REG_W24:
264+ return uint32_t (context->x [24 ]);
265+ case ARM64_REG_W25:
266+ return uint32_t (context->x [25 ]);
267+ case ARM64_REG_W26:
268+ return uint32_t (context->x [26 ]);
269+ case ARM64_REG_W27:
270+ return uint32_t (context->x [27 ]);
271+ case ARM64_REG_W28:
272+ return uint32_t (context->x [28 ]);
273+ case ARM64_REG_W29:
274+ return uint32_t (context->x [29 ]);
275+ case ARM64_REG_W30:
276+ return uint32_t (context->x [30 ]);
215277 default :
216278 assert_unhandled_case (reg);
217279 return 0 ;
218280 }
219281}
220282
283+ bool TestCapstonePstate (arm64_cc cond, uint32_t pstate) {
284+ // https://devblogs.microsoft.com/oldnewthing/20220815-00/?p=106975
285+ // Upper 4 bits of pstate are NZCV
286+ const bool N = !!(pstate & 0x80000000 );
287+ const bool Z = !!(pstate & 0x40000000 );
288+ const bool C = !!(pstate & 0x20000000 );
289+ const bool V = !!(pstate & 0x10000000 );
290+ switch (cond) {
291+ case ARM64_CC_EQ:
292+ return (Z == true );
293+ case ARM64_CC_NE:
294+ return (Z == false );
295+ case ARM64_CC_HS:
296+ return (C == true );
297+ case ARM64_CC_LO:
298+ return (C == false );
299+ case ARM64_CC_MI:
300+ return (N == true );
301+ case ARM64_CC_PL:
302+ return (N == false );
303+ case ARM64_CC_VS:
304+ return (V == true );
305+ case ARM64_CC_VC:
306+ return (V == false );
307+ case ARM64_CC_HI:
308+ return ((C == true ) && (Z == false ));
309+ case ARM64_CC_LS:
310+ return ((C == false ) || (Z == true ));
311+ case ARM64_CC_GE:
312+ return (N == V);
313+ case ARM64_CC_LT:
314+ return (N != V);
315+ case ARM64_CC_GT:
316+ return ((Z == false ) && (N == V));
317+ case ARM64_CC_LE:
318+ return ((Z == true ) || (N != V));
319+ case ARM64_CC_AL:
320+ return true ;
321+ case ARM64_CC_NV:
322+ return false ;
323+ default :
324+ assert_unhandled_case (cond);
325+ return false ;
326+ }
327+ }
328+
221329uint64_t A64Backend::CalculateNextHostInstruction (ThreadDebugInfo* thread_info,
222330 uint64_t current_pc) {
223331 auto machine_code_ptr = reinterpret_cast <const uint8_t *>(current_pc);
@@ -233,23 +341,52 @@ uint64_t A64Backend::CalculateNextHostInstruction(ThreadDebugInfo* thread_info,
233341 case ARM64_INS_B:
234342 case ARM64_INS_BL: {
235343 assert_true (detail.operands [0 ].type == ARM64_OP_IMM);
236- uint64_t target_pc = static_cast <uint64_t >(detail.operands [0 ].imm );
237- return current_pc + target_pc;
344+ const int64_t pc_offset = static_cast <int64_t >(detail.operands [0 ].imm );
345+ const bool test_passed =
346+ TestCapstonePstate (detail.cc , thread_info->host_context .cpsr );
347+ if (test_passed) {
348+ return current_pc + pc_offset;
349+ } else {
350+ return current_pc + insn.size ;
351+ }
238352 } break ;
239- case ARM64_INS_BLR :
240- case ARM64_INS_BR : {
353+ case ARM64_INS_BR :
354+ case ARM64_INS_BLR : {
241355 assert_true (detail.operands [0 ].type == ARM64_OP_REG);
242- uint64_t target_pc =
356+ const uint64_t target_pc =
243357 ReadCapstoneReg (&thread_info->host_context , detail.operands [0 ].reg );
244358 return target_pc;
245359 } break ;
246360 case ARM64_INS_RET: {
247- assert_zero (detail.op_count );
248- // Jump to link register
249- return thread_info->host_context .x [30 ];
361+ assert_true (detail.operands [0 ].type == ARM64_OP_REG);
362+ const uint64_t target_pc =
363+ ReadCapstoneReg (&thread_info->host_context , detail.operands [0 ].reg );
364+ return target_pc;
365+ } break ;
366+ case ARM64_INS_CBNZ: {
367+ assert_true (detail.operands [0 ].type == X86_OP_REG);
368+ assert_true (detail.operands [1 ].type == X86_OP_IMM);
369+ const int64_t pc_offset = static_cast <int64_t >(detail.operands [1 ].imm );
370+ const bool test_passed = (0 != ReadCapstoneReg (&thread_info->host_context ,
371+ detail.operands [0 ].reg ));
372+ if (test_passed) {
373+ return current_pc + pc_offset;
374+ } else {
375+ return current_pc + insn.size ;
376+ }
377+ } break ;
378+ case ARM64_INS_CBZ: {
379+ assert_true (detail.operands [0 ].type == X86_OP_REG);
380+ assert_true (detail.operands [1 ].type == X86_OP_IMM);
381+ const int64_t pc_offset = static_cast <int64_t >(detail.operands [1 ].imm );
382+ const bool test_passed = (0 == ReadCapstoneReg (&thread_info->host_context ,
383+ detail.operands [0 ].reg ));
384+ if (test_passed) {
385+ return current_pc + pc_offset;
386+ } else {
387+ return current_pc + insn.size ;
388+ }
250389 } break ;
251- case ARM64_INS_CBNZ:
252- case ARM64_INS_CBZ:
253390 default : {
254391 // Not a branching instruction - just move over it.
255392 return current_pc + insn.size ;
0 commit comments