linux/arch/arm/kernel/opcodes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  linux/arch/arm/kernel/opcodes.c
   4 *
   5 *  A32 condition code lookup feature moved from nwfpe/fpopcode.c
   6 */
   7
   8#include <linux/module.h>
   9#include <asm/opcodes.h>
  10
  11#define ARM_OPCODE_CONDITION_UNCOND 0xf
  12
  13/*
  14 * condition code lookup table
  15 * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
  16 *
  17 * bit position in short is condition code: NZCV
  18 */
  19static const unsigned short cc_map[16] = {
  20        0xF0F0,                 /* EQ == Z set            */
  21        0x0F0F,                 /* NE                     */
  22        0xCCCC,                 /* CS == C set            */
  23        0x3333,                 /* CC                     */
  24        0xFF00,                 /* MI == N set            */
  25        0x00FF,                 /* PL                     */
  26        0xAAAA,                 /* VS == V set            */
  27        0x5555,                 /* VC                     */
  28        0x0C0C,                 /* HI == C set && Z clear */
  29        0xF3F3,                 /* LS == C clear || Z set */
  30        0xAA55,                 /* GE == (N==V)           */
  31        0x55AA,                 /* LT == (N!=V)           */
  32        0x0A05,                 /* GT == (!Z && (N==V))   */
  33        0xF5FA,                 /* LE == (Z || (N!=V))    */
  34        0xFFFF,                 /* AL always              */
  35        0                       /* NV                     */
  36};
  37
  38/*
  39 * Returns:
  40 * ARM_OPCODE_CONDTEST_FAIL   - if condition fails
  41 * ARM_OPCODE_CONDTEST_PASS   - if condition passes (including AL)
  42 * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
  43 *                              opcode space from v5 onwards
  44 *
  45 * Code that tests whether a conditional instruction would pass its condition
  46 * check should check that return value == ARM_OPCODE_CONDTEST_PASS.
  47 *
  48 * Code that tests if a condition means that the instruction would be executed
  49 * (regardless of conditional or unconditional) should instead check that the
  50 * return value != ARM_OPCODE_CONDTEST_FAIL.
  51 */
  52asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr)
  53{
  54        u32 cc_bits  = opcode >> 28;
  55        u32 psr_cond = psr >> 28;
  56        unsigned int ret;
  57
  58        if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
  59                if ((cc_map[cc_bits] >> (psr_cond)) & 1)
  60                        ret = ARM_OPCODE_CONDTEST_PASS;
  61                else
  62                        ret = ARM_OPCODE_CONDTEST_FAIL;
  63        } else {
  64                ret = ARM_OPCODE_CONDTEST_UNCOND;
  65        }
  66
  67        return ret;
  68}
  69EXPORT_SYMBOL_GPL(arm_check_condition);
  70