linux/arch/arm/kernel/opcodes.c
Thomas Gleixner d2912cb15b treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
Based on 2 normalized pattern(s):

  this program is free software you can redistribute it and or modify
  it under the terms of the gnu general public license version 2 as
  published by the free software foundation

  this program is free software you can redistribute it and or modify
  it under the terms of the gnu general public license version 2 as
  published by the free software foundation #

extracted by the scancode license scanner the SPDX license identifier

  GPL-2.0-only

has been chosen to replace the boilerplate/reference in 4122 file(s).

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Enrico Weigelt <info@metux.net>
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Allison Randal <allison@lohutok.net>
Cc: linux-spdx@vger.kernel.org
Link: https://lkml.kernel.org/r/20190604081206.933168790@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-06-19 17:09:55 +02:00

70 lines
2.1 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/arch/arm/kernel/opcodes.c
*
* A32 condition code lookup feature moved from nwfpe/fpopcode.c
*/
#include <linux/module.h>
#include <asm/opcodes.h>
#define ARM_OPCODE_CONDITION_UNCOND 0xf
/*
* condition code lookup table
* index into the table is test code: EQ, NE, ... LT, GT, AL, NV
*
* bit position in short is condition code: NZCV
*/
static const unsigned short cc_map[16] = {
0xF0F0, /* EQ == Z set */
0x0F0F, /* NE */
0xCCCC, /* CS == C set */
0x3333, /* CC */
0xFF00, /* MI == N set */
0x00FF, /* PL */
0xAAAA, /* VS == V set */
0x5555, /* VC */
0x0C0C, /* HI == C set && Z clear */
0xF3F3, /* LS == C clear || Z set */
0xAA55, /* GE == (N==V) */
0x55AA, /* LT == (N!=V) */
0x0A05, /* GT == (!Z && (N==V)) */
0xF5FA, /* LE == (Z || (N!=V)) */
0xFFFF, /* AL always */
0 /* NV */
};
/*
* Returns:
* ARM_OPCODE_CONDTEST_FAIL - if condition fails
* ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL)
* ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
* opcode space from v5 onwards
*
* Code that tests whether a conditional instruction would pass its condition
* check should check that return value == ARM_OPCODE_CONDTEST_PASS.
*
* Code that tests if a condition means that the instruction would be executed
* (regardless of conditional or unconditional) should instead check that the
* return value != ARM_OPCODE_CONDTEST_FAIL.
*/
asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr)
{
u32 cc_bits = opcode >> 28;
u32 psr_cond = psr >> 28;
unsigned int ret;
if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
if ((cc_map[cc_bits] >> (psr_cond)) & 1)
ret = ARM_OPCODE_CONDTEST_PASS;
else
ret = ARM_OPCODE_CONDTEST_FAIL;
} else {
ret = ARM_OPCODE_CONDTEST_UNCOND;
}
return ret;
}
EXPORT_SYMBOL_GPL(arm_check_condition);