1c3fb76b9STaylor SimpsonHexagon is Qualcomm's very long instruction word (VLIW) digital signal 2375bcf38STaylor Simpsonprocessor(DSP). We also support Hexagon Vector eXtensions (HVX). HVX 3375bcf38STaylor Simpsonis a wide vector coprocessor designed for high performance computer vision, 4375bcf38STaylor Simpsonimage processing, machine learning, and other workloads. 5c3fb76b9STaylor Simpson 6c3fb76b9STaylor SimpsonThe following versions of the Hexagon core are supported 7c3fb76b9STaylor Simpson Scalar core: v67 8c3fb76b9STaylor Simpson https://developer.qualcomm.com/downloads/qualcomm-hexagon-v67-programmer-s-reference-manual 9375bcf38STaylor Simpson HVX extension: v66 10375bcf38STaylor Simpson https://developer.qualcomm.com/downloads/qualcomm-hexagon-v66-hvx-programmer-s-reference-manual 11c3fb76b9STaylor Simpson 12c3fb76b9STaylor SimpsonWe presented an overview of the project at the 2019 KVM Forum. 13c3fb76b9STaylor Simpson https://kvmforum2019.sched.com/event/Tmwc/qemu-hexagon-automatic-translation-of-the-isa-manual-pseudcode-to-tiny-code-instructions-of-a-vliw-architecture-niccolo-izzo-revng-taylor-simpson-qualcomm-innovation-center 14c3fb76b9STaylor Simpson 15c3fb76b9STaylor Simpson*** Tour of the code *** 16c3fb76b9STaylor Simpson 17c3fb76b9STaylor SimpsonThe qemu-hexagon implementation is a combination of qemu and the Hexagon 18c3fb76b9STaylor Simpsonarchitecture library (aka archlib). The three primary directories with 19c3fb76b9STaylor SimpsonHexagon-specific code are 20c3fb76b9STaylor Simpson 21c3fb76b9STaylor Simpson qemu/target/hexagon 22c3fb76b9STaylor Simpson This has all the instruction and packet semantics 23c3fb76b9STaylor Simpson qemu/target/hexagon/imported 24c3fb76b9STaylor Simpson These files are imported with very little modification from archlib 25c3fb76b9STaylor Simpson *.idef Instruction semantics definition 26c3fb76b9STaylor Simpson macros.def Mapping of macros to instruction attributes 27c3fb76b9STaylor Simpson encode*.def Encoding patterns for each instruction 28c3fb76b9STaylor Simpson iclass.def Instruction class definitions used to determine 29c3fb76b9STaylor Simpson legal VLIW slots for each instruction 3095e11505SAlessandro Di Federico qemu/target/hexagon/idef-parser 3195e11505SAlessandro Di Federico Parser that, given the high-level definitions of an instruction, 3295e11505SAlessandro Di Federico produces a C function generating equivalent tiny code instructions. 3395e11505SAlessandro Di Federico See README.rst. 34c3fb76b9STaylor Simpson qemu/linux-user/hexagon 35c3fb76b9STaylor Simpson Helpers for loading the ELF file and making Linux system calls, 36c3fb76b9STaylor Simpson signals, etc 37c3fb76b9STaylor Simpson 38c3fb76b9STaylor SimpsonWe start with scripts that generate a bunch of include files. This 39c3fb76b9STaylor Simpsonis a two step process. The first step is to use the C preprocessor to expand 40c3fb76b9STaylor Simpsonmacros inside the architecture definition files. This is done in 41c3fb76b9STaylor Simpsontarget/hexagon/gen_semantics.c. This step produces 42c3fb76b9STaylor Simpson <BUILD_DIR>/target/hexagon/semantics_generated.pyinc. 43c3fb76b9STaylor SimpsonThat file is consumed by the following python scripts to produce the indicated 44c3fb76b9STaylor Simpsonheader files in <BUILD_DIR>/target/hexagon 45c3fb76b9STaylor Simpson gen_opcodes_def.py -> opcodes_def_generated.h.inc 46c3fb76b9STaylor Simpson gen_op_regs.py -> op_regs_generated.h.inc 47c3fb76b9STaylor Simpson gen_printinsn.py -> printinsn_generated.h.inc 48c3fb76b9STaylor Simpson gen_op_attribs.py -> op_attribs_generated.h.inc 49c3fb76b9STaylor Simpson gen_helper_protos.py -> helper_protos_generated.h.inc 50c3fb76b9STaylor Simpson gen_shortcode.py -> shortcode_generated.h.inc 51c3fb76b9STaylor Simpson gen_tcg_funcs.py -> tcg_funcs_generated.c.inc 52c3fb76b9STaylor Simpson gen_tcg_func_table.py -> tcg_func_table_generated.c.inc 53c3fb76b9STaylor Simpson gen_helper_funcs.py -> helper_funcs_generated.c.inc 5495e11505SAlessandro Di Federico gen_idef_parser_funcs.py -> idef_parser_input.h 55*10849c26STaylor Simpson gen_analyze_funcs.py -> analyze_funcs_generated.c.inc 56c3fb76b9STaylor Simpson 57c3fb76b9STaylor SimpsonQemu helper functions have 3 parts 58c3fb76b9STaylor Simpson DEF_HELPER declaration indicates the signature of the helper 59c3fb76b9STaylor Simpson gen_helper_<NAME> will generate a TCG call to the helper function 60c3fb76b9STaylor Simpson The helper implementation 61c3fb76b9STaylor Simpson 62c3fb76b9STaylor SimpsonHere's an example of the A2_add instruction. 63c3fb76b9STaylor Simpson Instruction tag A2_add 64c3fb76b9STaylor Simpson Assembly syntax "Rd32=add(Rs32,Rt32)" 65c3fb76b9STaylor Simpson Instruction semantics "{ RdV=RsV+RtV;}" 66c3fb76b9STaylor Simpson 67c3fb76b9STaylor SimpsonBy convention, the operands are identified by letter 68c3fb76b9STaylor Simpson RdV is the destination register 69c3fb76b9STaylor Simpson RsV, RtV are source registers 70c3fb76b9STaylor Simpson 71c3fb76b9STaylor SimpsonThe generator uses the operand naming conventions (see large comment in 72c3fb76b9STaylor Simpsonhex_common.py) to determine the signature of the helper function. Here are the 73c3fb76b9STaylor Simpsonresults for A2_add 74c3fb76b9STaylor Simpson 75c3fb76b9STaylor Simpsonhelper_protos_generated.h.inc 76c3fb76b9STaylor Simpson DEF_HELPER_3(A2_add, s32, env, s32, s32) 77c3fb76b9STaylor Simpson 78c3fb76b9STaylor Simpsontcg_funcs_generated.c.inc 79c3fb76b9STaylor Simpson static void generate_A2_add( 80c3fb76b9STaylor Simpson CPUHexagonState *env, 81c3fb76b9STaylor Simpson DisasContext *ctx, 82c3fb76b9STaylor Simpson Insn *insn, 83c3fb76b9STaylor Simpson Packet *pkt) 84c3fb76b9STaylor Simpson { 857a819de8SRichard Henderson TCGv RdV = tcg_temp_new(); 86c3fb76b9STaylor Simpson const int RdN = insn->regno[0]; 87c3fb76b9STaylor Simpson TCGv RsV = hex_gpr[insn->regno[1]]; 88c3fb76b9STaylor Simpson TCGv RtV = hex_gpr[insn->regno[2]]; 89c3fb76b9STaylor Simpson gen_helper_A2_add(RdV, cpu_env, RsV, RtV); 90c3fb76b9STaylor Simpson gen_log_reg_write(RdN, RdV); 91c3fb76b9STaylor Simpson } 92c3fb76b9STaylor Simpson 93c3fb76b9STaylor Simpsonhelper_funcs_generated.c.inc 94c3fb76b9STaylor Simpson int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV) 95c3fb76b9STaylor Simpson { 96c3fb76b9STaylor Simpson uint32_t slot __attribute__((unused)) = 4; 97c3fb76b9STaylor Simpson int32_t RdV = 0; 98c3fb76b9STaylor Simpson { RdV=RsV+RtV;} 99c3fb76b9STaylor Simpson return RdV; 100c3fb76b9STaylor Simpson } 101c3fb76b9STaylor Simpson 102c3fb76b9STaylor SimpsonNote that generate_A2_add updates the disassembly context to be processed 103c3fb76b9STaylor Simpsonwhen the packet commits (see "Packet Semantics" below). 104c3fb76b9STaylor Simpson 105c3fb76b9STaylor SimpsonThe generator checks for fGEN_TCG_<tag> macro. This allows us to generate 106c3fb76b9STaylor SimpsonTCG code instead of a call to the helper. If defined, the macro takes 1 107c3fb76b9STaylor Simpsonargument. 108c3fb76b9STaylor Simpson C semantics (aka short code) 109c3fb76b9STaylor Simpson 110c3fb76b9STaylor SimpsonThis allows the code generator to override the auto-generated code. In some 111c3fb76b9STaylor Simpsoncases this is necessary for correct execution. We can also override for 112c3fb76b9STaylor Simpsonfaster emulation. For example, calling a helper for add is more expensive 113c3fb76b9STaylor Simpsonthan generating a TCG add operation. 114c3fb76b9STaylor Simpson 115c3fb76b9STaylor SimpsonThe gen_tcg.h file has any overrides. For example, we could write 116c3fb76b9STaylor Simpson #define fGEN_TCG_A2_add(GENHLPR, SHORTCODE) \ 117c3fb76b9STaylor Simpson tcg_gen_add_tl(RdV, RsV, RtV) 118c3fb76b9STaylor Simpson 119c3fb76b9STaylor SimpsonThe instruction semantics C code relies heavily on macros. In cases where the 120c3fb76b9STaylor SimpsonC semantics are specified only with macros, we can override the default with 121c3fb76b9STaylor Simpsonthe short semantics option and #define the macros to generate TCG code. One 122c3fb76b9STaylor Simpsonexample is L2_loadw_locked: 123c3fb76b9STaylor Simpson Instruction tag L2_loadw_locked 124c3fb76b9STaylor Simpson Assembly syntax "Rd32=memw_locked(Rs32)" 125c3fb76b9STaylor Simpson Instruction semantics "{ fEA_REG(RsV); fLOAD_LOCKED(1,4,u,EA,RdV) }" 126c3fb76b9STaylor Simpson 127c3fb76b9STaylor SimpsonIn gen_tcg.h, we use the shortcode 128c3fb76b9STaylor Simpson#define fGEN_TCG_L2_loadw_locked(SHORTCODE) \ 129c3fb76b9STaylor Simpson SHORTCODE 130c3fb76b9STaylor Simpson 131c3fb76b9STaylor SimpsonThere are also cases where we brute force the TCG code generation. 132c3fb76b9STaylor SimpsonInstructions with multiple definitions are examples. These require special 133c3fb76b9STaylor Simpsonhandling because qemu helpers can only return a single value. 134c3fb76b9STaylor Simpson 135375bcf38STaylor SimpsonFor HVX vectors, the generator behaves slightly differently. The wide vectors 136375bcf38STaylor Simpsonwon't fit in a TCGv or TCGv_i64, so we pass TCGv_ptr variables to pass the 137375bcf38STaylor Simpsonaddress to helper functions. Here's an example for an HVX vector-add-word 138375bcf38STaylor Simpsonistruction. 139375bcf38STaylor Simpson static void generate_V6_vaddw( 140375bcf38STaylor Simpson CPUHexagonState *env, 141375bcf38STaylor Simpson DisasContext *ctx, 142375bcf38STaylor Simpson Insn *insn, 143375bcf38STaylor Simpson Packet *pkt) 144375bcf38STaylor Simpson { 145375bcf38STaylor Simpson const int VdN = insn->regno[0]; 146375bcf38STaylor Simpson const intptr_t VdV_off = 147375bcf38STaylor Simpson ctx_future_vreg_off(ctx, VdN, 1, true); 1487a819de8SRichard Henderson TCGv_ptr VdV = tcg_temp_new_ptr(); 149375bcf38STaylor Simpson tcg_gen_addi_ptr(VdV, cpu_env, VdV_off); 150375bcf38STaylor Simpson const int VuN = insn->regno[1]; 151375bcf38STaylor Simpson const intptr_t VuV_off = 152375bcf38STaylor Simpson vreg_src_off(ctx, VuN); 1537a819de8SRichard Henderson TCGv_ptr VuV = tcg_temp_new_ptr(); 154375bcf38STaylor Simpson const int VvN = insn->regno[2]; 155375bcf38STaylor Simpson const intptr_t VvV_off = 156375bcf38STaylor Simpson vreg_src_off(ctx, VvN); 1577a819de8SRichard Henderson TCGv_ptr VvV = tcg_temp_new_ptr(); 158375bcf38STaylor Simpson tcg_gen_addi_ptr(VuV, cpu_env, VuV_off); 159375bcf38STaylor Simpson tcg_gen_addi_ptr(VvV, cpu_env, VvV_off); 160375bcf38STaylor Simpson TCGv slot = tcg_constant_tl(insn->slot); 161375bcf38STaylor Simpson gen_helper_V6_vaddw(cpu_env, VdV, VuV, VvV, slot); 162375bcf38STaylor Simpson gen_log_vreg_write(ctx, VdV_off, VdN, EXT_DFL, insn->slot, false); 163375bcf38STaylor Simpson } 164375bcf38STaylor Simpson 165375bcf38STaylor SimpsonNotice that we also generate a variable named <operand>_off for each operand of 166375bcf38STaylor Simpsonthe instruction. This makes it easy to override the instruction semantics with 167375bcf38STaylor Simpsonfunctions from tcg-op-gvec.h. Here's the override for this instruction. 168375bcf38STaylor Simpson #define fGEN_TCG_V6_vaddw(SHORTCODE) \ 169375bcf38STaylor Simpson tcg_gen_gvec_add(MO_32, VdV_off, VuV_off, VvV_off, \ 170375bcf38STaylor Simpson sizeof(MMVector), sizeof(MMVector)) 171375bcf38STaylor Simpson 172375bcf38STaylor SimpsonFinally, we notice that the override doesn't use the TCGv_ptr variables, so 173375bcf38STaylor Simpsonwe don't generate them when an override is present. Here is what we generate 174375bcf38STaylor Simpsonwhen the override is present. 175375bcf38STaylor Simpson static void generate_V6_vaddw( 176375bcf38STaylor Simpson CPUHexagonState *env, 177375bcf38STaylor Simpson DisasContext *ctx, 178375bcf38STaylor Simpson Insn *insn, 179375bcf38STaylor Simpson Packet *pkt) 180375bcf38STaylor Simpson { 181375bcf38STaylor Simpson const int VdN = insn->regno[0]; 182375bcf38STaylor Simpson const intptr_t VdV_off = 183375bcf38STaylor Simpson ctx_future_vreg_off(ctx, VdN, 1, true); 184375bcf38STaylor Simpson const int VuN = insn->regno[1]; 185375bcf38STaylor Simpson const intptr_t VuV_off = 186375bcf38STaylor Simpson vreg_src_off(ctx, VuN); 187375bcf38STaylor Simpson const int VvN = insn->regno[2]; 188375bcf38STaylor Simpson const intptr_t VvV_off = 189375bcf38STaylor Simpson vreg_src_off(ctx, VvN); 190375bcf38STaylor Simpson fGEN_TCG_V6_vaddw({ fHIDE(int i;) fVFOREACH(32, i) { VdV.w[i] = VuV.w[i] + VvV.w[i] ; } }); 191375bcf38STaylor Simpson gen_log_vreg_write(ctx, VdV_off, VdN, EXT_DFL, insn->slot, false); 192375bcf38STaylor Simpson } 193375bcf38STaylor Simpson 194*10849c26STaylor SimpsonWe also generate an analyze_<tag> function for each instruction. Currently, 195*10849c26STaylor Simpsonthese functions record the writes to registers by calling ctx_log_*. During 196*10849c26STaylor Simpsongen_start_packet, we invoke the analyze_<tag> function for each instruction in 197*10849c26STaylor Simpsonthe packet, and we mark the implicit writes. After the analysis is performed, 198*10849c26STaylor Simpsonwe initialize hex_new_value for each of the predicated assignments. 199*10849c26STaylor Simpson 200c3fb76b9STaylor SimpsonIn addition to instruction semantics, we use a generator to create the decode 201c3fb76b9STaylor Simpsontree. This generation is also a two step process. The first step is to run 202c3fb76b9STaylor Simpsontarget/hexagon/gen_dectree_import.c to produce 203c3fb76b9STaylor Simpson <BUILD_DIR>/target/hexagon/iset.py 204c3fb76b9STaylor SimpsonThis file is imported by target/hexagon/dectree.py to produce 205c3fb76b9STaylor Simpson <BUILD_DIR>/target/hexagon/dectree_generated.h.inc 206c3fb76b9STaylor Simpson 207c3fb76b9STaylor Simpson*** Key Files *** 208c3fb76b9STaylor Simpson 209c3fb76b9STaylor Simpsoncpu.h 210c3fb76b9STaylor Simpson 211c3fb76b9STaylor SimpsonThis file contains the definition of the CPUHexagonState struct. It is the 212c3fb76b9STaylor Simpsonruntime information for each thread and contains stuff like the GPR and 213c3fb76b9STaylor Simpsonpredicate registers. 214c3fb76b9STaylor Simpson 215c3fb76b9STaylor Simpsonmacros.h 216375bcf38STaylor Simpsonmmvec/macros.h 217c3fb76b9STaylor Simpson 218c3fb76b9STaylor SimpsonThe Hexagon arch lib relies heavily on macros for the instruction semantics. 219c3fb76b9STaylor SimpsonThis is a great advantage for qemu because we can override them for different 220c3fb76b9STaylor Simpsonpurposes. You will also notice there are sometimes two definitions of a macro. 221c3fb76b9STaylor SimpsonThe QEMU_GENERATE variable determines whether we want the macro to generate TCG 222c3fb76b9STaylor Simpsoncode. If QEMU_GENERATE is not defined, we want the macro to generate vanilla 223c3fb76b9STaylor SimpsonC code that will work in the helper implementation. 224c3fb76b9STaylor Simpson 225c3fb76b9STaylor Simpsontranslate.c 226c3fb76b9STaylor Simpson 227c3fb76b9STaylor SimpsonThe functions in this file generate TCG code for a translation block. Some 228c3fb76b9STaylor Simpsonimportant functions in this file are 229c3fb76b9STaylor Simpson 230c3fb76b9STaylor Simpson gen_start_packet - initialize the data structures for packet semantics 231c3fb76b9STaylor Simpson gen_commit_packet - commit the register writes, stores, etc for a packet 232c3fb76b9STaylor Simpson decode_and_translate_packet - disassemble a packet and generate code 233c3fb76b9STaylor Simpson 234c3fb76b9STaylor Simpsongenptr.c 235c3fb76b9STaylor Simpsongen_tcg.h 236c3fb76b9STaylor Simpson 237c3fb76b9STaylor SimpsonThese files create a function for each instruction. It is mostly composed of 238c3fb76b9STaylor SimpsonfGEN_TCG_<tag> definitions followed by including tcg_funcs_generated.c.inc. 239c3fb76b9STaylor Simpson 240c3fb76b9STaylor Simpsonop_helper.c 241c3fb76b9STaylor Simpson 242c3fb76b9STaylor SimpsonThis file contains the implementations of all the helpers. There are a few 243c3fb76b9STaylor Simpsongeneral purpose helpers, but most of them are generated by including 244c3fb76b9STaylor Simpsonhelper_funcs_generated.c.inc. There are also several helpers used for debugging. 245c3fb76b9STaylor Simpson 246c3fb76b9STaylor Simpson 247c3fb76b9STaylor Simpson*** Packet Semantics *** 248c3fb76b9STaylor Simpson 249c3fb76b9STaylor SimpsonVLIW packet semantics differ from serial semantics in that all input operands 250c3fb76b9STaylor Simpsonare read, then the operations are performed, then all the results are written. 251c3fb76b9STaylor SimpsonFor exmaple, this packet performs a swap of registers r0 and r1 252c3fb76b9STaylor Simpson { r0 = r1; r1 = r0 } 253c3fb76b9STaylor SimpsonNote that the result is different if the instructions are executed serially. 254c3fb76b9STaylor Simpson 255c3fb76b9STaylor SimpsonPacket semantics dictate that we defer any changes of state until the entire 256c3fb76b9STaylor Simpsonpacket is committed. We record the results of each instruction in a side data 257c3fb76b9STaylor Simpsonstructure, and update the visible processor state when we commit the packet. 258c3fb76b9STaylor Simpson 259c3fb76b9STaylor SimpsonThe data structures are divided between the runtime state and the translation 260c3fb76b9STaylor Simpsoncontext. 261c3fb76b9STaylor Simpson 262c3fb76b9STaylor SimpsonDuring the TCG generation (see translate.[ch]), we use the DisasContext to 263c3fb76b9STaylor Simpsontrack what needs to be done during packet commit. Here are the relevant 264c3fb76b9STaylor Simpsonfields 265c3fb76b9STaylor Simpson 266c3fb76b9STaylor Simpson reg_log list of registers written 267c3fb76b9STaylor Simpson reg_log_idx index into ctx_reg_log 268c3fb76b9STaylor Simpson pred_log list of predicates written 269c3fb76b9STaylor Simpson pred_log_idx index into ctx_pred_log 270c3fb76b9STaylor Simpson store_width width of stores (indexed by slot) 271c3fb76b9STaylor Simpson 272c3fb76b9STaylor SimpsonDuring runtime, the following fields in CPUHexagonState (see cpu.h) are used 273c3fb76b9STaylor Simpson 274c3fb76b9STaylor Simpson new_value new value of a given register 275c3fb76b9STaylor Simpson reg_written boolean indicating if register was written 276c3fb76b9STaylor Simpson new_pred_value new value of a predicate register 277c3fb76b9STaylor Simpson pred_written boolean indicating if predicate was written 278c3fb76b9STaylor Simpson mem_log_stores record of the stores (indexed by slot) 279c3fb76b9STaylor Simpson 280375bcf38STaylor SimpsonFor Hexagon Vector eXtensions (HVX), the following fields are used 281375bcf38STaylor Simpson VRegs Vector registers 282375bcf38STaylor Simpson future_VRegs Registers to be stored during packet commit 283375bcf38STaylor Simpson tmp_VRegs Temporary registers *not* stored during commit 284375bcf38STaylor Simpson VRegs_updated Mask of predicated vector writes 285375bcf38STaylor Simpson QRegs Q (vector predicate) registers 286375bcf38STaylor Simpson future_QRegs Registers to be stored during packet commit 287375bcf38STaylor Simpson QRegs_updated Mask of predicated vector writes 288375bcf38STaylor Simpson 289c3fb76b9STaylor Simpson*** Debugging *** 290c3fb76b9STaylor Simpson 291c3fb76b9STaylor SimpsonYou can turn on a lot of debugging by changing the HEX_DEBUG macro to 1 in 292c3fb76b9STaylor Simpsoninternal.h. This will stream a lot of information as it generates TCG and 293c3fb76b9STaylor Simpsonexecutes the code. 294c3fb76b9STaylor Simpson 295c3fb76b9STaylor SimpsonTo track down nasty issues with Hexagon->TCG generation, we compare the 296c3fb76b9STaylor Simpsonexecution results with actual hardware running on a Hexagon Linux target. 297c3fb76b9STaylor SimpsonRun qemu with the "-d cpu" option. Then, we can diff the results and figure 298c3fb76b9STaylor Simpsonout where qemu and hardware behave differently. 299c3fb76b9STaylor Simpson 300c3fb76b9STaylor SimpsonThe stacks are located at different locations. We handle this by changing 301c3fb76b9STaylor Simpsonenv->stack_adjust in translate.c. First, set this to zero and run qemu. 302c3fb76b9STaylor SimpsonThen, change env->stack_adjust to the difference between the two stack 303c3fb76b9STaylor Simpsonlocations. Then rebuild qemu and run again. That will produce a very 304c3fb76b9STaylor Simpsonclean diff. 305c3fb76b9STaylor Simpson 306c3fb76b9STaylor SimpsonHere are some handy places to set breakpoints 307c3fb76b9STaylor Simpson 308c3fb76b9STaylor Simpson At the call to gen_start_packet for a given PC (note that the line number 309c3fb76b9STaylor Simpson might change in the future) 310c3fb76b9STaylor Simpson br translate.c:602 if ctx->base.pc_next == 0xdeadbeef 311c3fb76b9STaylor Simpson The helper function for each instruction is named helper_<TAG>, so here's 312c3fb76b9STaylor Simpson an example that will set a breakpoint at the start 313c3fb76b9STaylor Simpson br helper_A2_add 314c3fb76b9STaylor Simpson If you have the HEX_DEBUG macro set, the following will be useful 315c3fb76b9STaylor Simpson At the start of execution of a packet for a given PC 316c3fb76b9STaylor Simpson br helper_debug_start_packet if env->gpr[41] == 0xdeadbeef 317c3fb76b9STaylor Simpson At the end of execution of a packet for a given PC 318c3fb76b9STaylor Simpson br helper_debug_commit_end if env->this_PC == 0xdeadbeef 319