// SPDX-License-Identifier: GPL-2.0-only1/*2* linux/arch/arm/kernel/opcodes.c3*4* A32 condition code lookup feature moved from nwfpe/fpopcode.c5*/67#include <linux/module.h>8#include <asm/opcodes.h>910#define ARM_OPCODE_CONDITION_UNCOND 0xf1112/*13* condition code lookup table14* index into the table is test code: EQ, NE, ... LT, GT, AL, NV15*16* bit position in short is condition code: NZCV17*/18static const unsigned short cc_map[16] = {190xF0F0, /* EQ == Z set */200x0F0F, /* NE */210xCCCC, /* CS == C set */220x3333, /* CC */230xFF00, /* MI == N set */240x00FF, /* PL */250xAAAA, /* VS == V set */260x5555, /* VC */270x0C0C, /* HI == C set && Z clear */280xF3F3, /* LS == C clear || Z set */290xAA55, /* GE == (N==V) */300x55AA, /* LT == (N!=V) */310x0A05, /* GT == (!Z && (N==V)) */320xF5FA, /* LE == (Z || (N!=V)) */330xFFFF, /* AL always */340 /* NV */35};3637/*38* Returns:39* ARM_OPCODE_CONDTEST_FAIL - if condition fails40* ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL)41* ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional42* opcode space from v5 onwards43*44* Code that tests whether a conditional instruction would pass its condition45* check should check that return value == ARM_OPCODE_CONDTEST_PASS.46*47* Code that tests if a condition means that the instruction would be executed48* (regardless of conditional or unconditional) should instead check that the49* return value != ARM_OPCODE_CONDTEST_FAIL.50*/51asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr)52{53u32 cc_bits = opcode >> 28;54u32 psr_cond = psr >> 28;55unsigned int ret;5657if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {58if ((cc_map[cc_bits] >> (psr_cond)) & 1)59ret = ARM_OPCODE_CONDTEST_PASS;60else61ret = ARM_OPCODE_CONDTEST_FAIL;62} else {63ret = ARM_OPCODE_CONDTEST_UNCOND;64}6566return ret;67}68EXPORT_SYMBOL_GPL(arm_check_condition);697071