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
23#include <asm/constants.h>
24
25/* This is the kernel's entry point into the floating point emulator.
26It is called from the kernel with code similar to this:
27
28	mov	fp, #0
29	teqp	pc, #I_BIT | MODE_SVC
30	ldr	r4, .LC2
31	ldr	pc, [r4]		@ Call FP module USR entry point
32
33The kernel expects the emulator to return via one of two possible
34points of return it passes to the emulator.  The emulator, if
35successful in its emulation, jumps to ret_from_exception and the
36kernel takes care of returning control from the trap to the user code.
37If the emulator is unable to emulate the instruction, it returns to
38fpundefinstr and the kernel halts the user program with a core dump.
39
40This routine does four things:
41
421) It saves SP into a variable called userRegisters.  The kernel has
43created a struct pt_regs on the stack and saved the user registers
44into it.  See /usr/include/asm/proc/ptrace.h for details.  The
45emulator code uses userRegisters as the base of an array of words from
46which the contents of the registers can be extracted.
47
482) It locates the FP emulator work area within the TSS structure and
49points `fpa11' to it.
50
513) It calls EmulateAll to emulate a floating point instruction.
52EmulateAll returns 1 if the emulation was successful, or 0 if not.
53
544) If an instruction has been emulated successfully, it looks ahead at
55the next instruction.  If it is a floating point instruction, it
56executes the instruction, without returning to user space.  In this
57way it repeatedly looks ahead and executes floating point instructions
58until it encounters a non floating point instruction, at which time it
59returns via _fpreturn.
60
61This is done to reduce the effect of the trap overhead on each
62floating point instructions.  GCC attempts to group floating point
63instructions to allow the emulator to spread the cost of the trap over
64several floating point instructions.  */
65
66	.globl	nwfpe_enter
67nwfpe_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
731:	cmp	r0, #0			@ was emulation successful
74	beq	fpundefinstr		@ no, return failure
75
76next:
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
113