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