// // Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package repl import ( `fmt` `github.com/klauspost/cpuid/v2` ) type _RegFileAMD64 struct { rax uint64 rbx uint64 rcx uint64 rdx uint64 rdi uint64 rsi uint64 rbp uint64 rsp uint64 r8 uint64 r9 uint64 r10 uint64 r11 uint64 r12 uint64 r13 uint64 r14 uint64 r15 uint64 rip uint64 rflags uint64 cs uint16 _ [6]byte fs uint16 _ [6]byte gs uint16 _ [30]byte xmm [32][16]byte ymm [32][32]byte zmm [32][64]byte k [8]uint64 } var ( hasAVX = cpuid.CPU.Has(cpuid.AVX) hasAVX512F = cpuid.CPU.Has(cpuid.AVX512F) hasAVX512BW = cpuid.CPU.Has(cpuid.AVX512BW) hasAVX512VL = cpuid.CPU.Has(cpuid.AVX512VL) ) //go:nosplit //go:noescape //goland:noinspection GoUnusedParameter func dumpregs(regs *_RegFileAMD64) func (self *_RegFileAMD64) Dump(indent int) []_Reg { dumpregs(self) return self.format(indent) } func (self *_RegFileAMD64) Compare(other _RegFile, indent int) (v []_Reg) { var ok bool var rf *_RegFileAMD64 /* must be an AMD64 register file */ if rf, ok = other.(*_RegFileAMD64); !ok { panic("can only compare with AMD64 register file") } /* compare generic registers, %rip is always going * to change, so ignore this in the comparison result */ if self.rax != rf.rax { v = append(v, _Reg{"rax" , fmt.Sprintf("%#016x -> %#016x", self.rax , rf.rax ), false}) } if self.rbx != rf.rbx { v = append(v, _Reg{"rbx" , fmt.Sprintf("%#016x -> %#016x", self.rbx , rf.rbx ), false}) } if self.rcx != rf.rcx { v = append(v, _Reg{"rcx" , fmt.Sprintf("%#016x -> %#016x", self.rcx , rf.rcx ), false}) } if self.rdx != rf.rdx { v = append(v, _Reg{"rdx" , fmt.Sprintf("%#016x -> %#016x", self.rdx , rf.rdx ), false}) } if self.rdi != rf.rdi { v = append(v, _Reg{"rdi" , fmt.Sprintf("%#016x -> %#016x", self.rdi , rf.rdi ), false}) } if self.rsi != rf.rsi { v = append(v, _Reg{"rsi" , fmt.Sprintf("%#016x -> %#016x", self.rsi , rf.rsi ), false}) } if self.rbp != rf.rbp { v = append(v, _Reg{"rbp" , fmt.Sprintf("%#016x -> %#016x", self.rbp , rf.rbp ), false}) } if self.rsp != rf.rsp { v = append(v, _Reg{"rsp" , fmt.Sprintf("%#016x -> %#016x", self.rsp , rf.rsp ), false}) } if self.r8 != rf.r8 { v = append(v, _Reg{"r8" , fmt.Sprintf("%#016x -> %#016x", self.r8 , rf.r8 ), false}) } if self.r9 != rf.r9 { v = append(v, _Reg{"r9" , fmt.Sprintf("%#016x -> %#016x", self.r9 , rf.r9 ), false}) } if self.r10 != rf.r10 { v = append(v, _Reg{"r10" , fmt.Sprintf("%#016x -> %#016x", self.r10 , rf.r10 ), false}) } if self.r11 != rf.r11 { v = append(v, _Reg{"r11" , fmt.Sprintf("%#016x -> %#016x", self.r11 , rf.r11 ), false}) } if self.r12 != rf.r12 { v = append(v, _Reg{"r12" , fmt.Sprintf("%#016x -> %#016x", self.r12 , rf.r12 ), false}) } if self.r13 != rf.r13 { v = append(v, _Reg{"r13" , fmt.Sprintf("%#016x -> %#016x", self.r13 , rf.r13 ), false}) } if self.r14 != rf.r14 { v = append(v, _Reg{"r14" , fmt.Sprintf("%#016x -> %#016x", self.r14 , rf.r14 ), false}) } if self.r15 != rf.r15 { v = append(v, _Reg{"r15" , fmt.Sprintf("%#016x -> %#016x", self.r15 , rf.r15 ), false}) } if self.rflags != rf.rflags { v = append(v, _Reg{"rflags", fmt.Sprintf("%#016x -> %#016x", self.rflags, rf.rflags), false}) } if self.cs != rf.cs { v = append(v, _Reg{"cs" , fmt.Sprintf("%#04x -> %#04x" , self.cs , rf.cs ), false}) } if self.fs != rf.fs { v = append(v, _Reg{"fs" , fmt.Sprintf("%#04x -> %#04x" , self.fs , rf.fs ), false}) } if self.gs != rf.gs { v = append(v, _Reg{"gs" , fmt.Sprintf("%#04x -> %#04x" , self.gs , rf.gs ), false}) } /* compare vector registers */ self.compareXmmStd(&v, rf, indent) self.compareXmmExt(&v, rf, indent) self.compareYmmStd(&v, rf, indent) self.compareYmmExt(&v, rf, indent) self.compareZmmAll(&v, rf, indent) self.compareMaskQW(&v, rf) return v } func (self *_RegFileAMD64) format(indent int) (v []_Reg) { v = []_Reg { { "rax" , fmt.Sprintf("%#016x %s", self.rax, symbol(self.rax)), false }, { "rbx" , fmt.Sprintf("%#016x %s", self.rbx, symbol(self.rbx)), false }, { "rcx" , fmt.Sprintf("%#016x %s", self.rcx, symbol(self.rcx)), false }, { "rdx" , fmt.Sprintf("%#016x %s", self.rdx, symbol(self.rdx)), false }, { "rdi" , fmt.Sprintf("%#016x %s", self.rdi, symbol(self.rdi)), false }, { "rsi" , fmt.Sprintf("%#016x %s", self.rsi, symbol(self.rsi)), false }, { "rbp" , fmt.Sprintf("%#016x %s", self.rbp, symbol(self.rbp)), false }, { "rsp" , fmt.Sprintf("%#016x %s", self.rsp, symbol(self.rsp)), false }, { "r8" , fmt.Sprintf("%#016x %s", self.r8 , symbol(self.r8 )), false }, { "r9" , fmt.Sprintf("%#016x %s", self.r9 , symbol(self.r9 )), false }, { "r10" , fmt.Sprintf("%#016x %s", self.r10, symbol(self.r10)), false }, { "r11" , fmt.Sprintf("%#016x %s", self.r11, symbol(self.r11)), false }, { "r12" , fmt.Sprintf("%#016x %s", self.r12, symbol(self.r12)), false }, { "r13" , fmt.Sprintf("%#016x %s", self.r13, symbol(self.r13)), false }, { "r14" , fmt.Sprintf("%#016x %s", self.r14, symbol(self.r14)), false }, { "r15" , fmt.Sprintf("%#016x %s", self.r15, symbol(self.r15)), false }, { "rip" , fmt.Sprintf("%#016x %s", self.rip, symbol(self.rip)), false }, { "rflags", fmt.Sprintf("%#016x" , self.rflags) , false }, { "cs" , fmt.Sprintf("%#04x" , self.cs) , false }, { "fs" , fmt.Sprintf("%#04x" , self.fs) , false }, { "gs" , fmt.Sprintf("%#04x" , self.gs) , false }, } /* add the vector registers */ self.formatXmmStd(&v, indent) self.formatXmmExt(&v, indent) self.formatYmmStd(&v, indent) self.formatYmmExt(&v, indent) self.formatZmmAll(&v, indent) self.formatMaskQW(&v) return } func (self *_RegFileAMD64) formatXmmStd(v *[]_Reg, indent int) { for i := 0; i < 16; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("xmm%d", i), val: vector(self.xmm[i][:], indent), vec: true, }) } } func (self *_RegFileAMD64) formatXmmExt(v *[]_Reg, indent int) { if hasAVX512VL { for i := 16; i < 32; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("xmm%d", i), val: vector(self.xmm[i][:], indent), vec: true, }) } } } func (self *_RegFileAMD64) formatYmmStd(v *[]_Reg, indent int) { if hasAVX { for i := 0; i < 16; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("ymm%d", i), val: vector(self.ymm[i][:], indent), vec: true, }) } } } func (self *_RegFileAMD64) formatYmmExt(v *[]_Reg, indent int) { if hasAVX512VL { for i := 16; i < 32; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("ymm%d", i), val: vector(self.ymm[i][:], indent), vec: true, }) } } } func (self *_RegFileAMD64) formatZmmAll(v *[]_Reg, indent int) { if hasAVX512F { for i := 0; i < 32; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("zmm%d", i), val: vector(self.zmm[i][:], indent), vec: true, }) } } } func (self *_RegFileAMD64) formatMaskQW(v *[]_Reg) { if hasAVX512BW { for i := 0; i < 8; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("k%d", i), val: fmt.Sprintf("%#016x", self.k[i]), vec: true, }) } } else if hasAVX512F { for i := 0; i < 8; i++ { *v = append(*v, _Reg { reg: fmt.Sprintf("k%d", i), val: fmt.Sprintf("%#04x", self.k[i]), vec: true, }) } } } func (self *_RegFileAMD64) compareXmmStd(v *[]_Reg, rf *_RegFileAMD64, indent int) { for i := 0; i < 16; i++ { if self.xmm[i] != rf.xmm[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("xmm%d", i), val: vecdiff(self.xmm[i][:], rf.xmm[i][:], indent), vec: true, }) } } } func (self *_RegFileAMD64) compareXmmExt(v *[]_Reg, rf *_RegFileAMD64, indent int) { if hasAVX512VL { for i := 16; i < 32; i++ { if self.xmm[i] != rf.xmm[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("xmm%d", i), val: vecdiff(self.xmm[i][:], rf.xmm[i][:], indent), vec: true, }) } } } } func (self *_RegFileAMD64) compareYmmStd(v *[]_Reg, rf *_RegFileAMD64, indent int) { if hasAVX { for i := 0; i < 16; i++ { if self.ymm[i] != rf.ymm[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("ymm%d", i), val: vecdiff(self.ymm[i][:], rf.ymm[i][:], indent), vec: true, }) } } } } func (self *_RegFileAMD64) compareYmmExt(v *[]_Reg, rf *_RegFileAMD64, indent int) { if hasAVX512VL { for i := 16; i < 32; i++ { if self.ymm[i] != rf.ymm[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("ymm%d", i), val: vecdiff(self.ymm[i][:], rf.ymm[i][:], indent), vec: true, }) } } } } func (self *_RegFileAMD64) compareZmmAll(v *[]_Reg, rf *_RegFileAMD64, indent int) { if hasAVX512F { for i := 0; i < 32; i++ { if self.zmm[i] != rf.zmm[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("zmm%d", i), val: vecdiff(self.zmm[i][:], rf.zmm[i][:], indent), vec: true, }) } } } } func (self *_RegFileAMD64) compareMaskQW(v *[]_Reg, rf *_RegFileAMD64) { if hasAVX512BW { for i := 0; i < 8; i++ { if self.k[i] != rf.k[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("k%d", i), val: fmt.Sprintf("%#016x -> %#016x", self.k[i], rf.k[i]), vec: true, }) } } } else if hasAVX512F { for i := 0; i < 8; i++ { if self.k[i] != rf.k[i] { *v = append(*v, _Reg { reg: fmt.Sprintf("k%d", i), val: fmt.Sprintf("%#04x -> %#04x", self.k[i], rf.k[i]), vec: true, }) } } } } func init() { _regs = new(_RegFileAMD64) }