~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/ppc/kernel/softemu8xx.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Software emulation of some PPC instructions for the 8xx core.
  3  *
  4  * Copyright (C) 1998 Dan Malek (dmalek@jlc.net)
  5  *
  6  * Software floating emuation for the MPC8xx processor.  I did this mostly
  7  * because it was easier than trying to get the libraries compiled for
  8  * software floating point.  The goal is still to get the libraries done,
  9  * but I lost patience and needed some hacks to at least get init and
 10  * shells running.  The first problem is the setjmp/longjmp that save
 11  * and restore the floating point registers.
 12  *
 13  * For this emulation, our working registers are found on the register
 14  * save area.
 15  */
 16 
 17 #include <linux/errno.h>
 18 #include <linux/sched.h>
 19 #include <linux/kernel.h>
 20 #include <linux/mm.h>
 21 #include <linux/stddef.h>
 22 #include <linux/unistd.h>
 23 #include <linux/ptrace.h>
 24 #include <linux/slab.h>
 25 #include <linux/user.h>
 26 #include <linux/a.out.h>
 27 #include <linux/interrupt.h>
 28 
 29 #include <asm/pgtable.h>
 30 #include <asm/uaccess.h>
 31 #include <asm/system.h>
 32 #include <asm/io.h>
 33 
 34 extern void
 35 print_8xx_pte(struct mm_struct *mm, unsigned long addr);
 36 extern int
 37 get_8xx_pte(struct mm_struct *mm, unsigned long addr);
 38 
 39 /* Eventually we may need a look-up table, but this works for now.
 40 */
 41 #define LFS     48
 42 #define LFD     50
 43 #define LFDU    51
 44 #define STFD    54
 45 #define STFDU   55
 46 #define FMR     63
 47 
 48 /*
 49  * We return 0 on success, 1 on unimplemented instruction, and EFAULT
 50  * if a load/store faulted.
 51  */
 52 int
 53 Soft_emulate_8xx(struct pt_regs *regs)
 54 {
 55         uint    inst, instword;
 56         uint    flreg, idxreg, disp;
 57         uint    retval;
 58         signed short sdisp;
 59         uint    *ea, *ip;
 60 
 61         retval = 0;
 62 
 63         instword = *((uint *)regs->nip);
 64         inst = instword >> 26;
 65 
 66         flreg = (instword >> 21) & 0x1f;
 67         idxreg = (instword >> 16) & 0x1f;
 68         disp = instword & 0xffff;
 69 
 70         ea = (uint *)(regs->gpr[idxreg] + disp);
 71         ip = (uint *)&current->thread.fpr[flreg];
 72 
 73         switch ( inst )
 74         {
 75         case LFD:
 76                 /* this is a 16 bit quantity that is sign extended
 77                  * so use a signed short here -- Cort
 78                  */
 79                 sdisp = (instword & 0xffff);
 80                 ea = (uint *)(regs->gpr[idxreg] + sdisp);
 81                 if (copy_from_user(ip, ea, sizeof(double)))
 82                         retval = -EFAULT;
 83                 break;
 84                 
 85         case LFDU:
 86                 if (copy_from_user(ip, ea, sizeof(double)))
 87                         retval = -EFAULT;
 88                 else
 89                         regs->gpr[idxreg] = (uint)ea;
 90                 break;
 91         case LFS:
 92                 sdisp = (instword & 0xffff);
 93                 ea = (uint *)(regs->gpr[idxreg] + sdisp);
 94                 if (copy_from_user(ip, ea, sizeof(float)))
 95                         retval = -EFAULT;
 96                 break;
 97         case STFD:
 98                 /* this is a 16 bit quantity that is sign extended
 99                  * so use a signed short here -- Cort
100                  */
101                 sdisp = (instword & 0xffff);
102                 ea = (uint *)(regs->gpr[idxreg] + sdisp);
103                 if (copy_to_user(ea, ip, sizeof(double)))
104                         retval = -EFAULT;
105                 break;
106 
107         case STFDU:
108                 if (copy_to_user(ea, ip, sizeof(double)))
109                         retval = -EFAULT;
110                 else
111                         regs->gpr[idxreg] = (uint)ea;
112                 break;
113         case FMR:
114                 /* assume this is a fp move -- Cort */
115                 memcpy( ip, &current->thread.fpr[(instword>>11)&0x1f],
116                         sizeof(double) );
117                 break;
118         default:
119                 retval = 1;
120                 printk("Bad emulation %s/%d\n"
121                        " NIP: %08lx instruction: %08x opcode: %x "
122                        "A: %x B: %x C: %x code: %x rc: %x\n",
123                        current->comm,current->pid,
124                        regs->nip,
125                        instword,inst,
126                        (instword>>16)&0x1f,
127                        (instword>>11)&0x1f,
128                        (instword>>6)&0x1f,
129                        (instword>>1)&0x3ff,
130                        instword&1);
131                 {
132                         int pa;
133                         print_8xx_pte(current->mm,regs->nip);
134                         pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK;
135                         pa |= (regs->nip & ~PAGE_MASK);
136                         pa = __va(pa);
137                         printk("Kernel VA for NIP %x ", pa);
138                         print_8xx_pte(current->mm,pa);
139                 }
140                 
141         }
142 
143         if (retval == 0)
144                 regs->nip += 4;
145         return(retval);
146 }
147 
148 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp