/*
 * Software emulation of some PPC instructions for the 8xx core.
 *
 * Copyright (C) 1998 Dan Malek (dmalek@jlc.net)
 *
 * Software floating emuation for the MPC8xx processor.  I did this mostly
 * because it was easier than trying to get the libraries compiled for
 * software floating point.  The goal is still to get the libraries done,
 * but I lost patience and needed some hacks to at least get init and
 * shells running.  The first problem is the setjmp/longjmp that save
 * and restore the floating point registers.
 *
 * For this emulation, our working registers are found on the register
 * save area.
 */

#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/interrupt.h>

#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>

/* Eventually we may need a look-up table, but this works for now.
*/
#define LFS	48
#define LFD	50
#define LFDU	51
#define STFD	54
#define STFDU	55
#define FMR	63

void print_8xx_pte(struct mm_struct *mm, unsigned long addr)
{
	pgd_t *pgd;
	pmd_t *pmd;
	pte_t *pte;

	printk(" pte @ 0x%8lx: ", addr);
	pgd = pgd_offset(mm, addr & PAGE_MASK);
	if (pgd) {
		pmd = pmd_offset(pud_offset(pgd, addr & PAGE_MASK),
		                 addr & PAGE_MASK);
		if (pmd && pmd_present(*pmd)) {
			pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
			if (pte) {
				printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
				        (long)pgd, (long)pte, (long)pte_val(*pte));
#define pp ((long)pte_val(*pte))
				printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
				       "CI: %lx v: %lx\n",
				       pp>>12,    /* rpn */
				       (pp>>10)&3, /* pp */
				       (pp>>3)&1, /* small */
				       (pp>>2)&1, /* shared */
				       (pp>>1)&1, /* cache inhibit */
				       pp&1       /* valid */
				       );
#undef pp
			}
			else {
				printk("no pte\n");
			}
		}
		else {
			printk("no pmd\n");
		}
	}
	else {
		printk("no pgd\n");
	}
}

int get_8xx_pte(struct mm_struct *mm, unsigned long addr)
{
	pgd_t *pgd;
	pmd_t *pmd;
	pte_t *pte;
	int retval = 0;

	pgd = pgd_offset(mm, addr & PAGE_MASK);
	if (pgd) {
		pmd = pmd_offset(pud_offset(pgd, addr & PAGE_MASK),
		                 addr & PAGE_MASK);
		if (pmd && pmd_present(*pmd)) {
			pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
			if (pte) {
				retval = (int)pte_val(*pte);
			}
		}
	}
	return retval;
}

/*
 * We return 0 on success, 1 on unimplemented instruction, and EFAULT
 * if a load/store faulted.
 */
int Soft_emulate_8xx(struct pt_regs *regs)
{
	u32 inst, instword;
	u32 flreg, idxreg, disp;
	int retval;
	s16 sdisp;
	u32 *ea, *ip;

	retval = 0;

	instword = *((u32 *)regs->nip);
	inst = instword >> 26;

	flreg = (instword >> 21) & 0x1f;
	idxreg = (instword >> 16) & 0x1f;
	disp = instword & 0xffff;

	ea = (u32 *)(regs->gpr[idxreg] + disp);
	ip = (u32 *)&current->thread.TS_FPR(flreg);

	switch ( inst )
	{
	case LFD:
		/* this is a 16 bit quantity that is sign extended
		 * so use a signed short here -- Cort
		 */
		sdisp = (instword & 0xffff);
		ea = (u32 *)(regs->gpr[idxreg] + sdisp);
		if (copy_from_user(ip, ea, sizeof(double)))
			retval = -EFAULT;
		break;

	case LFDU:
		if (copy_from_user(ip, ea, sizeof(double)))
			retval = -EFAULT;
		else
			regs->gpr[idxreg] = (u32)ea;
		break;
	case LFS:
		sdisp = (instword & 0xffff);
		ea = (u32 *)(regs->gpr[idxreg] + sdisp);
		if (copy_from_user(ip, ea, sizeof(float)))
			retval = -EFAULT;
		break;
	case STFD:
		/* this is a 16 bit quantity that is sign extended
		 * so use a signed short here -- Cort
		 */
		sdisp = (instword & 0xffff);
		ea = (u32 *)(regs->gpr[idxreg] + sdisp);
		if (copy_to_user(ea, ip, sizeof(double)))
			retval = -EFAULT;
		break;

	case STFDU:
		if (copy_to_user(ea, ip, sizeof(double)))
			retval = -EFAULT;
		else
			regs->gpr[idxreg] = (u32)ea;
		break;
	case FMR:
		/* assume this is a fp move -- Cort */
		memcpy(ip, &current->thread.TS_FPR((instword>>11)&0x1f),
		       sizeof(double));
		break;
	default:
		retval = 1;
		printk("Bad emulation %s/%d\n"
		       " NIP: %08lx instruction: %08x opcode: %x "
		       "A: %x B: %x C: %x code: %x rc: %x\n",
		       current->comm,current->pid,
		       regs->nip,
		       instword,inst,
		       (instword>>16)&0x1f,
		       (instword>>11)&0x1f,
		       (instword>>6)&0x1f,
		       (instword>>1)&0x3ff,
		       instword&1);
		{
			int pa;
			print_8xx_pte(current->mm,regs->nip);
			pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK;
			pa |= (regs->nip & ~PAGE_MASK);
			pa = (unsigned long)__va(pa);
			printk("Kernel VA for NIP %x ", pa);
			print_8xx_pte(current->mm,pa);
		}
	}

	if (retval == 0)
		regs->nip += 4;

	return retval;
}
