-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 67494 b: refs/heads/master c: 5dd57a1 h: refs/heads/master v: v3
- Loading branch information
Scott Wood
authored and
Kumar Gala
committed
Oct 4, 2007
1 parent
d4609ca
commit d240440
Showing
5 changed files
with
221 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: c4e05bc57dd14294683cdea7fe36ce3c01f5c6ae | ||
refs/heads/master: 5dd57a1308a7e40e04fb6ecbff170df7a0b92cd8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
/* | ||
* 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/a.out.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 *)¤t->thread.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, ¤t->thread.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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters