/*
 * Copyright 2003 PathScale, Inc.
 *
 * Licensed under the GPL
 */

#define __FRAME_OFFSETS
#include <asm/ptrace.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/elf.h>

/* XXX x86_64 */
unsigned long not_ss;
unsigned long not_ds;
unsigned long not_es;

#define SC_SS(r) (not_ss)
#define SC_DS(r) (not_ds)
#define SC_ES(r) (not_es)

/* determines which flags the user has access to. */
/* 1 = access 0 = no access */
#define FLAG_MASK 0x44dd5UL

int putreg(struct task_struct *child, int regno, unsigned long value)
{
	unsigned long tmp;

#ifdef TIF_IA32
	/* Some code in the 64bit emulation may not be 64bit clean.
	   Don't take any chances. */
	if (test_tsk_thread_flag(child, TIF_IA32))
		value &= 0xffffffff;
#endif
	switch (regno){
	case FS:
	case GS:
	case DS:
	case ES:
	case SS:
	case CS:
		if (value && (value & 3) != 3)
			return -EIO;
		value &= 0xffff;
		break;

	case FS_BASE:
	case GS_BASE:
		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
			return -EIO;
		break;

	case EFLAGS:
		value &= FLAG_MASK;
		tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK;
		value |= tmp;
		break;
	}

	PT_REGS_SET(&child->thread.regs, regno, value);
	return 0;
}

int poke_user(struct task_struct *child, long addr, long data)
{
        if ((addr & 3) || addr < 0)
                return -EIO;

        if (addr < MAX_REG_OFFSET)
                return putreg(child, addr, data);

#if 0 /* Need x86_64 debugregs handling */
        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))){
                addr -= offsetof(struct user, u_debugreg[0]);
                addr = addr >> 2;
                if((addr == 4) || (addr == 5)) return -EIO;
                child->thread.arch.debugregs[addr] = data;
                return 0;
        }
#endif
        return -EIO;
}

unsigned long getreg(struct task_struct *child, int regno)
{
	unsigned long retval = ~0UL;
	switch (regno) {
	case FS:
	case GS:
	case DS:
	case ES:
	case SS:
	case CS:
		retval = 0xffff;
		/* fall through */
	default:
		retval &= PT_REG(&child->thread.regs, regno);
#ifdef TIF_IA32
		if (test_tsk_thread_flag(child, TIF_IA32))
			retval &= 0xffffffff;
#endif
	}
	return retval;
}

int peek_user(struct task_struct *child, long addr, long data)
{
	/* read the word at location addr in the USER area. */
        unsigned long tmp;

        if ((addr & 3) || addr < 0)
                return -EIO;

        tmp = 0;  /* Default return condition */
        if(addr < MAX_REG_OFFSET){
                tmp = getreg(child, addr);
        }
#if 0 /* Need x86_64 debugregs handling */
        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))){
                addr -= offsetof(struct user, u_debugreg[0]);
                addr = addr >> 2;
                tmp = child->thread.arch.debugregs[addr];
        }
#endif
        return put_user(tmp, (unsigned long *) data);
}

void arch_switch(void)
{
/* XXX
	printk("arch_switch\n");
*/
}

/* XXX Mostly copied from sys-i386 */
int is_syscall(unsigned long addr)
{
	unsigned short instr;
	int n;

	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
	if(n){
		/* access_process_vm() grants access to vsyscall and stub,
		 * while copy_from_user doesn't. Maybe access_process_vm is
		 * slow, but that doesn't matter, since it will be called only
		 * in case of singlestepping, if copy_from_user failed.
		 */
		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
		if(n != sizeof(instr)) {
			printk("is_syscall : failed to read instruction from "
			       "0x%lx\n", addr);
			return(1);
		}
	}
	/* sysenter */
	return(instr == 0x050f);
}

int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
{
	panic("dump_fpu");
	return(1);
}

int get_fpregs(unsigned long buf, struct task_struct *child)
{
	panic("get_fpregs");
	return(0);
}

int set_fpregs(unsigned long buf, struct task_struct *child)
{
	panic("set_fpregs");
	return(0);
}

int get_fpxregs(unsigned long buf, struct task_struct *tsk)
{
	panic("get_fpxregs");
	return(0);
}

int set_fpxregs(unsigned long buf, struct task_struct *tsk)
{
	panic("set_fxpregs");
	return(0);
}

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-file-style: "linux"
 * End:
 */
