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