qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

README (13882B)


      1 Hexagon is Qualcomm's very long instruction word (VLIW) digital signal
      2 processor(DSP).  We also support Hexagon Vector eXtensions (HVX).  HVX
      3 is a wide vector coprocessor designed for high performance computer vision,
      4 image processing, machine learning, and other workloads.
      5 
      6 The following versions of the Hexagon core are supported
      7     Scalar core: v67
      8     https://developer.qualcomm.com/downloads/qualcomm-hexagon-v67-programmer-s-reference-manual
      9     HVX extension: v66
     10     https://developer.qualcomm.com/downloads/qualcomm-hexagon-v66-hvx-programmer-s-reference-manual
     11 
     12 We presented an overview of the project at the 2019 KVM Forum.
     13     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
     14 
     15 *** Tour of the code ***
     16 
     17 The qemu-hexagon implementation is a combination of qemu and the Hexagon
     18 architecture library (aka archlib).  The three primary directories with
     19 Hexagon-specific code are
     20 
     21     qemu/target/hexagon
     22         This has all the instruction and packet semantics
     23     qemu/target/hexagon/imported
     24         These files are imported with very little modification from archlib
     25         *.idef                  Instruction semantics definition
     26         macros.def              Mapping of macros to instruction attributes
     27         encode*.def             Encoding patterns for each instruction
     28         iclass.def              Instruction class definitions used to determine
     29                                 legal VLIW slots for each instruction
     30     qemu/linux-user/hexagon
     31         Helpers for loading the ELF file and making Linux system calls,
     32         signals, etc
     33 
     34 We start with scripts that generate a bunch of include files.  This
     35 is a two step process.  The first step is to use the C preprocessor to expand
     36 macros inside the architecture definition files.  This is done in
     37 target/hexagon/gen_semantics.c.  This step produces
     38     <BUILD_DIR>/target/hexagon/semantics_generated.pyinc.
     39 That file is consumed by the following python scripts to produce the indicated
     40 header files in <BUILD_DIR>/target/hexagon
     41         gen_opcodes_def.py              -> opcodes_def_generated.h.inc
     42         gen_op_regs.py                  -> op_regs_generated.h.inc
     43         gen_printinsn.py                -> printinsn_generated.h.inc
     44         gen_op_attribs.py               -> op_attribs_generated.h.inc
     45         gen_helper_protos.py            -> helper_protos_generated.h.inc
     46         gen_shortcode.py                -> shortcode_generated.h.inc
     47         gen_tcg_funcs.py                -> tcg_funcs_generated.c.inc
     48         gen_tcg_func_table.py           -> tcg_func_table_generated.c.inc
     49         gen_helper_funcs.py             -> helper_funcs_generated.c.inc
     50 
     51 Qemu helper functions have 3 parts
     52     DEF_HELPER declaration indicates the signature of the helper
     53     gen_helper_<NAME> will generate a TCG call to the helper function
     54     The helper implementation
     55 
     56 Here's an example of the A2_add instruction.
     57     Instruction tag        A2_add
     58     Assembly syntax        "Rd32=add(Rs32,Rt32)"
     59     Instruction semantics  "{ RdV=RsV+RtV;}"
     60 
     61 By convention, the operands are identified by letter
     62     RdV is the destination register
     63     RsV, RtV are source registers
     64 
     65 The generator uses the operand naming conventions (see large comment in
     66 hex_common.py) to determine the signature of the helper function.  Here are the
     67 results for A2_add
     68 
     69 helper_protos_generated.h.inc
     70     DEF_HELPER_3(A2_add, s32, env, s32, s32)
     71 
     72 tcg_funcs_generated.c.inc
     73     static void generate_A2_add(
     74                     CPUHexagonState *env,
     75                     DisasContext *ctx,
     76                     Insn *insn,
     77                     Packet *pkt)
     78     {
     79         TCGv RdV = tcg_temp_local_new();
     80         const int RdN = insn->regno[0];
     81         TCGv RsV = hex_gpr[insn->regno[1]];
     82         TCGv RtV = hex_gpr[insn->regno[2]];
     83         gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
     84         gen_log_reg_write(RdN, RdV);
     85         ctx_log_reg_write(ctx, RdN);
     86         tcg_temp_free(RdV);
     87     }
     88 
     89 helper_funcs_generated.c.inc
     90     int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
     91     {
     92         uint32_t slot __attribute__((unused)) = 4;
     93         int32_t RdV = 0;
     94         { RdV=RsV+RtV;}
     95         return RdV;
     96     }
     97 
     98 Note that generate_A2_add updates the disassembly context to be processed
     99 when the packet commits (see "Packet Semantics" below).
    100 
    101 The generator checks for fGEN_TCG_<tag> macro.  This allows us to generate
    102 TCG code instead of a call to the helper.  If defined, the macro takes 1
    103 argument.
    104     C semantics (aka short code)
    105 
    106 This allows the code generator to override the auto-generated code.  In some
    107 cases this is necessary for correct execution.  We can also override for
    108 faster emulation.  For example, calling a helper for add is more expensive
    109 than generating a TCG add operation.
    110 
    111 The gen_tcg.h file has any overrides. For example, we could write
    112     #define fGEN_TCG_A2_add(GENHLPR, SHORTCODE) \
    113         tcg_gen_add_tl(RdV, RsV, RtV)
    114 
    115 The instruction semantics C code relies heavily on macros.  In cases where the
    116 C semantics are specified only with macros, we can override the default with
    117 the short semantics option and #define the macros to generate TCG code.  One
    118 example is L2_loadw_locked:
    119     Instruction tag        L2_loadw_locked
    120     Assembly syntax        "Rd32=memw_locked(Rs32)"
    121     Instruction semantics  "{ fEA_REG(RsV); fLOAD_LOCKED(1,4,u,EA,RdV) }"
    122 
    123 In gen_tcg.h, we use the shortcode
    124 #define fGEN_TCG_L2_loadw_locked(SHORTCODE) \
    125     SHORTCODE
    126 
    127 There are also cases where we brute force the TCG code generation.
    128 Instructions with multiple definitions are examples.  These require special
    129 handling because qemu helpers can only return a single value.
    130 
    131 For HVX vectors, the generator behaves slightly differently.  The wide vectors
    132 won't fit in a TCGv or TCGv_i64, so we pass TCGv_ptr variables to pass the
    133 address to helper functions.  Here's an example for an HVX vector-add-word
    134 istruction.
    135     static void generate_V6_vaddw(
    136                     CPUHexagonState *env,
    137                     DisasContext *ctx,
    138                     Insn *insn,
    139                     Packet *pkt)
    140     {
    141         const int VdN = insn->regno[0];
    142         const intptr_t VdV_off =
    143             ctx_future_vreg_off(ctx, VdN, 1, true);
    144         TCGv_ptr VdV = tcg_temp_local_new_ptr();
    145         tcg_gen_addi_ptr(VdV, cpu_env, VdV_off);
    146         const int VuN = insn->regno[1];
    147         const intptr_t VuV_off =
    148             vreg_src_off(ctx, VuN);
    149         TCGv_ptr VuV = tcg_temp_local_new_ptr();
    150         const int VvN = insn->regno[2];
    151         const intptr_t VvV_off =
    152             vreg_src_off(ctx, VvN);
    153         TCGv_ptr VvV = tcg_temp_local_new_ptr();
    154         tcg_gen_addi_ptr(VuV, cpu_env, VuV_off);
    155         tcg_gen_addi_ptr(VvV, cpu_env, VvV_off);
    156         TCGv slot = tcg_constant_tl(insn->slot);
    157         gen_helper_V6_vaddw(cpu_env, VdV, VuV, VvV, slot);
    158         tcg_temp_free(slot);
    159         gen_log_vreg_write(ctx, VdV_off, VdN, EXT_DFL, insn->slot, false);
    160         ctx_log_vreg_write(ctx, VdN, EXT_DFL, false);
    161         tcg_temp_free_ptr(VdV);
    162         tcg_temp_free_ptr(VuV);
    163         tcg_temp_free_ptr(VvV);
    164     }
    165 
    166 Notice that we also generate a variable named <operand>_off for each operand of
    167 the instruction.  This makes it easy to override the instruction semantics with
    168 functions from tcg-op-gvec.h.  Here's the override for this instruction.
    169     #define fGEN_TCG_V6_vaddw(SHORTCODE) \
    170         tcg_gen_gvec_add(MO_32, VdV_off, VuV_off, VvV_off, \
    171                          sizeof(MMVector), sizeof(MMVector))
    172 
    173 Finally, we notice that the override doesn't use the TCGv_ptr variables, so
    174 we don't generate them when an override is present.  Here is what we generate
    175 when the override is present.
    176     static void generate_V6_vaddw(
    177                     CPUHexagonState *env,
    178                     DisasContext *ctx,
    179                     Insn *insn,
    180                     Packet *pkt)
    181     {
    182         const int VdN = insn->regno[0];
    183         const intptr_t VdV_off =
    184             ctx_future_vreg_off(ctx, VdN, 1, true);
    185         const int VuN = insn->regno[1];
    186         const intptr_t VuV_off =
    187             vreg_src_off(ctx, VuN);
    188         const int VvN = insn->regno[2];
    189         const intptr_t VvV_off =
    190             vreg_src_off(ctx, VvN);
    191         fGEN_TCG_V6_vaddw({ fHIDE(int i;) fVFOREACH(32, i) { VdV.w[i] = VuV.w[i] + VvV.w[i] ; } });
    192         gen_log_vreg_write(ctx, VdV_off, VdN, EXT_DFL, insn->slot, false);
    193         ctx_log_vreg_write(ctx, VdN, EXT_DFL, false);
    194     }
    195 
    196 In addition to instruction semantics, we use a generator to create the decode
    197 tree.  This generation is also a two step process.  The first step is to run
    198 target/hexagon/gen_dectree_import.c to produce
    199     <BUILD_DIR>/target/hexagon/iset.py
    200 This file is imported by target/hexagon/dectree.py to produce
    201     <BUILD_DIR>/target/hexagon/dectree_generated.h.inc
    202 
    203 *** Key Files ***
    204 
    205 cpu.h
    206 
    207 This file contains the definition of the CPUHexagonState struct.  It is the
    208 runtime information for each thread and contains stuff like the GPR and
    209 predicate registers.
    210 
    211 macros.h
    212 mmvec/macros.h
    213 
    214 The Hexagon arch lib relies heavily on macros for the instruction semantics.
    215 This is a great advantage for qemu because we can override them for different
    216 purposes.  You will also notice there are sometimes two definitions of a macro.
    217 The QEMU_GENERATE variable determines whether we want the macro to generate TCG
    218 code.  If QEMU_GENERATE is not defined, we want the macro to generate vanilla
    219 C code that will work in the helper implementation.
    220 
    221 translate.c
    222 
    223 The functions in this file generate TCG code for a translation block.  Some
    224 important functions in this file are
    225 
    226     gen_start_packet - initialize the data structures for packet semantics
    227     gen_commit_packet - commit the register writes, stores, etc for a packet
    228     decode_and_translate_packet - disassemble a packet and generate code
    229 
    230 genptr.c
    231 gen_tcg.h
    232 
    233 These files create a function for each instruction.  It is mostly composed of
    234 fGEN_TCG_<tag> definitions followed by including tcg_funcs_generated.c.inc.
    235 
    236 op_helper.c
    237 
    238 This file contains the implementations of all the helpers.  There are a few
    239 general purpose helpers, but most of them are generated by including
    240 helper_funcs_generated.c.inc.  There are also several helpers used for debugging.
    241 
    242 
    243 *** Packet Semantics ***
    244 
    245 VLIW packet semantics differ from serial semantics in that all input operands
    246 are read, then the operations are performed, then all the results are written.
    247 For exmaple, this packet performs a swap of registers r0 and r1
    248     { r0 = r1; r1 = r0 }
    249 Note that the result is different if the instructions are executed serially.
    250 
    251 Packet semantics dictate that we defer any changes of state until the entire
    252 packet is committed.  We record the results of each instruction in a side data
    253 structure, and update the visible processor state when we commit the packet.
    254 
    255 The data structures are divided between the runtime state and the translation
    256 context.
    257 
    258 During the TCG generation (see translate.[ch]), we use the DisasContext to
    259 track what needs to be done during packet commit.  Here are the relevant
    260 fields
    261 
    262     reg_log            list of registers written
    263     reg_log_idx        index into ctx_reg_log
    264     pred_log           list of predicates written
    265     pred_log_idx       index into ctx_pred_log
    266     store_width        width of stores (indexed by slot)
    267 
    268 During runtime, the following fields in CPUHexagonState (see cpu.h) are used
    269 
    270     new_value             new value of a given register
    271     reg_written           boolean indicating if register was written
    272     new_pred_value        new value of a predicate register
    273     pred_written          boolean indicating if predicate was written
    274     mem_log_stores        record of the stores (indexed by slot)
    275 
    276 For Hexagon Vector eXtensions (HVX), the following fields are used
    277     VRegs                       Vector registers
    278     future_VRegs                Registers to be stored during packet commit
    279     tmp_VRegs                   Temporary registers *not* stored during commit
    280     VRegs_updated               Mask of predicated vector writes
    281     QRegs                       Q (vector predicate) registers
    282     future_QRegs                Registers to be stored during packet commit
    283     QRegs_updated               Mask of predicated vector writes
    284 
    285 *** Debugging ***
    286 
    287 You can turn on a lot of debugging by changing the HEX_DEBUG macro to 1 in
    288 internal.h.  This will stream a lot of information as it generates TCG and
    289 executes the code.
    290 
    291 To track down nasty issues with Hexagon->TCG generation, we compare the
    292 execution results with actual hardware running on a Hexagon Linux target.
    293 Run qemu with the "-d cpu" option.  Then, we can diff the results and figure
    294 out where qemu and hardware behave differently.
    295 
    296 The stacks are located at different locations.  We handle this by changing
    297 env->stack_adjust in translate.c.  First, set this to zero and run qemu.
    298 Then, change env->stack_adjust to the difference between the two stack
    299 locations.  Then rebuild qemu and run again. That will produce a very
    300 clean diff.
    301 
    302 Here are some handy places to set breakpoints
    303 
    304     At the call to gen_start_packet for a given PC (note that the line number
    305         might change in the future)
    306         br translate.c:602 if ctx->base.pc_next == 0xdeadbeef
    307     The helper function for each instruction is named helper_<TAG>, so here's
    308         an example that will set a breakpoint at the start
    309         br helper_A2_add
    310     If you have the HEX_DEBUG macro set, the following will be useful
    311         At the start of execution of a packet for a given PC
    312             br helper_debug_start_packet if env->gpr[41] == 0xdeadbeef
    313         At the end of execution of a packet for a given PC
    314             br helper_debug_commit_end if env->this_PC == 0xdeadbeef