Exemple #1
0
func TestIncDec(t *testing.T) {
	cases := []simple{
		{
			func(a *Assembler) {
				a.Mov(Rdi, Rax)
				a.Inc(Rax)
			},
			[]uintptr{0, 1, 10, 11},
		},
		{
			func(a *Assembler) {
				a.Mov(Rdi, Rax)
				a.Dec(Rax)
			},
			[]uintptr{1, 0, 11, 10},
		},
		{
			func(a *Assembler) {
				a.Mov(Imm{0x11223344}, Indirect{Rdi, 0, 32})
				a.Incb(Indirect{Rdi, 1, 8})
				a.Mov(Indirect{Rdi, 0, 32}, Eax)
			},
			[]uintptr{gojit.Addr(mem), 0x11223444},
		},
		{
			func(a *Assembler) {
				a.Mov(Imm{0x11223344}, Indirect{Rdi, 0, 32})
				a.Decb(Indirect{Rdi, 1, 8})
				a.Mov(Indirect{Rdi, 0, 32}, Eax)
			},
			[]uintptr{gojit.Addr(mem), 0x11223244},
		},
	}
	testSimple("inc/dec", t, cases)
}
Exemple #2
0
func emitRbrac(asm *amd64.Assembler, cc *compiled) {
	header := cc.stack[len(cc.stack)-1]
	cc.stack = cc.stack[:len(cc.stack)-1]
	asm.JmpRel(gojit.Addr(asm.Buf[header:]))
	end := asm.Off

	asm.Off = header
	asm.Testb(amd64.Imm{0xff}, amd64.Indirect{amd64.Rax, 0, 8})
	asm.JccRel(amd64.CC_Z, gojit.Addr(asm.Buf[end:]))
	asm.Off = end
}
Exemple #3
0
func TestMov(t *testing.T) {
	cases := []simple{
		{
			func(a *Assembler) {
				a.Mov(Imm{U32(0xdeadbeef)}, Rax)
			},
			[]uintptr{0, 0xdeadbeef},
		},
		{
			func(a *Assembler) {
				a.Mov(Rdi, Rax)
			},
			[]uintptr{0, 0, 1, 1, 0xdeadbeef, 0xdeadbeef, 0xffffffffffffffff, 0xffffffffffffffff},
		},
		{
			func(a *Assembler) {
				a.Mov(Imm{U32(0xcafebabe)}, Indirect{Rdi, 0, 64})
				a.Mov(Indirect{Rdi, 0, 64}, Rax)
			},
			[]uintptr{gojit.Addr(mem), 0xffffffffcafebabe},
		},
		{
			func(a *Assembler) {
				a.Mov(Imm{U32(0xf00dface)}, R10)
				a.Mov(R10, Rax)
			},
			[]uintptr{0, 0xf00dface},
		},
	}

	testSimple("mov", t, cases)
}
Exemple #4
0
func (a *Assembler) rel32(addr uintptr) {
	off := uintptr(addr) - gojit.Addr(a.Buf[a.Off:]) - 4
	if uintptr(int32(off)) != off {
		panic("call rel: target out of range")
	}
	a.int32(uint32(off))
}
Exemple #5
0
func emitLbrac(asm *amd64.Assembler, cc *compiled) {
	cc.stack = append(cc.stack, asm.Off)
	asm.Testb(amd64.Imm{0xff}, amd64.Indirect{amd64.Rax, 0, 8})
	asm.JccRel(amd64.CC_Z, gojit.Addr(asm.Buf[asm.Off:]))
}
Exemple #6
0
func TestArith(t *testing.T) {
	cases := []struct {
		insn     *Instruction
		lhs, rhs int32
		out      uintptr
	}{
		{InstAdd, 20, 30, 50},
		{InstAdd, 0x7fffffff, 0x70000001, 0xf0000000},
		{InstAnd, 0x77777777, U32(0xffffffff), 0x77777777},
		{InstAnd, 0x77777777, U32(0x88888888), 0},
		{InstOr, 0x77777777, U32(0x88888888), 0xffffffff},
		{InstOr, 1, 0, 1},
		{InstSub, 5, 10, 5},
		{InstSub, 10, 5, 0xfffffffffffffffb},
	}

	buf, e := gojit.Alloc(gojit.PageSize)
	if e != nil {
		t.Fatalf(e.Error())
	}
	defer gojit.Release(buf)

	for _, tc := range cases {
		asm := &Assembler{buf, 0, CgoABI}
		var funcs []func(uintptr) uintptr
		if tc.insn.imm_r.ok() {
			begin(asm)
			asm.Mov(Imm{tc.rhs}, Rax)
			asm.Arithmetic(tc.insn, Imm{tc.lhs}, Rax)
			funcs = append(funcs, finish(asm))
		}
		if tc.insn.imm_rm.op.ok() {
			begin(asm)
			asm.Mov(Imm{0}, Indirect{Rdi, 0, 0})
			asm.Mov(Imm{tc.rhs}, Indirect{Rdi, 0, 32})
			asm.Arithmetic(tc.insn, Imm{tc.lhs}, Indirect{Rdi, 0, 64})
			asm.Mov(Indirect{Rdi, 0, 64}, Rax)
			funcs = append(funcs, finish(asm))
		}
		if tc.insn.r_rm.ok() {
			begin(asm)
			asm.Mov(Imm{tc.lhs}, R10)
			asm.Mov(Imm{0}, Indirect{Rdi, 0, 0})
			asm.Mov(Imm{tc.rhs}, Indirect{Rdi, 0, 32})
			asm.Arithmetic(tc.insn, R10, Indirect{Rdi, 0, 64})
			asm.Mov(Indirect{Rdi, 0, 64}, Rax)
			funcs = append(funcs, finish(asm))
		}
		if tc.insn.rm_r.ok() {
			begin(asm)
			asm.Mov(Imm{0}, Indirect{Rdi, 0, 0})
			asm.Mov(Imm{tc.lhs}, Indirect{Rdi, 0, 32})
			asm.Mov(Imm{tc.rhs}, R10)
			asm.Arithmetic(tc.insn, Indirect{Rdi, 0, 64}, R10)
			asm.Mov(R10, Rax)
			funcs = append(funcs, finish(asm))
		}

		for i, f := range funcs {
			got := f(gojit.Addr(mem))
			if got != tc.out {
				t.Errorf("%s(0x%x,0x%x) [%d] = 0x%x (expect 0x%x)",
					tc.insn.Mnemonic, tc.lhs, tc.rhs, i, got, tc.out)
			} else if testing.Verbose() {
				// We don't use `testing.Logf` because
				// if we panic inside JIT'd code, the
				// runtime dies horrible (rightfully
				// so!), and so the `testing` cleanup
				// code never runs, and we never see
				// log messages. We want to get these
				// out as soon as possible, so we
				// write them directly.
				fmt.Printf("OK %d %s(0x%x,0x%x) = 0x%x\n",
					i, tc.insn.Mnemonic, tc.lhs, tc.rhs, got)
			}
		}
	}
}