github.com/cloudwego/iasm@v0.2.0/repl/regs_amd64.go (about)

     1  //
     2  // Copyright 2024 CloudWeGo Authors
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package repl
    18  
    19  import (
    20      `fmt`
    21  
    22      `github.com/klauspost/cpuid/v2`
    23  )
    24  
    25  type _RegFileAMD64 struct {
    26      rax    uint64
    27      rbx    uint64
    28      rcx    uint64
    29      rdx    uint64
    30      rdi    uint64
    31      rsi    uint64
    32      rbp    uint64
    33      rsp    uint64
    34      r8     uint64
    35      r9     uint64
    36      r10    uint64
    37      r11    uint64
    38      r12    uint64
    39      r13    uint64
    40      r14    uint64
    41      r15    uint64
    42      rip    uint64
    43      rflags uint64
    44      cs     uint16
    45      _      [6]byte
    46      fs     uint16
    47      _      [6]byte
    48      gs     uint16
    49      _      [30]byte
    50      xmm    [32][16]byte
    51      ymm    [32][32]byte
    52      zmm    [32][64]byte
    53      k      [8]uint64
    54  }
    55  
    56  var (
    57      hasAVX      = cpuid.CPU.Has(cpuid.AVX)
    58      hasAVX512F  = cpuid.CPU.Has(cpuid.AVX512F)
    59      hasAVX512BW = cpuid.CPU.Has(cpuid.AVX512BW)
    60      hasAVX512VL = cpuid.CPU.Has(cpuid.AVX512VL)
    61  )
    62  
    63  //go:nosplit
    64  //go:noescape
    65  //goland:noinspection GoUnusedParameter
    66  func dumpregs(regs *_RegFileAMD64)
    67  
    68  func (self *_RegFileAMD64) Dump(indent int) []_Reg {
    69      dumpregs(self)
    70      return self.format(indent)
    71  }
    72  
    73  func (self *_RegFileAMD64) Compare(other _RegFile, indent int) (v []_Reg) {
    74      var ok bool
    75      var rf *_RegFileAMD64
    76  
    77      /* must be an AMD64 register file */
    78      if rf, ok = other.(*_RegFileAMD64); !ok {
    79          panic("can only compare with AMD64 register file")
    80      }
    81  
    82      /* compare generic registers, %rip is always going
    83       * to change, so ignore this in the comparison result */
    84      if self.rax    != rf.rax    { v = append(v, _Reg{"rax"   , fmt.Sprintf("%#016x -> %#016x", self.rax   , rf.rax   ), false}) }
    85      if self.rbx    != rf.rbx    { v = append(v, _Reg{"rbx"   , fmt.Sprintf("%#016x -> %#016x", self.rbx   , rf.rbx   ), false}) }
    86      if self.rcx    != rf.rcx    { v = append(v, _Reg{"rcx"   , fmt.Sprintf("%#016x -> %#016x", self.rcx   , rf.rcx   ), false}) }
    87      if self.rdx    != rf.rdx    { v = append(v, _Reg{"rdx"   , fmt.Sprintf("%#016x -> %#016x", self.rdx   , rf.rdx   ), false}) }
    88      if self.rdi    != rf.rdi    { v = append(v, _Reg{"rdi"   , fmt.Sprintf("%#016x -> %#016x", self.rdi   , rf.rdi   ), false}) }
    89      if self.rsi    != rf.rsi    { v = append(v, _Reg{"rsi"   , fmt.Sprintf("%#016x -> %#016x", self.rsi   , rf.rsi   ), false}) }
    90      if self.rbp    != rf.rbp    { v = append(v, _Reg{"rbp"   , fmt.Sprintf("%#016x -> %#016x", self.rbp   , rf.rbp   ), false}) }
    91      if self.rsp    != rf.rsp    { v = append(v, _Reg{"rsp"   , fmt.Sprintf("%#016x -> %#016x", self.rsp   , rf.rsp   ), false}) }
    92      if self.r8     != rf.r8     { v = append(v, _Reg{"r8"    , fmt.Sprintf("%#016x -> %#016x", self.r8    , rf.r8    ), false}) }
    93      if self.r9     != rf.r9     { v = append(v, _Reg{"r9"    , fmt.Sprintf("%#016x -> %#016x", self.r9    , rf.r9    ), false}) }
    94      if self.r10    != rf.r10    { v = append(v, _Reg{"r10"   , fmt.Sprintf("%#016x -> %#016x", self.r10   , rf.r10   ), false}) }
    95      if self.r11    != rf.r11    { v = append(v, _Reg{"r11"   , fmt.Sprintf("%#016x -> %#016x", self.r11   , rf.r11   ), false}) }
    96      if self.r12    != rf.r12    { v = append(v, _Reg{"r12"   , fmt.Sprintf("%#016x -> %#016x", self.r12   , rf.r12   ), false}) }
    97      if self.r13    != rf.r13    { v = append(v, _Reg{"r13"   , fmt.Sprintf("%#016x -> %#016x", self.r13   , rf.r13   ), false}) }
    98      if self.r14    != rf.r14    { v = append(v, _Reg{"r14"   , fmt.Sprintf("%#016x -> %#016x", self.r14   , rf.r14   ), false}) }
    99      if self.r15    != rf.r15    { v = append(v, _Reg{"r15"   , fmt.Sprintf("%#016x -> %#016x", self.r15   , rf.r15   ), false}) }
   100      if self.rflags != rf.rflags { v = append(v, _Reg{"rflags", fmt.Sprintf("%#016x -> %#016x", self.rflags, rf.rflags), false}) }
   101      if self.cs     != rf.cs     { v = append(v, _Reg{"cs"    , fmt.Sprintf("%#04x -> %#04x"  , self.cs    , rf.cs    ), false}) }
   102      if self.fs     != rf.fs     { v = append(v, _Reg{"fs"    , fmt.Sprintf("%#04x -> %#04x"  , self.fs    , rf.fs    ), false}) }
   103      if self.gs     != rf.gs     { v = append(v, _Reg{"gs"    , fmt.Sprintf("%#04x -> %#04x"  , self.gs    , rf.gs    ), false}) }
   104  
   105      /* compare vector registers */
   106      self.compareXmmStd(&v, rf, indent)
   107      self.compareXmmExt(&v, rf, indent)
   108      self.compareYmmStd(&v, rf, indent)
   109      self.compareYmmExt(&v, rf, indent)
   110      self.compareZmmAll(&v, rf, indent)
   111      self.compareMaskQW(&v, rf)
   112      return v
   113  }
   114  
   115  func (self *_RegFileAMD64) format(indent int) (v []_Reg) {
   116      v = []_Reg {
   117          { "rax"   , fmt.Sprintf("%#016x %s", self.rax, symbol(self.rax)), false },
   118          { "rbx"   , fmt.Sprintf("%#016x %s", self.rbx, symbol(self.rbx)), false },
   119          { "rcx"   , fmt.Sprintf("%#016x %s", self.rcx, symbol(self.rcx)), false },
   120          { "rdx"   , fmt.Sprintf("%#016x %s", self.rdx, symbol(self.rdx)), false },
   121          { "rdi"   , fmt.Sprintf("%#016x %s", self.rdi, symbol(self.rdi)), false },
   122          { "rsi"   , fmt.Sprintf("%#016x %s", self.rsi, symbol(self.rsi)), false },
   123          { "rbp"   , fmt.Sprintf("%#016x %s", self.rbp, symbol(self.rbp)), false },
   124          { "rsp"   , fmt.Sprintf("%#016x %s", self.rsp, symbol(self.rsp)), false },
   125          { "r8"    , fmt.Sprintf("%#016x %s", self.r8 , symbol(self.r8 )), false },
   126          { "r9"    , fmt.Sprintf("%#016x %s", self.r9 , symbol(self.r9 )), false },
   127          { "r10"   , fmt.Sprintf("%#016x %s", self.r10, symbol(self.r10)), false },
   128          { "r11"   , fmt.Sprintf("%#016x %s", self.r11, symbol(self.r11)), false },
   129          { "r12"   , fmt.Sprintf("%#016x %s", self.r12, symbol(self.r12)), false },
   130          { "r13"   , fmt.Sprintf("%#016x %s", self.r13, symbol(self.r13)), false },
   131          { "r14"   , fmt.Sprintf("%#016x %s", self.r14, symbol(self.r14)), false },
   132          { "r15"   , fmt.Sprintf("%#016x %s", self.r15, symbol(self.r15)), false },
   133          { "rip"   , fmt.Sprintf("%#016x %s", self.rip, symbol(self.rip)), false },
   134          { "rflags", fmt.Sprintf("%#016x"   , self.rflags)               , false },
   135          { "cs"    , fmt.Sprintf("%#04x"    , self.cs)                   , false },
   136          { "fs"    , fmt.Sprintf("%#04x"    , self.fs)                   , false },
   137          { "gs"    , fmt.Sprintf("%#04x"    , self.gs)                   , false },
   138      }
   139  
   140      /* add the vector registers */
   141      self.formatXmmStd(&v, indent)
   142      self.formatXmmExt(&v, indent)
   143      self.formatYmmStd(&v, indent)
   144      self.formatYmmExt(&v, indent)
   145      self.formatZmmAll(&v, indent)
   146      self.formatMaskQW(&v)
   147      return
   148  }
   149  
   150  func (self *_RegFileAMD64) formatXmmStd(v *[]_Reg, indent int) {
   151      for i := 0; i < 16; i++ {
   152          *v = append(*v, _Reg {
   153              reg: fmt.Sprintf("xmm%d", i),
   154              val: vector(self.xmm[i][:], indent),
   155              vec: true,
   156          })
   157      }
   158  }
   159  
   160  func (self *_RegFileAMD64) formatXmmExt(v *[]_Reg, indent int) {
   161      if hasAVX512VL {
   162          for i := 16; i < 32; i++ {
   163              *v = append(*v, _Reg {
   164                  reg: fmt.Sprintf("xmm%d", i),
   165                  val: vector(self.xmm[i][:], indent),
   166                  vec: true,
   167              })
   168          }
   169      }
   170  }
   171  
   172  func (self *_RegFileAMD64) formatYmmStd(v *[]_Reg, indent int) {
   173      if hasAVX {
   174          for i := 0; i < 16; i++ {
   175              *v = append(*v, _Reg {
   176                  reg: fmt.Sprintf("ymm%d", i),
   177                  val: vector(self.ymm[i][:], indent),
   178                  vec: true,
   179              })
   180          }
   181      }
   182  }
   183  
   184  func (self *_RegFileAMD64) formatYmmExt(v *[]_Reg, indent int) {
   185      if hasAVX512VL {
   186          for i := 16; i < 32; i++ {
   187              *v = append(*v, _Reg {
   188                  reg: fmt.Sprintf("ymm%d", i),
   189                  val: vector(self.ymm[i][:], indent),
   190                  vec: true,
   191              })
   192          }
   193      }
   194  }
   195  
   196  func (self *_RegFileAMD64) formatZmmAll(v *[]_Reg, indent int) {
   197      if hasAVX512F {
   198          for i := 0; i < 32; i++ {
   199              *v = append(*v, _Reg {
   200                  reg: fmt.Sprintf("zmm%d", i),
   201                  val: vector(self.zmm[i][:], indent),
   202                  vec: true,
   203              })
   204          }
   205      }
   206  }
   207  
   208  func (self *_RegFileAMD64) formatMaskQW(v *[]_Reg) {
   209      if hasAVX512BW {
   210          for i := 0; i < 8; i++ {
   211              *v = append(*v, _Reg {
   212                  reg: fmt.Sprintf("k%d", i),
   213                  val: fmt.Sprintf("%#016x", self.k[i]),
   214                  vec: true,
   215              })
   216          }
   217      } else if hasAVX512F {
   218          for i := 0; i < 8; i++ {
   219              *v = append(*v, _Reg {
   220                  reg: fmt.Sprintf("k%d", i),
   221                  val: fmt.Sprintf("%#04x", self.k[i]),
   222                  vec: true,
   223              })
   224          }
   225      }
   226  }
   227  
   228  func (self *_RegFileAMD64) compareXmmStd(v *[]_Reg, rf *_RegFileAMD64, indent int) {
   229      for i := 0; i < 16; i++ {
   230          if self.xmm[i] != rf.xmm[i] {
   231              *v = append(*v, _Reg {
   232                  reg: fmt.Sprintf("xmm%d", i),
   233                  val: vecdiff(self.xmm[i][:], rf.xmm[i][:], indent),
   234                  vec: true,
   235              })
   236          }
   237      }
   238  }
   239  
   240  func (self *_RegFileAMD64) compareXmmExt(v *[]_Reg, rf *_RegFileAMD64, indent int) {
   241      if hasAVX512VL {
   242          for i := 16; i < 32; i++ {
   243              if self.xmm[i] != rf.xmm[i] {
   244                  *v = append(*v, _Reg {
   245                      reg: fmt.Sprintf("xmm%d", i),
   246                      val: vecdiff(self.xmm[i][:], rf.xmm[i][:], indent),
   247                      vec: true,
   248                  })
   249              }
   250          }
   251      }
   252  }
   253  
   254  func (self *_RegFileAMD64) compareYmmStd(v *[]_Reg, rf *_RegFileAMD64, indent int) {
   255      if hasAVX {
   256          for i := 0; i < 16; i++ {
   257              if self.ymm[i] != rf.ymm[i] {
   258                  *v = append(*v, _Reg {
   259                      reg: fmt.Sprintf("ymm%d", i),
   260                      val: vecdiff(self.ymm[i][:], rf.ymm[i][:], indent),
   261                      vec: true,
   262                  })
   263              }
   264          }
   265      }
   266  }
   267  
   268  func (self *_RegFileAMD64) compareYmmExt(v *[]_Reg, rf *_RegFileAMD64, indent int) {
   269      if hasAVX512VL {
   270          for i := 16; i < 32; i++ {
   271              if self.ymm[i] != rf.ymm[i] {
   272                  *v = append(*v, _Reg {
   273                      reg: fmt.Sprintf("ymm%d", i),
   274                      val: vecdiff(self.ymm[i][:], rf.ymm[i][:], indent),
   275                      vec: true,
   276                  })
   277              }
   278          }
   279      }
   280  }
   281  
   282  func (self *_RegFileAMD64) compareZmmAll(v *[]_Reg, rf *_RegFileAMD64, indent int) {
   283      if hasAVX512F {
   284          for i := 0; i < 32; i++ {
   285              if self.zmm[i] != rf.zmm[i] {
   286                  *v = append(*v, _Reg {
   287                      reg: fmt.Sprintf("zmm%d", i),
   288                      val: vecdiff(self.zmm[i][:], rf.zmm[i][:], indent),
   289                      vec: true,
   290                  })
   291              }
   292          }
   293      }
   294  }
   295  
   296  func (self *_RegFileAMD64) compareMaskQW(v *[]_Reg, rf *_RegFileAMD64) {
   297      if hasAVX512BW {
   298          for i := 0; i < 8; i++ {
   299              if self.k[i] != rf.k[i] {
   300                  *v = append(*v, _Reg {
   301                      reg: fmt.Sprintf("k%d", i),
   302                      val: fmt.Sprintf("%#016x -> %#016x", self.k[i], rf.k[i]),
   303                      vec: true,
   304                  })
   305              }
   306          }
   307      } else if hasAVX512F {
   308          for i := 0; i < 8; i++ {
   309              if self.k[i] != rf.k[i] {
   310                  *v = append(*v, _Reg {
   311                      reg: fmt.Sprintf("k%d", i),
   312                      val: fmt.Sprintf("%#04x -> %#04x", self.k[i], rf.k[i]),
   313                      vec: true,
   314                  })
   315              }
   316          }
   317      }
   318  }
   319  
   320  func init() {
   321      _regs = new(_RegFileAMD64)
   322  }