// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package proc

import (
	"os";
	"strconv";
	"syscall";
)

type amd64Regs struct {
	syscall.PtraceRegs;
	setter	func(*syscall.PtraceRegs) os.Error;
}

var names = [...]string{
	"rax",
	"rbx",
	"rcx",
	"rdx",
	"rsi",
	"rdi",
	"rbp",
	"rsp",
	"r8",
	"r9",
	"r10",
	"r11",
	"r12",
	"r13",
	"r14",
	"r15",
	"rip",
	"eflags",
	"cs",
	"ss",
	"ds",
	"es",
	"fs",
	"gs",

	// PtraceRegs contains these registers, but I don't think
	// they're actually meaningful.
	//"orig_rax",
	//"fs_base",
	//"gs_base",
}

func (r *amd64Regs) PC() Word	{ return Word(r.Rip) }

func (r *amd64Regs) SetPC(val Word) os.Error {
	r.Rip = uint64(val);
	return r.setter(&r.PtraceRegs);
}

func (r *amd64Regs) Link() Word {
	// TODO(austin)
	panic("No link register")
}

func (r *amd64Regs) SetLink(val Word) os.Error {
	panic("No link register")
}

func (r *amd64Regs) SP() Word	{ return Word(r.Rsp) }

func (r *amd64Regs) SetSP(val Word) os.Error {
	r.Rsp = uint64(val);
	return r.setter(&r.PtraceRegs);
}

func (r *amd64Regs) Names() []string	{ return &names }

func (r *amd64Regs) Get(i int) Word {
	switch i {
	case 0:
		return Word(r.Rax)
	case 1:
		return Word(r.Rbx)
	case 2:
		return Word(r.Rcx)
	case 3:
		return Word(r.Rdx)
	case 4:
		return Word(r.Rsi)
	case 5:
		return Word(r.Rdi)
	case 6:
		return Word(r.Rbp)
	case 7:
		return Word(r.Rsp)
	case 8:
		return Word(r.R8)
	case 9:
		return Word(r.R9)
	case 10:
		return Word(r.R10)
	case 11:
		return Word(r.R11)
	case 12:
		return Word(r.R12)
	case 13:
		return Word(r.R13)
	case 14:
		return Word(r.R14)
	case 15:
		return Word(r.R15)
	case 16:
		return Word(r.Rip)
	case 17:
		return Word(r.Eflags)
	case 18:
		return Word(r.Cs)
	case 19:
		return Word(r.Ss)
	case 20:
		return Word(r.Ds)
	case 21:
		return Word(r.Es)
	case 22:
		return Word(r.Fs)
	case 23:
		return Word(r.Gs)
	}
	panic("invalid register index ", strconv.Itoa(i));
}

func (r *amd64Regs) Set(i int, val Word) os.Error {
	switch i {
	case 0:
		r.Rax = uint64(val)
	case 1:
		r.Rbx = uint64(val)
	case 2:
		r.Rcx = uint64(val)
	case 3:
		r.Rdx = uint64(val)
	case 4:
		r.Rsi = uint64(val)
	case 5:
		r.Rdi = uint64(val)
	case 6:
		r.Rbp = uint64(val)
	case 7:
		r.Rsp = uint64(val)
	case 8:
		r.R8 = uint64(val)
	case 9:
		r.R9 = uint64(val)
	case 10:
		r.R10 = uint64(val)
	case 11:
		r.R11 = uint64(val)
	case 12:
		r.R12 = uint64(val)
	case 13:
		r.R13 = uint64(val)
	case 14:
		r.R14 = uint64(val)
	case 15:
		r.R15 = uint64(val)
	case 16:
		r.Rip = uint64(val)
	case 17:
		r.Eflags = uint64(val)
	case 18:
		r.Cs = uint64(val)
	case 19:
		r.Ss = uint64(val)
	case 20:
		r.Ds = uint64(val)
	case 21:
		r.Es = uint64(val)
	case 22:
		r.Fs = uint64(val)
	case 23:
		r.Gs = uint64(val)
	default:
		panic("invalid register index ", strconv.Itoa(i))
	}
	return r.setter(&r.PtraceRegs);
}

func newRegs(regs *syscall.PtraceRegs, setter func(*syscall.PtraceRegs) os.Error) Regs {
	res := amd64Regs{};
	res.PtraceRegs = *regs;
	res.setter = setter;
	return &res;
}
