Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/kernel/opcodes.c
0004  *
0005  *  A32 condition code lookup feature moved from nwfpe/fpopcode.c
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <asm/opcodes.h>
0010 
0011 #define ARM_OPCODE_CONDITION_UNCOND 0xf
0012 
0013 /*
0014  * condition code lookup table
0015  * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
0016  *
0017  * bit position in short is condition code: NZCV
0018  */
0019 static const unsigned short cc_map[16] = {
0020     0xF0F0,         /* EQ == Z set            */
0021     0x0F0F,         /* NE                     */
0022     0xCCCC,         /* CS == C set            */
0023     0x3333,         /* CC                     */
0024     0xFF00,         /* MI == N set            */
0025     0x00FF,         /* PL                     */
0026     0xAAAA,         /* VS == V set            */
0027     0x5555,         /* VC                     */
0028     0x0C0C,         /* HI == C set && Z clear */
0029     0xF3F3,         /* LS == C clear || Z set */
0030     0xAA55,         /* GE == (N==V)           */
0031     0x55AA,         /* LT == (N!=V)           */
0032     0x0A05,         /* GT == (!Z && (N==V))   */
0033     0xF5FA,         /* LE == (Z || (N!=V))    */
0034     0xFFFF,         /* AL always              */
0035     0           /* NV                     */
0036 };
0037 
0038 /*
0039  * Returns:
0040  * ARM_OPCODE_CONDTEST_FAIL   - if condition fails
0041  * ARM_OPCODE_CONDTEST_PASS   - if condition passes (including AL)
0042  * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
0043  *                              opcode space from v5 onwards
0044  *
0045  * Code that tests whether a conditional instruction would pass its condition
0046  * check should check that return value == ARM_OPCODE_CONDTEST_PASS.
0047  *
0048  * Code that tests if a condition means that the instruction would be executed
0049  * (regardless of conditional or unconditional) should instead check that the
0050  * return value != ARM_OPCODE_CONDTEST_FAIL.
0051  */
0052 asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr)
0053 {
0054     u32 cc_bits  = opcode >> 28;
0055     u32 psr_cond = psr >> 28;
0056     unsigned int ret;
0057 
0058     if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
0059         if ((cc_map[cc_bits] >> (psr_cond)) & 1)
0060             ret = ARM_OPCODE_CONDTEST_PASS;
0061         else
0062             ret = ARM_OPCODE_CONDTEST_FAIL;
0063     } else {
0064         ret = ARM_OPCODE_CONDTEST_UNCOND;
0065     }
0066 
0067     return ret;
0068 }
0069 EXPORT_SYMBOL_GPL(arm_check_condition);