func TestRegAllocSet(t *testing.T) { for _, avail := range []uint64{0xffffffffffffffff, 1 << (5 << 1)} { t.Logf("avail: 0x%016x", avail) var ra regAllocator ra.init(avail) ra.setAllocated(gen.RegCategoryInt, regs.R(5)) if !ra.allocated(gen.RegCategoryInt, regs.R(5)) { t.Fatal("1") } ra.setAllocated(gen.RegCategoryInt, regs.R(5)) if !ra.allocated(gen.RegCategoryInt, regs.R(5)) { t.Fatal("2") } func() { defer func() { if recover() == nil { t.Fatal("3") } }() ra.allocSpecific(gen.RegCategoryInt, regs.R(5)) }() } }
func (i xchgInsn) opFromReg(code gen.OpCoder, t types.T, a, b regs.R) { switch { case a == regs.R(0): i.r0.op(code, t, b) case b == regs.R(0): i.r0.op(code, t, a) default: i.insnPrefix.opFromReg(code, t, a, b) } }
func RegCategoryMask(cat RegCategory, callRegs *[]regs.R, available ...bool) (mask uint64) { for i, a := range available { if a { mask |= uint64(1) << (uint8(i<<1) + uint8(cat)) *callRegs = append(*callRegs, regs.R(i)) } } return }
func TestRegAllocSpecific(t *testing.T) { for _, avail := range []uint64{0xffffffffffffffff, 1 << (5 << 1)} { t.Logf("avail: 0x%016x", avail) var ra regAllocator ra.init(avail) t.Logf("cat = %#v", gen.RegCategoryInt) t.Logf("reg = %#v", regs.R(5)) t.Logf("ra = %#v", ra) t.Logf("reg index = %v", regIndex(gen.RegCategoryInt, regs.R(5))) t.Logf("reg mask = %v", regMask(gen.RegCategoryInt, regs.R(5))) ra.allocSpecific(gen.RegCategoryInt, regs.R(5)) if !ra.allocated(gen.RegCategoryInt, regs.R(5)) { t.Fatal("1") } func() { defer func() { if recover() == nil { t.Fatal("2") } }() ra.allocSpecific(gen.RegCategoryInt, regs.R(5)) }() } }
"github.com/tsavola/wag/types" ) const ( functionAlignment = 16 paddingByte = 0xcc // int3 instruction ) const ( // Don't use regResult for effective addresses etc. to avoid information // leaks. Void functions may leave information in the result register, and // call graph could be rewritten during snapshot/restore to cause void // function to return to a non-void call site. regResult = regs.R(0) // rax or xmm0 regShiftCount = regs.R(1) // rcx regScratch = regs.R(2) // rdx or xmm2 regImportArgCount = regs.R(2) // rdx regImportSigIndex = regs.R(3) // rbx regStackPtr = regs.R(4) // rsp regTextBase = regs.R(12) // r12 regStackLimit = regs.R(13) // r13 regMemoryBase = regs.R(14) // r14 regMemoryLimit = regs.R(15) // r15 regTrapHandlerMMX = regs.R(0) // mm0 regMemoryGrowLimitMMX = regs.R(1) // mm1 regScratchMMX = regs.R(2) // mm2 )
func (o Operand) Reg() regs.R { return regs.R(byte(o.payload)) }
} return } func writeModTo(code gen.OpCoder, mod mod, ro, rm byte) { code.WriteByte(byte(mod) | ((ro & 7) << 3) | (rm & 7)) } const ( MemSIB = byte((1 << 2)) MemDisp32 = byte((1 << 2) | (1 << 0)) ) const ( NoIndex = regs.R((1 << 2)) NoBase = regs.R((1 << 2) | (1 << 0)) ) func writeSibTo(code gen.OpCoder, scale byte, index, base regs.R) { if scale >= 4 { panic("scale factor out of bounds") } code.WriteByte((scale << 6) | (byte(index&7) << 3) | byte(base&7)) } // type insnConst []byte func (opcode insnConst) op(code gen.OpCoder) {