gem5 version: 21.2.1.1, commit: e4fae58da6c044b6efec62392ff99f343ce67947

how gem5 decode a x86 inst

test: ~/Gist/hello/hello.s

#hello.s
.section .data
>---output:>.ascii  "Hello World\n"
.section .text
.globl _start
_start:
/* output  like printf */
    movl $4, %eax
    movl $1, %ebx
    movl $output, %ecx
    movl $12, %edx
    int $0x80
/* exit */
    movl $1, %eax
    movl $0, %ebx
    int $0x80
2022.06.24

How x86_macroop::MOV_R_I::MOV_R_I's microops[0] =... is generated?

Try1

Inheritage

  • src/arch/x86/isa/macroop.isa:

    X86Macroop

    • src/arch/micro_asm.py:

      Combinational_Macroop

      • Micro_Container

        • Object

Try2

src/arch/x86/isa/macroop.isa:

def template MacroConstructor {{
  x86_macroop::%(class_name)s::%(class_name)s(...)
  {
    ...
    /// This one generates microops[0] =...
    %(alloc_microops)s
  }
}};

src/arch/x86/isa/macroop.isa:

class X86Macroop(Combinational_Macroop):
  def getDefinition(self, env):
    ...
    for op in self.microops:
      ...
      allocMicroops += \
        "microops[%d] = %s;\n" % \
        (micropc, op.getAllocator(flags))
2022.06.23

src/arch/x86/isa/microops/limmop.isa:

class LimmOp(X86Microop):
  ...
  def getAllocator(self, microFlags):
    allocString = '''
      (%(dataSize)s >= 4) ?
        ...
    ...
    '''
microopClasses["limm"] = LimmOp

src/arch/x86/isa/microasm.isa:

assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop)

Overview

  • src/arch/x86/isa/decoder/one_byte_opcodes.isa:

    A huge C-like switch case

    opcode(binary) => MOV(Bv, Iv)

    maybe it generates build/X86/arch/x86/generated/decode-method.cc.inc

  • src/arch/x86/isa/insts/general_purpose/data_transfer/move.py:

    /// [TODO] what language is this?
    def macroop MOV_R_I {
      limm reg, imm
    };
    
  • src/arch/x86/isa/macroop.isa:

    def template MacroConstructor {{...}}: [TODO]what => build/X86/arch/x86/generated/decoder-ns.cc.inc:

    x86_macroop::MOV_R_I::MOV_R_I(...) {
    ...
    microops[0] = (env.dataSize >= 4) ? ...LimmBig... : ...Limm...;
    }
    
  • src/arch/x86/isa/microops/limmop.isa:

    limmop.isa generates the declaration and execution of class LimmBig

    MicroLimmOpDeclare.subst(InstObjParams(...)) => build/X86/arch/x86/generated/decoder-ns.hh.inc:

    class LimmBig : ... {...};
    

    MicroLimmOpExecute.subst(InstObjParams(...)) => build/X86/arch/x86/generated/exec-ns.cc.inc:

    Fault LimmBig::execute(...) {...}
    

[TODO]decoder isa

one_byte_opcodes.isa

How MOV(Bb, Ib) work? What does Bb, Ib mean?

2022.06.22

DPRINT mov imm, reg

  • build/X86/arch/x86/generated/decoder-ns.hh.inc:

    class Limm : public X86ISA::RegOpT<X86ISA::FoldedDestOp, X86ISA::Imm64Op> {
      Limm(ExtMachInst mach_inst, ...):
      ...
      X86ISA::RegOpT<X86ISA::FoldedDestOp, X86ISA::Imm64Op>(mach_inst, "limm", ...) {}
    }
    
    • src/arch/x86/insts/microregop.hh:

      /// Operands are X86ISA::FoldedDestOp, X86ISA::Imm64Op
      template <typename ...Operands>
      using RegOpT = InstOperands<RegOpBase, Operands...>;
      
      • src/arch/x86/insts/microop_args.hh:

        /// Base is RegOpBase
        /// Operands are X86ISA::FoldedDestOp, X86ISA::Imm64Op
        template <typename Base, typename ...Operands>
        class InstOperands : public Base, public Operands...
        

example: MOV指令,借助gdb打断点

gdb build/X86/gem5.debug
(gdb) r --debug-flags ExecAll configs/example/se.py -c ~/Gist/hello/hello
  • build/X86/sim/simulate.cc:

    simulate

    • doSimLoop(EventQueue *eventq)
      • src/sim/eventq.cc:

        eventq->serviceOne()

        • override Event::process() function in src/sim/eventq.hh:

          EventFunctionWrapper::process() { callback(); }

          • src/cpu/simple/atomic.cc:

            AtomicSimpleCPU::tick()

            • preExecute()
              • decoder->moreBytes(pc_state, fetch_pc)

                • src/arch/x86/decoder.hh:

                  void
                  moreBytes(const PCStateBase &pc, Addr fetchPC) override
                  
                  • src/arch/x86/decoder.cc:

                    This is a decode state machine.

                    void Decoder::process() {
                      switch (state) {
                        case PrefixState:
                        ...
                      }
                    }
                    
              • decoder->decode(pc_state) /// InstDecoder::decode()

                • function override src/arch/x86/decoder.cc:
                X86ISA::Decoder : public InstDecoder {...};
                X86ISA::Decoder::decode(PCStateBase &next_pc)
                
                • X86ISA::Decoder::decode(ExtMachInst mach_inst, Addr addr)
                  • build/X86/arch/x86/generated/decode-method.cc.inc:

                    /// a HUGE switch case
                    X86ISA::Decoder::decodeInst(X86ISA::ExtMachInst)
                    
                    • build/X86/arch/x86/generated/decoder-ns.cc.inc:

                      x86_macroop::MOV_R_I::MOV_R_I(ExtMachInst machInst, EmulEnv _env)
                        : Macroop("mov", machInst, 1, _env) {...}
                      
                      • build/X86/arch/x86/generated/decoder-ns.hh.inc:

                        LimmBig::LimmBig(ExtMachInst mach_inst, const char *inst_mnem,
                                         uint64_t set_flags, Dest _dest,
                                         uint64_t _imm, uint8_t data_size)
                          : X86ISA::RegOpT<...>(...) {...}
                        

解码部分每个架构不同,使用.isa语言生成。 .isa语言生成的内容位于generated/文件夹。

2022.06.09

isa

lyw:负责处理isa文件

gem5/src/arch/isa_parser/isa_parser.py

2022.06.06

gem5 microops何时出现的?

gem5/src/arch/x86/isa/microops/base.isa最早始于2007年4月5日。

gem5如何计算X86 flags?是扩展了位宽吗?

以Add为例

  • gem5/src/arch/x86/isa/microops/regop.isa: class Add(FlagRegOp)
    • class FlagRegOp(BasicRegOp)
      • gem5/src/arch/x86/insts/microregop.cc: genFlags
2022.06.16

https://www.gem5.org/documentation/learning_gem5/part2/parameters/

C++ objects are not created until m5.instantiate() is called

Memory Object

https://www.gem5.org/documentation/learning_gem5/part2/memoryobject/

callchain? retry can be a single call stack?