![]() |
|
|||
0001 /* SPDX-License-Identifier: GPL-2.0-or-later */ 0002 /* 0003 NetWinder Floating Point Emulator 0004 (c) Rebel.COM, 1998 0005 (c) 1998, 1999 Philip Blundell 0006 0007 Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 0008 0009 */ 0010 #include <asm/assembler.h> 0011 #include <asm/opcodes.h> 0012 0013 /* This is the kernel's entry point into the floating point emulator. 0014 It is called from the kernel with code similar to this: 0015 0016 sub r4, r5, #4 0017 ldrt r0, [r4] @ r0 = instruction 0018 adrsvc al, r9, ret_from_exception @ r9 = normal FP return 0019 adrsvc al, lr, fpundefinstr @ lr = undefined instr return 0020 0021 get_current_task r10 0022 mov r8, #1 0023 strb r8, [r10, #TSK_USED_MATH] @ set current->used_math 0024 add r10, r10, #TSS_FPESAVE @ r10 = workspace 0025 ldr r4, .LC2 0026 ldr pc, [r4] @ Call FP emulator entry point 0027 0028 The kernel expects the emulator to return via one of two possible 0029 points of return it passes to the emulator. The emulator, if 0030 successful in its emulation, jumps to ret_from_exception (passed in 0031 r9) and the kernel takes care of returning control from the trap to 0032 the user code. If the emulator is unable to emulate the instruction, 0033 it returns via _fpundefinstr (passed via lr) and the kernel halts the 0034 user program with a core dump. 0035 0036 On entry to the emulator r10 points to an area of private FP workspace 0037 reserved in the thread structure for this process. This is where the 0038 emulator saves its registers across calls. The first word of this area 0039 is used as a flag to detect the first time a process uses floating point, 0040 so that the emulator startup cost can be avoided for tasks that don't 0041 want it. 0042 0043 This routine does three things: 0044 0045 1) The kernel has created a struct pt_regs on the stack and saved the 0046 user registers into it. See /usr/include/asm/proc/ptrace.h for details. 0047 0048 2) It calls EmulateAll to emulate a floating point instruction. 0049 EmulateAll returns 1 if the emulation was successful, or 0 if not. 0050 0051 3) If an instruction has been emulated successfully, it looks ahead at 0052 the next instruction. If it is a floating point instruction, it 0053 executes the instruction, without returning to user space. In this 0054 way it repeatedly looks ahead and executes floating point instructions 0055 until it encounters a non floating point instruction, at which time it 0056 returns via _fpreturn. 0057 0058 This is done to reduce the effect of the trap overhead on each 0059 floating point instructions. GCC attempts to group floating point 0060 instructions to allow the emulator to spread the cost of the trap over 0061 several floating point instructions. */ 0062 0063 #include <asm/asm-offsets.h> 0064 0065 .globl nwfpe_enter 0066 nwfpe_enter: 0067 mov r4, lr @ save the failure-return addresses 0068 mov sl, sp @ we access the registers via 'sl' 0069 0070 ldr r5, [sp, #S_PC] @ get contents of PC; 0071 mov r6, r0 @ save the opcode 0072 emulate: 0073 ldr r1, [sp, #S_PSR] @ fetch the PSR 0074 bl arm_check_condition @ check the condition 0075 cmp r0, #ARM_OPCODE_CONDTEST_PASS @ condition passed? 0076 0077 @ if condition code failed to match, next insn 0078 bne next @ get the next instruction; 0079 0080 mov r0, r6 @ prepare for EmulateAll() 0081 bl EmulateAll @ emulate the instruction 0082 cmp r0, #0 @ was emulation successful 0083 reteq r4 @ no, return failure 0084 0085 next: 0086 uaccess_enable r3 0087 .Lx1: ldrt r6, [r5], #4 @ get the next instruction and 0088 @ increment PC 0089 uaccess_disable r3 0090 and r2, r6, #0x0F000000 @ test for FP insns 0091 teq r2, #0x0C000000 0092 teqne r2, #0x0D000000 0093 teqne r2, #0x0E000000 0094 retne r9 @ return ok if not a fp insn 0095 0096 str r5, [sp, #S_PC] @ update PC copy in regs 0097 0098 mov r0, r6 @ save a copy 0099 b emulate @ check condition and emulate 0100 0101 @ We need to be prepared for the instructions at .Lx1 and .Lx2 0102 @ to fault. Emit the appropriate exception gunk to fix things up. 0103 @ ??? For some reason, faults can happen at .Lx2 even with a 0104 @ plain LDR instruction. Weird, but it seems harmless. 0105 .pushsection .text.fixup,"ax" 0106 .align 2 0107 .Lfix: ret r9 @ let the user eat segfaults 0108 .popsection 0109 0110 .pushsection __ex_table,"a" 0111 .align 3 0112 .long .Lx1, .Lfix 0113 .popsection
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |