Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003     NetWinder Floating Point Emulator
0004     (c) Rebel.COM, 1998,1999
0005     (c) Philip Blundell, 2001
0006 
0007     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
0008 
0009 */
0010 
0011 #ifndef __FPOPCODE_H__
0012 #define __FPOPCODE_H__
0013 
0014 
0015 /*
0016 ARM Floating Point Instruction Classes
0017 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 
0018 |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
0019 |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)
0020 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 
0021 |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
0022 |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
0023 |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
0024 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 
0025 
0026 CPDT        data transfer instructions
0027         LDF, STF, LFM (copro 2), SFM (copro 2)
0028         
0029 CPDO        dyadic arithmetic instructions
0030         ADF, MUF, SUF, RSF, DVF, RDF,
0031         POW, RPW, RMF, FML, FDV, FRD, POL
0032 
0033 CPDO        monadic arithmetic instructions
0034         MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
0035         SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
0036         
0037 CPRT        joint arithmetic/data transfer instructions
0038         FIX (arithmetic followed by load/store)
0039         FLT (load/store followed by arithmetic)
0040         CMF, CNF CMFE, CNFE (comparisons)
0041         WFS, RFS (write/read floating point status register)
0042         WFC, RFC (write/read floating point control register)
0043 
0044 cond        condition codes
0045 P       pre/post index bit: 0 = postindex, 1 = preindex
0046 U       up/down bit: 0 = stack grows down, 1 = stack grows up
0047 W       write back bit: 1 = update base register (Rn)
0048 L       load/store bit: 0 = store, 1 = load
0049 Rn      base register
0050 Rd      destination/source register     
0051 Fd      floating point destination register
0052 Fn      floating point source register
0053 Fm      floating point source register or floating point constant
0054 
0055 uv      transfer length (TABLE 1)
0056 wx      register count (TABLE 2)
0057 abcd        arithmetic opcode (TABLES 3 & 4)
0058 ef      destination size (rounding precision) (TABLE 5)
0059 gh      rounding mode (TABLE 6)
0060 j       dyadic/monadic bit: 0 = dyadic, 1 = monadic
0061 i       constant bit: 1 = constant (TABLE 6)
0062 */
0063 
0064 /*
0065 TABLE 1
0066 +-------------------------+---+---+---------+---------+
0067 |  Precision              | u | v | FPSR.EP | length  |
0068 +-------------------------+---+---+---------+---------+
0069 | Single                  | 0 | 0 |    x    | 1 words |
0070 | Double                  | 1 | 1 |    x    | 2 words |
0071 | Extended                | 1 | 1 |    x    | 3 words |
0072 | Packed decimal          | 1 | 1 |    0    | 3 words |
0073 | Expanded packed decimal | 1 | 1 |    1    | 4 words |
0074 +-------------------------+---+---+---------+---------+
0075 Note: x = don't care
0076 */
0077 
0078 /*
0079 TABLE 2
0080 +---+---+---------------------------------+
0081 | w | x | Number of registers to transfer |
0082 +---+---+---------------------------------+
0083 | 0 | 1 |  1                              |
0084 | 1 | 0 |  2                              |
0085 | 1 | 1 |  3                              |
0086 | 0 | 0 |  4                              |
0087 +---+---+---------------------------------+
0088 */
0089 
0090 /*
0091 TABLE 3: Dyadic Floating Point Opcodes
0092 +---+---+---+---+----------+-----------------------+-----------------------+
0093 | a | b | c | d | Mnemonic | Description           | Operation             |
0094 +---+---+---+---+----------+-----------------------+-----------------------+
0095 | 0 | 0 | 0 | 0 | ADF      | Add                   | Fd := Fn + Fm         |
0096 | 0 | 0 | 0 | 1 | MUF      | Multiply              | Fd := Fn * Fm         |
0097 | 0 | 0 | 1 | 0 | SUF      | Subtract              | Fd := Fn - Fm         |
0098 | 0 | 0 | 1 | 1 | RSF      | Reverse subtract      | Fd := Fm - Fn         |
0099 | 0 | 1 | 0 | 0 | DVF      | Divide                | Fd := Fn / Fm         |
0100 | 0 | 1 | 0 | 1 | RDF      | Reverse divide        | Fd := Fm / Fn         |
0101 | 0 | 1 | 1 | 0 | POW      | Power                 | Fd := Fn ^ Fm         |
0102 | 0 | 1 | 1 | 1 | RPW      | Reverse power         | Fd := Fm ^ Fn         |
0103 | 1 | 0 | 0 | 0 | RMF      | Remainder             | Fd := IEEE rem(Fn/Fm) |
0104 | 1 | 0 | 0 | 1 | FML      | Fast Multiply         | Fd := Fn * Fm         |
0105 | 1 | 0 | 1 | 0 | FDV      | Fast Divide           | Fd := Fn / Fm         |
0106 | 1 | 0 | 1 | 1 | FRD      | Fast reverse divide   | Fd := Fm / Fn         |
0107 | 1 | 1 | 0 | 0 | POL      | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm)  |
0108 | 1 | 1 | 0 | 1 |          | undefined instruction | trap                  |
0109 | 1 | 1 | 1 | 0 |          | undefined instruction | trap                  |
0110 | 1 | 1 | 1 | 1 |          | undefined instruction | trap                  |
0111 +---+---+---+---+----------+-----------------------+-----------------------+
0112 Note: POW, RPW, POL are deprecated, and are available for backwards
0113       compatibility only.
0114 */
0115 
0116 /*
0117 TABLE 4: Monadic Floating Point Opcodes
0118 +---+---+---+---+----------+-----------------------+-----------------------+
0119 | a | b | c | d | Mnemonic | Description           | Operation             |
0120 +---+---+---+---+----------+-----------------------+-----------------------+
0121 | 0 | 0 | 0 | 0 | MVF      | Move                  | Fd := Fm              |
0122 | 0 | 0 | 0 | 1 | MNF      | Move negated          | Fd := - Fm            |
0123 | 0 | 0 | 1 | 0 | ABS      | Absolute value        | Fd := abs(Fm)         |
0124 | 0 | 0 | 1 | 1 | RND      | Round to integer      | Fd := int(Fm)         |
0125 | 0 | 1 | 0 | 0 | SQT      | Square root           | Fd := sqrt(Fm)        |
0126 | 0 | 1 | 0 | 1 | LOG      | Log base 10           | Fd := log10(Fm)       |
0127 | 0 | 1 | 1 | 0 | LGN      | Log base e            | Fd := ln(Fm)          |
0128 | 0 | 1 | 1 | 1 | EXP      | Exponent              | Fd := e ^ Fm          |
0129 | 1 | 0 | 0 | 0 | SIN      | Sine                  | Fd := sin(Fm)         |
0130 | 1 | 0 | 0 | 1 | COS      | Cosine                | Fd := cos(Fm)         |
0131 | 1 | 0 | 1 | 0 | TAN      | Tangent               | Fd := tan(Fm)         |
0132 | 1 | 0 | 1 | 1 | ASN      | Arc Sine              | Fd := arcsin(Fm)      |
0133 | 1 | 1 | 0 | 0 | ACS      | Arc Cosine            | Fd := arccos(Fm)      |
0134 | 1 | 1 | 0 | 1 | ATN      | Arc Tangent           | Fd := arctan(Fm)      |
0135 | 1 | 1 | 1 | 0 | URD      | Unnormalized round    | Fd := int(Fm)         |
0136 | 1 | 1 | 1 | 1 | NRM      | Normalize             | Fd := norm(Fm)        |
0137 +---+---+---+---+----------+-----------------------+-----------------------+
0138 Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
0139       available for backwards compatibility only.
0140 */
0141 
0142 /*
0143 TABLE 5
0144 +-------------------------+---+---+
0145 |  Rounding Precision     | e | f |
0146 +-------------------------+---+---+
0147 | IEEE Single precision   | 0 | 0 |
0148 | IEEE Double precision   | 0 | 1 |
0149 | IEEE Extended precision | 1 | 0 |
0150 | undefined (trap)        | 1 | 1 |
0151 +-------------------------+---+---+
0152 */
0153 
0154 /*
0155 TABLE 5
0156 +---------------------------------+---+---+
0157 |  Rounding Mode                  | g | h |
0158 +---------------------------------+---+---+
0159 | Round to nearest (default)      | 0 | 0 |
0160 | Round toward plus infinity      | 0 | 1 |
0161 | Round toward negative infinity  | 1 | 0 |
0162 | Round toward zero               | 1 | 1 |
0163 +---------------------------------+---+---+
0164 */
0165 
0166 /*
0167 ===
0168 === Definitions for load and store instructions
0169 ===
0170 */
0171 
0172 /* bit masks */
0173 #define BIT_PREINDEX    0x01000000
0174 #define BIT_UP      0x00800000
0175 #define BIT_WRITE_BACK  0x00200000
0176 #define BIT_LOAD    0x00100000
0177 
0178 /* masks for load/store */
0179 #define MASK_CPDT       0x0c000000  /* data processing opcode */
0180 #define MASK_OFFSET     0x000000ff
0181 #define MASK_TRANSFER_LENGTH    0x00408000
0182 #define MASK_REGISTER_COUNT MASK_TRANSFER_LENGTH
0183 #define MASK_COPROCESSOR    0x00000f00
0184 
0185 /* Tests for transfer length */
0186 #define TRANSFER_SINGLE     0x00000000
0187 #define TRANSFER_DOUBLE     0x00008000
0188 #define TRANSFER_EXTENDED   0x00400000
0189 #define TRANSFER_PACKED     MASK_TRANSFER_LENGTH
0190 
0191 /* Get the coprocessor number from the opcode. */
0192 #define getCoprocessorNumber(opcode)    ((opcode & MASK_COPROCESSOR) >> 8)
0193 
0194 /* Get the offset from the opcode. */
0195 #define getOffset(opcode)       (opcode & MASK_OFFSET)
0196 
0197 /* Tests for specific data transfer load/store opcodes. */
0198 #define TEST_OPCODE(opcode,mask)    (((opcode) & (mask)) == (mask))
0199 
0200 #define LOAD_OP(opcode)   TEST_OPCODE((opcode),MASK_CPDT | BIT_LOAD)
0201 #define STORE_OP(opcode)  ((opcode & (MASK_CPDT | BIT_LOAD)) == MASK_CPDT)
0202 
0203 #define LDF_OP(opcode)  (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 1))
0204 #define LFM_OP(opcode)  (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 2))
0205 #define STF_OP(opcode)  (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 1))
0206 #define SFM_OP(opcode)  (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 2))
0207 
0208 #define PREINDEXED(opcode)      ((opcode & BIT_PREINDEX) != 0)
0209 #define POSTINDEXED(opcode)     ((opcode & BIT_PREINDEX) == 0)
0210 #define BIT_UP_SET(opcode)      ((opcode & BIT_UP) != 0)
0211 #define BIT_UP_CLEAR(opcode)        ((opcode & BIT_DOWN) == 0)
0212 #define WRITE_BACK(opcode)      ((opcode & BIT_WRITE_BACK) != 0)
0213 #define LOAD(opcode)            ((opcode & BIT_LOAD) != 0)
0214 #define STORE(opcode)           ((opcode & BIT_LOAD) == 0)
0215 
0216 /*
0217 ===
0218 === Definitions for arithmetic instructions
0219 ===
0220 */
0221 /* bit masks */
0222 #define BIT_MONADIC 0x00008000
0223 #define BIT_CONSTANT    0x00000008
0224 
0225 #define CONSTANT_FM(opcode)     ((opcode & BIT_CONSTANT) != 0)
0226 #define MONADIC_INSTRUCTION(opcode) ((opcode & BIT_MONADIC) != 0)
0227 
0228 /* instruction identification masks */
0229 #define MASK_CPDO       0x0e000000  /* arithmetic opcode */
0230 #define MASK_ARITHMETIC_OPCODE  0x00f08000
0231 #define MASK_DESTINATION_SIZE   0x00080080
0232 
0233 /* dyadic arithmetic opcodes. */
0234 #define ADF_CODE    0x00000000
0235 #define MUF_CODE    0x00100000
0236 #define SUF_CODE    0x00200000
0237 #define RSF_CODE    0x00300000
0238 #define DVF_CODE    0x00400000
0239 #define RDF_CODE    0x00500000
0240 #define POW_CODE    0x00600000
0241 #define RPW_CODE    0x00700000
0242 #define RMF_CODE    0x00800000
0243 #define FML_CODE    0x00900000
0244 #define FDV_CODE    0x00a00000
0245 #define FRD_CODE    0x00b00000
0246 #define POL_CODE    0x00c00000
0247 /* 0x00d00000 is an invalid dyadic arithmetic opcode */
0248 /* 0x00e00000 is an invalid dyadic arithmetic opcode */
0249 /* 0x00f00000 is an invalid dyadic arithmetic opcode */
0250 
0251 /* monadic arithmetic opcodes. */
0252 #define MVF_CODE    0x00008000
0253 #define MNF_CODE    0x00108000
0254 #define ABS_CODE    0x00208000
0255 #define RND_CODE    0x00308000
0256 #define SQT_CODE    0x00408000
0257 #define LOG_CODE    0x00508000
0258 #define LGN_CODE    0x00608000
0259 #define EXP_CODE    0x00708000
0260 #define SIN_CODE    0x00808000
0261 #define COS_CODE    0x00908000
0262 #define TAN_CODE    0x00a08000
0263 #define ASN_CODE    0x00b08000
0264 #define ACS_CODE    0x00c08000
0265 #define ATN_CODE    0x00d08000
0266 #define URD_CODE    0x00e08000
0267 #define NRM_CODE    0x00f08000
0268 
0269 /*
0270 ===
0271 === Definitions for register transfer and comparison instructions
0272 ===
0273 */
0274 
0275 #define MASK_CPRT       0x0e000010  /* register transfer opcode */
0276 #define MASK_CPRT_CODE      0x00f00000
0277 #define FLT_CODE        0x00000000
0278 #define FIX_CODE        0x00100000
0279 #define WFS_CODE        0x00200000
0280 #define RFS_CODE        0x00300000
0281 #define WFC_CODE        0x00400000
0282 #define RFC_CODE        0x00500000
0283 #define CMF_CODE        0x00900000
0284 #define CNF_CODE        0x00b00000
0285 #define CMFE_CODE       0x00d00000
0286 #define CNFE_CODE       0x00f00000
0287 
0288 /*
0289 ===
0290 === Common definitions
0291 ===
0292 */
0293 
0294 /* register masks */
0295 #define MASK_Rd     0x0000f000
0296 #define MASK_Rn     0x000f0000
0297 #define MASK_Fd     0x00007000
0298 #define MASK_Fm     0x00000007
0299 #define MASK_Fn     0x00070000
0300 
0301 /* condition code masks */
0302 #define CC_MASK     0xf0000000
0303 #define CC_NEGATIVE 0x80000000
0304 #define CC_ZERO     0x40000000
0305 #define CC_CARRY    0x20000000
0306 #define CC_OVERFLOW 0x10000000
0307 #define CC_EQ       0x00000000
0308 #define CC_NE       0x10000000
0309 #define CC_CS       0x20000000
0310 #define CC_HS       CC_CS
0311 #define CC_CC       0x30000000
0312 #define CC_LO       CC_CC
0313 #define CC_MI       0x40000000
0314 #define CC_PL       0x50000000
0315 #define CC_VS       0x60000000
0316 #define CC_VC       0x70000000
0317 #define CC_HI       0x80000000
0318 #define CC_LS       0x90000000
0319 #define CC_GE       0xa0000000
0320 #define CC_LT       0xb0000000
0321 #define CC_GT       0xc0000000
0322 #define CC_LE       0xd0000000
0323 #define CC_AL       0xe0000000
0324 #define CC_NV       0xf0000000
0325 
0326 /* rounding masks/values */
0327 #define MASK_ROUNDING_MODE  0x00000060
0328 #define ROUND_TO_NEAREST    0x00000000
0329 #define ROUND_TO_PLUS_INFINITY  0x00000020
0330 #define ROUND_TO_MINUS_INFINITY 0x00000040
0331 #define ROUND_TO_ZERO       0x00000060
0332 
0333 #define MASK_ROUNDING_PRECISION 0x00080080
0334 #define ROUND_SINGLE        0x00000000
0335 #define ROUND_DOUBLE        0x00000080
0336 #define ROUND_EXTENDED      0x00080000
0337 
0338 /* Get the condition code from the opcode. */
0339 #define getCondition(opcode)        (opcode >> 28)
0340 
0341 /* Get the source register from the opcode. */
0342 #define getRn(opcode)           ((opcode & MASK_Rn) >> 16)
0343 
0344 /* Get the destination floating point register from the opcode. */
0345 #define getFd(opcode)           ((opcode & MASK_Fd) >> 12)
0346 
0347 /* Get the first source floating point register from the opcode. */
0348 #define getFn(opcode)       ((opcode & MASK_Fn) >> 16)
0349 
0350 /* Get the second source floating point register from the opcode. */
0351 #define getFm(opcode)       (opcode & MASK_Fm)
0352 
0353 /* Get the destination register from the opcode. */
0354 #define getRd(opcode)       ((opcode & MASK_Rd) >> 12)
0355 
0356 /* Get the rounding mode from the opcode. */
0357 #define getRoundingMode(opcode)     ((opcode & MASK_ROUNDING_MODE) >> 5)
0358 
0359 #ifdef CONFIG_FPE_NWFPE_XP
0360 static inline floatx80 __pure getExtendedConstant(const unsigned int nIndex)
0361 {
0362     extern const floatx80 floatx80Constant[];
0363     return floatx80Constant[nIndex];
0364 }
0365 #endif
0366 
0367 static inline float64 __pure getDoubleConstant(const unsigned int nIndex)
0368 {
0369     extern const float64 float64Constant[];
0370     return float64Constant[nIndex];
0371 }
0372 
0373 static inline float32 __pure getSingleConstant(const unsigned int nIndex)
0374 {
0375     extern const float32 float32Constant[];
0376     return float32Constant[nIndex];
0377 }
0378 
0379 static inline unsigned int getTransferLength(const unsigned int opcode)
0380 {
0381     unsigned int nRc;
0382 
0383     switch (opcode & MASK_TRANSFER_LENGTH) {
0384     case 0x00000000:
0385         nRc = 1;
0386         break;      /* single precision */
0387     case 0x00008000:
0388         nRc = 2;
0389         break;      /* double precision */
0390     case 0x00400000:
0391         nRc = 3;
0392         break;      /* extended precision */
0393     default:
0394         nRc = 0;
0395     }
0396 
0397     return (nRc);
0398 }
0399 
0400 static inline unsigned int getRegisterCount(const unsigned int opcode)
0401 {
0402     unsigned int nRc;
0403 
0404     switch (opcode & MASK_REGISTER_COUNT) {
0405     case 0x00000000:
0406         nRc = 4;
0407         break;
0408     case 0x00008000:
0409         nRc = 1;
0410         break;
0411     case 0x00400000:
0412         nRc = 2;
0413         break;
0414     case 0x00408000:
0415         nRc = 3;
0416         break;
0417     default:
0418         nRc = 0;
0419     }
0420 
0421     return (nRc);
0422 }
0423 
0424 static inline unsigned int getRoundingPrecision(const unsigned int opcode)
0425 {
0426     unsigned int nRc;
0427 
0428     switch (opcode & MASK_ROUNDING_PRECISION) {
0429     case 0x00000000:
0430         nRc = 1;
0431         break;
0432     case 0x00000080:
0433         nRc = 2;
0434         break;
0435     case 0x00080000:
0436         nRc = 3;
0437         break;
0438     default:
0439         nRc = 0;
0440     }
0441 
0442     return (nRc);
0443 }
0444 
0445 static inline unsigned int getDestinationSize(const unsigned int opcode)
0446 {
0447     unsigned int nRc;
0448 
0449     switch (opcode & MASK_DESTINATION_SIZE) {
0450     case 0x00000000:
0451         nRc = typeSingle;
0452         break;
0453     case 0x00000080:
0454         nRc = typeDouble;
0455         break;
0456     case 0x00080000:
0457         nRc = typeExtended;
0458         break;
0459     default:
0460         nRc = typeNone;
0461     }
0462 
0463     return (nRc);
0464 }
0465 
0466 extern const float64 float64Constant[];
0467 extern const float32 float32Constant[];
0468 
0469 #endif