Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | NetWinder Floating Point Emulator | |
3 | (c) Rebel.COM, 1998 | |
4 | (c) Philip Blundell 1998-1999 | |
5 | ||
6 | Direct questions, comments to Scott Bambrough <scottb@netwinder.org> | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | */ | |
22 | ||
e6ae744d | 23 | #include <asm/asm-offsets.h> |
1da177e4 LT |
24 | |
25 | /* This is the kernel's entry point into the floating point emulator. | |
26 | It is called from the kernel with code similar to this: | |
27 | ||
28 | mov fp, #0 | |
29 | teqp pc, #PSR_I_BIT | MODE_SVC | |
30 | ldr r4, .LC2 | |
31 | ldr pc, [r4] @ Call FP module USR entry point | |
32 | ||
33 | The kernel expects the emulator to return via one of two possible | |
34 | points of return it passes to the emulator. The emulator, if | |
35 | successful in its emulation, jumps to ret_from_exception and the | |
36 | kernel takes care of returning control from the trap to the user code. | |
37 | If the emulator is unable to emulate the instruction, it returns to | |
38 | fpundefinstr and the kernel halts the user program with a core dump. | |
39 | ||
40 | This routine does four things: | |
41 | ||
42 | 1) It saves SP into a variable called userRegisters. The kernel has | |
43 | created a struct pt_regs on the stack and saved the user registers | |
44 | into it. See /usr/include/asm/proc/ptrace.h for details. The | |
45 | emulator code uses userRegisters as the base of an array of words from | |
46 | which the contents of the registers can be extracted. | |
47 | ||
48 | 2) It locates the FP emulator work area within the TSS structure and | |
49 | points `fpa11' to it. | |
50 | ||
51 | 3) It calls EmulateAll to emulate a floating point instruction. | |
52 | EmulateAll returns 1 if the emulation was successful, or 0 if not. | |
53 | ||
54 | 4) If an instruction has been emulated successfully, it looks ahead at | |
55 | the next instruction. If it is a floating point instruction, it | |
56 | executes the instruction, without returning to user space. In this | |
57 | way it repeatedly looks ahead and executes floating point instructions | |
58 | until it encounters a non floating point instruction, at which time it | |
59 | returns via _fpreturn. | |
60 | ||
61 | This is done to reduce the effect of the trap overhead on each | |
62 | floating point instructions. GCC attempts to group floating point | |
63 | instructions to allow the emulator to spread the cost of the trap over | |
64 | several floating point instructions. */ | |
65 | ||
66 | .globl nwfpe_enter | |
67 | nwfpe_enter: | |
68 | mov sl, sp | |
69 | ldr r5, [sp, #60] @ get contents of PC | |
70 | bic r5, r5, #0xfc000003 | |
71 | ldr r0, [r5, #-4] @ get actual instruction into r0 | |
72 | bl EmulateAll @ emulate the instruction | |
73 | 1: cmp r0, #0 @ was emulation successful | |
74 | beq fpundefinstr @ no, return failure | |
75 | ||
76 | next: | |
77 | .Lx1: ldrt r6, [r5], #4 @ get the next instruction and | |
78 | @ increment PC | |
79 | ||
80 | and r2, r6, #0x0F000000 @ test for FP insns | |
81 | teq r2, #0x0C000000 | |
82 | teqne r2, #0x0D000000 | |
83 | teqne r2, #0x0E000000 | |
84 | bne ret_from_exception @ return ok if not a fp insn | |
85 | ||
86 | ldr r9, [sp, #60] @ get new condition codes | |
87 | and r9, r9, #0xfc000003 | |
88 | orr r7, r5, r9 | |
89 | str r7, [sp, #60] @ update PC copy in regs | |
90 | ||
91 | mov r0, r6 @ save a copy | |
92 | mov r1, r9 @ fetch the condition codes | |
93 | bl checkCondition @ check the condition | |
94 | cmp r0, #0 @ r0 = 0 ==> condition failed | |
95 | ||
96 | @ if condition code failed to match, next insn | |
97 | beq next @ get the next instruction; | |
98 | ||
99 | mov r0, r6 @ prepare for EmulateAll() | |
100 | adr lr, 1b | |
101 | orr lr, lr, #3 | |
102 | b EmulateAll @ if r0 != 0, goto EmulateAll | |
103 | ||
104 | .Lret: b ret_from_exception @ let the user eat segfaults | |
105 | ||
106 | @ We need to be prepared for the instruction at .Lx1 to fault. | |
107 | @ Emit the appropriate exception gunk to fix things up. | |
108 | .section __ex_table,"a" | |
109 | .align 3 | |
110 | .long .Lx1 | |
111 | ldr lr, [lr, $(.Lret - .Lx1)/4] | |
112 | .previous |