opcodes.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. #include <linux/module.h>
  11. #include <asm/opcodes.h>
  12. #define ARM_OPCODE_CONDITION_UNCOND 0xf
  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. */
  19. static 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. * Returns:
  39. * ARM_OPCODE_CONDTEST_FAIL - if condition fails
  40. * ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL)
  41. * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
  42. * opcode space from v5 onwards
  43. *
  44. * Code that tests whether a conditional instruction would pass its condition
  45. * check should check that return value == ARM_OPCODE_CONDTEST_PASS.
  46. *
  47. * Code that tests if a condition means that the instruction would be executed
  48. * (regardless of conditional or unconditional) should instead check that the
  49. * return value != ARM_OPCODE_CONDTEST_FAIL.
  50. */
  51. asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr)
  52. {
  53. u32 cc_bits = opcode >> 28;
  54. u32 psr_cond = psr >> 28;
  55. unsigned int ret;
  56. if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
  57. if ((cc_map[cc_bits] >> (psr_cond)) & 1)
  58. ret = ARM_OPCODE_CONDTEST_PASS;
  59. else
  60. ret = ARM_OPCODE_CONDTEST_FAIL;
  61. } else {
  62. ret = ARM_OPCODE_CONDTEST_UNCOND;
  63. }
  64. return ret;
  65. }
  66. EXPORT_SYMBOL_GPL(arm_check_condition);