|
1 /* |
|
2 NetWinder Floating Point Emulator |
|
3 (c) Rebel.COM, 1998,1999 |
|
4 |
|
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org> |
|
6 |
|
7 This program is free software; you can redistribute it and/or modify |
|
8 it under the terms of the GNU General Public License as published by |
|
9 the Free Software Foundation; either version 2 of the License, or |
|
10 (at your option) any later version. |
|
11 |
|
12 This program is distributed in the hope that it will be useful, |
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 GNU General Public License for more details. |
|
16 |
|
17 You should have received a copy of the GNU General Public License |
|
18 along with this program; if not, write to the Free Software |
|
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
20 */ |
|
21 |
|
22 #ifndef __FPOPCODE_H__ |
|
23 #define __FPOPCODE_H__ |
|
24 |
|
25 /* |
|
26 ARM Floating Point Instruction Classes |
|
27 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
28 |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT |
|
29 |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|0|1| o f f s e t | CPDT |
|
30 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
31 |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO |
|
32 |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT |
|
33 |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons |
|
34 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
35 |
|
36 CPDT data transfer instructions |
|
37 LDF, STF, LFM, SFM |
|
38 |
|
39 CPDO dyadic arithmetic instructions |
|
40 ADF, MUF, SUF, RSF, DVF, RDF, |
|
41 POW, RPW, RMF, FML, FDV, FRD, POL |
|
42 |
|
43 CPDO monadic arithmetic instructions |
|
44 MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP, |
|
45 SIN, COS, TAN, ASN, ACS, ATN, URD, NRM |
|
46 |
|
47 CPRT joint arithmetic/data transfer instructions |
|
48 FIX (arithmetic followed by load/store) |
|
49 FLT (load/store followed by arithmetic) |
|
50 CMF, CNF CMFE, CNFE (comparisons) |
|
51 WFS, RFS (write/read floating point status register) |
|
52 WFC, RFC (write/read floating point control register) |
|
53 |
|
54 cond condition codes |
|
55 P pre/post index bit: 0 = postindex, 1 = preindex |
|
56 U up/down bit: 0 = stack grows down, 1 = stack grows up |
|
57 W write back bit: 1 = update base register (Rn) |
|
58 L load/store bit: 0 = store, 1 = load |
|
59 Rn base register |
|
60 Rd destination/source register |
|
61 Fd floating point destination register |
|
62 Fn floating point source register |
|
63 Fm floating point source register or floating point constant |
|
64 |
|
65 uv transfer length (TABLE 1) |
|
66 wx register count (TABLE 2) |
|
67 abcd arithmetic opcode (TABLES 3 & 4) |
|
68 ef destination size (rounding precision) (TABLE 5) |
|
69 gh rounding mode (TABLE 6) |
|
70 j dyadic/monadic bit: 0 = dyadic, 1 = monadic |
|
71 i constant bit: 1 = constant (TABLE 6) |
|
72 */ |
|
73 |
|
74 /* |
|
75 TABLE 1 |
|
76 +-------------------------+---+---+---------+---------+ |
|
77 | Precision | u | v | FPSR.EP | length | |
|
78 +-------------------------+---+---+---------+---------+ |
|
79 | Single | 0 ü 0 | x | 1 words | |
|
80 | Double | 1 ü 1 | x | 2 words | |
|
81 | Extended | 1 ü 1 | x | 3 words | |
|
82 | Packed decimal | 1 ü 1 | 0 | 3 words | |
|
83 | Expanded packed decimal | 1 ü 1 | 1 | 4 words | |
|
84 +-------------------------+---+---+---------+---------+ |
|
85 Note: x = don't care |
|
86 */ |
|
87 |
|
88 /* |
|
89 TABLE 2 |
|
90 +---+---+---------------------------------+ |
|
91 | w | x | Number of registers to transfer | |
|
92 +---+---+---------------------------------+ |
|
93 | 0 ü 1 | 1 | |
|
94 | 1 ü 0 | 2 | |
|
95 | 1 ü 1 | 3 | |
|
96 | 0 ü 0 | 4 | |
|
97 +---+---+---------------------------------+ |
|
98 */ |
|
99 |
|
100 /* |
|
101 TABLE 3: Dyadic Floating Point Opcodes |
|
102 +---+---+---+---+----------+-----------------------+-----------------------+ |
|
103 | a | b | c | d | Mnemonic | Description | Operation | |
|
104 +---+---+---+---+----------+-----------------------+-----------------------+ |
|
105 | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm | |
|
106 | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm | |
|
107 | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm | |
|
108 | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn | |
|
109 | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm | |
|
110 | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn | |
|
111 | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm | |
|
112 | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn | |
|
113 | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) | |
|
114 | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm | |
|
115 | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm | |
|
116 | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn | |
|
117 | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) | |
|
118 | 1 | 1 | 0 | 1 | | undefined instruction | trap | |
|
119 | 1 | 1 | 1 | 0 | | undefined instruction | trap | |
|
120 | 1 | 1 | 1 | 1 | | undefined instruction | trap | |
|
121 +---+---+---+---+----------+-----------------------+-----------------------+ |
|
122 Note: POW, RPW, POL are deprecated, and are available for backwards |
|
123 compatibility only. |
|
124 */ |
|
125 |
|
126 /* |
|
127 TABLE 4: Monadic Floating Point Opcodes |
|
128 +---+---+---+---+----------+-----------------------+-----------------------+ |
|
129 | a | b | c | d | Mnemonic | Description | Operation | |
|
130 +---+---+---+---+----------+-----------------------+-----------------------+ |
|
131 | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm | |
|
132 | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm | |
|
133 | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) | |
|
134 | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) | |
|
135 | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) | |
|
136 | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) | |
|
137 | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) | |
|
138 | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm | |
|
139 | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) | |
|
140 | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) | |
|
141 | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) | |
|
142 | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) | |
|
143 | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) | |
|
144 | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) | |
|
145 | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) | |
|
146 | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) | |
|
147 +---+---+---+---+----------+-----------------------+-----------------------+ |
|
148 Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are |
|
149 available for backwards compatibility only. |
|
150 */ |
|
151 |
|
152 /* |
|
153 TABLE 5 |
|
154 +-------------------------+---+---+ |
|
155 | Rounding Precision | e | f | |
|
156 +-------------------------+---+---+ |
|
157 | IEEE Single precision | 0 ü 0 | |
|
158 | IEEE Double precision | 0 ü 1 | |
|
159 | IEEE Extended precision | 1 ü 0 | |
|
160 | undefined (trap) | 1 ü 1 | |
|
161 +-------------------------+---+---+ |
|
162 */ |
|
163 |
|
164 /* |
|
165 TABLE 5 |
|
166 +---------------------------------+---+---+ |
|
167 | Rounding Mode | g | h | |
|
168 +---------------------------------+---+---+ |
|
169 | Round to nearest (default) | 0 ü 0 | |
|
170 | Round toward plus infinity | 0 ü 1 | |
|
171 | Round toward negative infinity | 1 ü 0 | |
|
172 | Round toward zero | 1 ü 1 | |
|
173 +---------------------------------+---+---+ |
|
174 */ |
|
175 |
|
176 /* |
|
177 === |
|
178 === Definitions for load and store instructions |
|
179 === |
|
180 */ |
|
181 |
|
182 /* bit masks */ |
|
183 #define BIT_PREINDEX 0x01000000 |
|
184 #define BIT_UP 0x00800000 |
|
185 #define BIT_WRITE_BACK 0x00200000 |
|
186 #define BIT_LOAD 0x00100000 |
|
187 |
|
188 /* masks for load/store */ |
|
189 #define MASK_CPDT 0x0c000000 /* data processing opcode */ |
|
190 #define MASK_OFFSET 0x000000ff |
|
191 #define MASK_TRANSFER_LENGTH 0x00408000 |
|
192 #define MASK_REGISTER_COUNT MASK_TRANSFER_LENGTH |
|
193 #define MASK_COPROCESSOR 0x00000f00 |
|
194 |
|
195 /* Tests for transfer length */ |
|
196 #define TRANSFER_SINGLE 0x00000000 |
|
197 #define TRANSFER_DOUBLE 0x00008000 |
|
198 #define TRANSFER_EXTENDED 0x00400000 |
|
199 #define TRANSFER_PACKED MASK_TRANSFER_LENGTH |
|
200 |
|
201 /* Get the coprocessor number from the opcode. */ |
|
202 #define getCoprocessorNumber(opcode) ((opcode & MASK_COPROCESSOR) >> 8) |
|
203 |
|
204 /* Get the offset from the opcode. */ |
|
205 #define getOffset(opcode) (opcode & MASK_OFFSET) |
|
206 |
|
207 /* Tests for specific data transfer load/store opcodes. */ |
|
208 #define TEST_OPCODE(opcode,mask) (((opcode) & (mask)) == (mask)) |
|
209 |
|
210 #define LOAD_OP(opcode) TEST_OPCODE((opcode),MASK_CPDT | BIT_LOAD) |
|
211 #define STORE_OP(opcode) ((opcode & (MASK_CPDT | BIT_LOAD)) == MASK_CPDT) |
|
212 |
|
213 #define LDF_OP(opcode) (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 1)) |
|
214 #define LFM_OP(opcode) (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 2)) |
|
215 #define STF_OP(opcode) (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 1)) |
|
216 #define SFM_OP(opcode) (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 2)) |
|
217 |
|
218 #define PREINDEXED(opcode) ((opcode & BIT_PREINDEX) != 0) |
|
219 #define POSTINDEXED(opcode) ((opcode & BIT_PREINDEX) == 0) |
|
220 #define BIT_UP_SET(opcode) ((opcode & BIT_UP) != 0) |
|
221 #define BIT_UP_CLEAR(opcode) ((opcode & BIT_DOWN) == 0) |
|
222 #define WRITE_BACK(opcode) ((opcode & BIT_WRITE_BACK) != 0) |
|
223 #define LOAD(opcode) ((opcode & BIT_LOAD) != 0) |
|
224 #define STORE(opcode) ((opcode & BIT_LOAD) == 0) |
|
225 |
|
226 /* |
|
227 === |
|
228 === Definitions for arithmetic instructions |
|
229 === |
|
230 */ |
|
231 /* bit masks */ |
|
232 #define BIT_MONADIC 0x00008000 |
|
233 #define BIT_CONSTANT 0x00000008 |
|
234 |
|
235 #define CONSTANT_FM(opcode) ((opcode & BIT_CONSTANT) != 0) |
|
236 #define MONADIC_INSTRUCTION(opcode) ((opcode & BIT_MONADIC) != 0) |
|
237 |
|
238 /* instruction identification masks */ |
|
239 #define MASK_CPDO 0x0e000000 /* arithmetic opcode */ |
|
240 #define MASK_ARITHMETIC_OPCODE 0x00f08000 |
|
241 #define MASK_DESTINATION_SIZE 0x00080080 |
|
242 |
|
243 /* dyadic arithmetic opcodes. */ |
|
244 #define ADF_CODE 0x00000000 |
|
245 #define MUF_CODE 0x00100000 |
|
246 #define SUF_CODE 0x00200000 |
|
247 #define RSF_CODE 0x00300000 |
|
248 #define DVF_CODE 0x00400000 |
|
249 #define RDF_CODE 0x00500000 |
|
250 #define POW_CODE 0x00600000 |
|
251 #define RPW_CODE 0x00700000 |
|
252 #define RMF_CODE 0x00800000 |
|
253 #define FML_CODE 0x00900000 |
|
254 #define FDV_CODE 0x00a00000 |
|
255 #define FRD_CODE 0x00b00000 |
|
256 #define POL_CODE 0x00c00000 |
|
257 /* 0x00d00000 is an invalid dyadic arithmetic opcode */ |
|
258 /* 0x00e00000 is an invalid dyadic arithmetic opcode */ |
|
259 /* 0x00f00000 is an invalid dyadic arithmetic opcode */ |
|
260 |
|
261 /* monadic arithmetic opcodes. */ |
|
262 #define MVF_CODE 0x00008000 |
|
263 #define MNF_CODE 0x00108000 |
|
264 #define ABS_CODE 0x00208000 |
|
265 #define RND_CODE 0x00308000 |
|
266 #define SQT_CODE 0x00408000 |
|
267 #define LOG_CODE 0x00508000 |
|
268 #define LGN_CODE 0x00608000 |
|
269 #define EXP_CODE 0x00708000 |
|
270 #define SIN_CODE 0x00808000 |
|
271 #define COS_CODE 0x00908000 |
|
272 #define TAN_CODE 0x00a08000 |
|
273 #define ASN_CODE 0x00b08000 |
|
274 #define ACS_CODE 0x00c08000 |
|
275 #define ATN_CODE 0x00d08000 |
|
276 #define URD_CODE 0x00e08000 |
|
277 #define NRM_CODE 0x00f08000 |
|
278 |
|
279 /* |
|
280 === |
|
281 === Definitions for register transfer and comparison instructions |
|
282 === |
|
283 */ |
|
284 |
|
285 #define MASK_CPRT 0x0e000010 /* register transfer opcode */ |
|
286 #define MASK_CPRT_CODE 0x00f00000 |
|
287 #define FLT_CODE 0x00000000 |
|
288 #define FIX_CODE 0x00100000 |
|
289 #define WFS_CODE 0x00200000 |
|
290 #define RFS_CODE 0x00300000 |
|
291 #define WFC_CODE 0x00400000 |
|
292 #define RFC_CODE 0x00500000 |
|
293 #define CMF_CODE 0x00900000 |
|
294 #define CNF_CODE 0x00b00000 |
|
295 #define CMFE_CODE 0x00d00000 |
|
296 #define CNFE_CODE 0x00f00000 |
|
297 |
|
298 /* |
|
299 === |
|
300 === Common definitions |
|
301 === |
|
302 */ |
|
303 |
|
304 /* register masks */ |
|
305 #define MASK_Rd 0x0000f000 |
|
306 #define MASK_Rn 0x000f0000 |
|
307 #define MASK_Fd 0x00007000 |
|
308 #define MASK_Fm 0x00000007 |
|
309 #define MASK_Fn 0x00070000 |
|
310 |
|
311 /* condition code masks */ |
|
312 #define CC_MASK 0xf0000000 |
|
313 #define CC_NEGATIVE 0x80000000 |
|
314 #define CC_ZERO 0x40000000 |
|
315 #define CC_CARRY 0x20000000 |
|
316 #define CC_OVERFLOW 0x10000000 |
|
317 #define CC_EQ 0x00000000 |
|
318 #define CC_NE 0x10000000 |
|
319 #define CC_CS 0x20000000 |
|
320 #define CC_HS CC_CS |
|
321 #define CC_CC 0x30000000 |
|
322 #define CC_LO CC_CC |
|
323 #define CC_MI 0x40000000 |
|
324 #define CC_PL 0x50000000 |
|
325 #define CC_VS 0x60000000 |
|
326 #define CC_VC 0x70000000 |
|
327 #define CC_HI 0x80000000 |
|
328 #define CC_LS 0x90000000 |
|
329 #define CC_GE 0xa0000000 |
|
330 #define CC_LT 0xb0000000 |
|
331 #define CC_GT 0xc0000000 |
|
332 #define CC_LE 0xd0000000 |
|
333 #define CC_AL 0xe0000000 |
|
334 #define CC_NV 0xf0000000 |
|
335 |
|
336 /* rounding masks/values */ |
|
337 #define MASK_ROUNDING_MODE 0x00000060 |
|
338 #define ROUND_TO_NEAREST 0x00000000 |
|
339 #define ROUND_TO_PLUS_INFINITY 0x00000020 |
|
340 #define ROUND_TO_MINUS_INFINITY 0x00000040 |
|
341 #define ROUND_TO_ZERO 0x00000060 |
|
342 |
|
343 #define MASK_ROUNDING_PRECISION 0x00080080 |
|
344 #define ROUND_SINGLE 0x00000000 |
|
345 #define ROUND_DOUBLE 0x00000080 |
|
346 #define ROUND_EXTENDED 0x00080000 |
|
347 |
|
348 /* Get the condition code from the opcode. */ |
|
349 #define getCondition(opcode) (opcode >> 28) |
|
350 |
|
351 /* Get the source register from the opcode. */ |
|
352 #define getRn(opcode) ((opcode & MASK_Rn) >> 16) |
|
353 |
|
354 /* Get the destination floating point register from the opcode. */ |
|
355 #define getFd(opcode) ((opcode & MASK_Fd) >> 12) |
|
356 |
|
357 /* Get the first source floating point register from the opcode. */ |
|
358 #define getFn(opcode) ((opcode & MASK_Fn) >> 16) |
|
359 |
|
360 /* Get the second source floating point register from the opcode. */ |
|
361 #define getFm(opcode) (opcode & MASK_Fm) |
|
362 |
|
363 /* Get the destination register from the opcode. */ |
|
364 #define getRd(opcode) ((opcode & MASK_Rd) >> 12) |
|
365 |
|
366 /* Get the rounding mode from the opcode. */ |
|
367 #define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5) |
|
368 |
|
369 static inline floatx80 getExtendedConstant(const unsigned int nIndex) |
|
370 { |
|
371 extern const floatx80 floatx80Constant[]; |
|
372 return floatx80Constant[nIndex]; |
|
373 } |
|
374 |
|
375 static inline float64 getDoubleConstant(const unsigned int nIndex) |
|
376 { |
|
377 extern const float64 float64Constant[]; |
|
378 return float64Constant[nIndex]; |
|
379 } |
|
380 |
|
381 static inline float32 getSingleConstant(const unsigned int nIndex) |
|
382 { |
|
383 extern const float32 float32Constant[]; |
|
384 return float32Constant[nIndex]; |
|
385 } |
|
386 |
|
387 extern unsigned int getRegisterCount(const unsigned int opcode); |
|
388 extern unsigned int getDestinationSize(const unsigned int opcode); |
|
389 |
|
390 #endif |