Exemple #1
0
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))
		}()
	}
}
Exemple #2
0
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)
	}
}
Exemple #3
0
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
}
Exemple #4
0
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))
		}()
	}
}
Exemple #5
0
	"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
)
Exemple #6
0
func (o Operand) Reg() regs.R {
	return regs.R(byte(o.payload))
}
Exemple #7
0
	}

	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) {