Move interrupt emulation code from INSTR_EmulateInstruction to winedos
[wine] / msdos / fpu.c
1 /*
2  * DOS interrupt 34->3e handlers.  All FPU interrupt code should be
3  * moved into this file.
4  *  int 3d is not activated yet...
5  *
6  * Copyright 2002 Robert 'Admiral' Coeyman
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library 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 GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <stdlib.h>
24 #include "msdos.h"
25 #include "miscemu.h"
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(int);
29
30 /*
31  *  The actual work is done by a single routine.
32  */
33
34 static void FPU_ModifyCode(CONTEXT86 *context, BYTE Opcode);
35
36
37
38 /**********************************************************************
39  *          INT_Int34Handler (WPROCS.152)
40  *
41  * Handler for int 34 (FLOATING POINT EMULATION - Opcode 0xd8).
42  *
43  *  The interrupt list isn't specific about what this interrupt
44  *  actually does. [ interrup.m ]
45  */
46 void WINAPI INT_Int34Handler(CONTEXT86 *context)
47 {
48
49         TRACE("Int 0x34 called-- FP opcode 0xd8");
50         FPU_ModifyCode(context, 0xd8);
51
52 }
53
54 /**********************************************************************
55  *          INT_Int35Handler (WPROCS.153)
56  *
57  * Handler for int 35 (FLOATING POINT EMULATION - Opcode 0xd9).
58  *
59  *  The interrupt list isn't specific about what this interrupt
60  *  actually does. [ interrup.m ]
61  */
62 void WINAPI INT_Int35Handler(CONTEXT86 *context)
63 {
64         TRACE("Int 0x35 called-- FP opcode 0xd9");
65         FPU_ModifyCode(context, 0xd9);
66
67 }
68
69
70 /**********************************************************************
71  *          INT_Int36Handler (WPROCS.154)
72  *
73  * Handler for int 36 (FLOATING POINT EMULATION - Opcode 0xda).
74  *
75  *  The interrupt list isn't specific about what this interrupt
76  *  actually does. [ interrup.m ]
77  */
78 void WINAPI INT_Int36Handler(CONTEXT86 *context)
79 {
80         TRACE("Int 0x36 called-- FP opcode 0xda");
81         FPU_ModifyCode(context, 0xda);
82
83 }
84
85 /**********************************************************************
86  *          INT_Int37Handler (WPROCS.155)
87  *
88  * Handler for int 37 (FLOATING POINT EMULATION - Opcode 0xdb).
89  *
90  *  The interrupt list isn't specific about what this interrupt
91  *  actually does. [ interrup.m ]
92  */
93 void WINAPI INT_Int37Handler(CONTEXT86 *context)
94 {
95         TRACE("Int 0x37 called-- FP opcode 0xdb");
96         FPU_ModifyCode(context, 0xdb);
97
98 }
99
100 /**********************************************************************
101  *          INT_Int38Handler (WPROCS.156)
102  *
103  * Handler for int 38 (FLOATING POINT EMULATION - Opcode 0xdc).
104  *
105  *  Between versions 3.0 and 5.01, the original PC-MOS API call that
106  *  was here was moved to int 0xd4.
107  *
108  *  The interrupt list isn't specific about what this interrupt
109  *  actually does. [ interrup.m ]
110  */
111 void WINAPI INT_Int38Handler(CONTEXT86 *context)
112 {
113         TRACE("Int 0x38 called-- FP opcode 0xdc");
114         FPU_ModifyCode(context, 0xdc);
115
116 }
117
118 /**********************************************************************
119  *          INT_Int39Handler (WPROCS.157)
120  *
121  * Handler for int 39 (FLOATING POINT EMULATION - Opcode 0xdd).
122  *
123  *  The interrupt list isn't specific about what this interrupt
124  *  actually does. [ interrup.m ]
125  */
126 void WINAPI INT_Int39Handler(CONTEXT86 *context)
127 {
128         TRACE("Int 0x39 called-- FP opcode 0xdd");
129         FPU_ModifyCode(context, 0xdd);
130
131 }
132
133 /**********************************************************************
134  *          INT_Int3aHandler (WPROCS.158)
135  *
136  * Handler for int 3a (FLOATING POINT EMULATION - Opcode 0xde).
137  *
138  *  The interrupt list isn't specific about what this interrupt
139  *  actually does. [ interrup.m ]
140  */
141 void WINAPI INT_Int3aHandler(CONTEXT86 *context)
142 {
143         TRACE("Int 0x3a called-- FP opcode 0xde");
144         FPU_ModifyCode(context, 0xde);
145
146 }
147
148 /**********************************************************************
149  *          INT_Int3bHandler (WPROCS.159)
150  *
151  * Handler for int 3B (FLOATING POINT EMULATION - Opcode 0xdf).
152  *
153  *  The interrupt list isn't specific about what this interrupt
154  *  actually does. [ interrup.m ]
155  */
156 void WINAPI INT_Int3bHandler(CONTEXT86 *context)
157 {
158         TRACE("Int 0x3b called-- FP opcode 0xdf");
159         FPU_ModifyCode(context, 0xdf);
160
161 }
162
163
164
165 /**********************************************************************
166  *          INT_Int3cHandler (WPROCS.160)
167  *
168  * Handler for int 3C (FLOATING POINT EMULATION - INSTRUCTIONS WITH SEGMENT OVERRIDE).
169  *
170  *  Generated code is CD 3C xy mm ... (CD = int | 3C = this interrupt)
171  *   xy is a modified ESC code and mm is the modR/M byte.
172  *   xy byte seems to be encoded as ss011xxx  or ss000xxx
173  *   ss= segment override.
174  *      00 -> DS
175  *      01 -> SS
176  *      10 -> CS
177  *      11 -> ES
178  *
179  *  11011xxx should be the opcode instruction.
180  */
181 void WINAPI INT_Int3cHandler(CONTEXT86 *context)
182 {
183         FIXME("Int 3C NOT Implemented");
184         INT_BARF(context, 0x3c);
185 }
186
187 /**********************************************************************
188  *          INT_Int3dHandler (WPROCS.161)
189  *
190  * Handler for int 3D (FLOATING POINT EMULATION - Standalone FWAIT).
191  *
192  *  Opcode 0x90 is a NOP.  It just fills space where the 3D was.
193  */
194 void WINAPI INT_Int3dHandler(CONTEXT86 *context)
195 {
196         TRACE("Int 0x3d called-- Standalone FWAIT");
197         FPU_ModifyCode(context, 0x90);
198
199 }
200
201
202
203 /**********************************************************************
204  *          INT_Int3eHandler (WPROCS.162)
205  *
206  * FLOATING POINT EMULATION -- Borland "Shortcut" call.
207  *  The two bytes following the int 3E instruction are
208  *  the subcode and a NOP ( 0x90 ), except for subcodes DC and DE
209  *  where the second byte is the register count.
210  *
211  *  Direct access 4.0 modifies and does not restore this vector.
212  *
213  */
214 void WINAPI INT_Int3eHandler(CONTEXT86 *context)
215 {
216         FIXME("Int 3E NOT Implemented");
217         INT_BARF(context, 0x3e);
218 }
219
220 /**********************************************************************
221  *          FPU_ModifyCode
222  *
223  *   This is the function that inserts the 0x9b fwait instruction
224  *   and the actual FPU opcode into the program.
225  *           -A.C.
226  *
227  *               Code thanks to Ove Kaaven
228  */
229 static void FPU_ModifyCode(CONTEXT86 *context, BYTE Opcode)
230 {
231   WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
232   BYTE *code =  CTX_SEG_OFF_TO_LIN(context, stack[1], stack[0]);
233
234 /*
235  * All *NIX systems should have a real or kernel emulated FPU.
236  */
237
238   code[-2] = 0x9b;          /* The fwait instruction */
239   code[-1] = Opcode;        /* Insert the opcode     */
240
241   if ( stack[0] < 2 ) FIXME("Backed up over a segment boundry in FPU code.");
242
243   stack[0] -= 2;             /* back up the return address 2 bytes */
244
245   TRACE("Modified code in FPU int call to 0x9b 0x%x",Opcode);
246 }