iflag.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #ifndef NASM_IFLAG_H
  2. #define NASM_IFLAG_H
  3. #include "compiler.h"
  4. #include "ilog2.h"
  5. #include "iflaggen.h"
  6. #define IF_GENBIT(bit) (UINT32_C(1) << ((bit) & 31))
  7. static inline int ifcomp(uint32_t a, uint32_t b)
  8. {
  9. return (a > b) - (a < b);
  10. }
  11. static inline bool iflag_test(const iflag_t *f, unsigned int bit)
  12. {
  13. return !!(f->field[bit >> 5] & IF_GENBIT(bit));
  14. }
  15. static inline void iflag_set(iflag_t *f, unsigned int bit)
  16. {
  17. f->field[bit >> 5] |= IF_GENBIT(bit);
  18. }
  19. static inline void iflag_clear(iflag_t *f, unsigned int bit)
  20. {
  21. f->field[bit >> 5] &= ~IF_GENBIT(bit);
  22. }
  23. static inline void iflag_clear_all(iflag_t *f)
  24. {
  25. memset(f, 0, sizeof(*f));
  26. }
  27. static inline void iflag_set_all(iflag_t *f)
  28. {
  29. memset(f, ~0, sizeof(*f));
  30. }
  31. #define iflag_for_each_field(v) for ((v) = 0; (v) < IF_FIELD_COUNT; (v)++)
  32. static inline int iflag_cmp(const iflag_t *a, const iflag_t *b)
  33. {
  34. int i;
  35. /* This is intentionally a reverse loop! */
  36. for (i = IF_FIELD_COUNT-1; i >= 0; i--) {
  37. if (a->field[i] == b->field[i])
  38. continue;
  39. return ifcomp(a->field[i], b->field[i]);
  40. }
  41. return 0;
  42. }
  43. #define IF_GEN_HELPER(name, op) \
  44. static inline iflag_t iflag_##name(const iflag_t *a, const iflag_t *b) \
  45. { \
  46. unsigned int i; \
  47. iflag_t res; \
  48. \
  49. iflag_for_each_field(i) \
  50. res.field[i] = a->field[i] op b->field[i]; \
  51. \
  52. return res; \
  53. }
  54. IF_GEN_HELPER(xor, ^)
  55. /* Some helpers which are to work with predefined masks */
  56. #define IF_SMASK (IFM_SB|IFM_SW|IFM_SD|IFM_SQ|IFM_SO|IFM_SY|IFM_SZ|IFM_SIZE|IFM_ANYSIZE)
  57. #define IF_ARMASK (IFM_AR0|IFM_AR1|IFM_AR2|IFM_AR3|IFM_AR4)
  58. #define _itemp_smask(idx) (insns_flags[(idx)].field[0] & IF_SMASK)
  59. #define _itemp_armask(idx) (insns_flags[(idx)].field[0] & IF_ARMASK)
  60. #define _itemp_arg(idx) ((_itemp_armask(idx) >> IF_AR0) - 1)
  61. #define itemp_smask(itemp) _itemp_smask((itemp)->iflag_idx)
  62. #define itemp_arg(itemp) _itemp_arg((itemp)->iflag_idx)
  63. #define itemp_armask(itemp) _itemp_armask((itemp)->iflag_idx)
  64. /*
  65. * IF_ANY is the highest CPU level by definition
  66. */
  67. #define IF_PLEVEL IF_ANY /* Default CPU level */
  68. #define IF_CPU_LEVEL_MASK ((IFM_ANY << 1) - 1)
  69. static inline int iflag_cmp_cpu(const iflag_t *a, const iflag_t *b)
  70. {
  71. return ifcomp(a->field[IF_CPU_FIELD], b->field[IF_CPU_FIELD]);
  72. }
  73. static inline uint32_t _iflag_cpu_level(const iflag_t *a)
  74. {
  75. return a->field[IF_CPU_FIELD] & IF_CPU_LEVEL_MASK;
  76. }
  77. static inline int iflag_cmp_cpu_level(const iflag_t *a, const iflag_t *b)
  78. {
  79. return ifcomp(_iflag_cpu_level(a), _iflag_cpu_level(b));
  80. }
  81. /* Returns true if the CPU level is at least a certain value */
  82. static inline bool iflag_cpu_level_ok(const iflag_t *a, unsigned int bit)
  83. {
  84. return _iflag_cpu_level(a) >= IF_GENBIT(bit);
  85. }
  86. static inline void iflag_set_all_features(iflag_t *a)
  87. {
  88. uint32_t *p = &a->field[IF_FEATURE_FIELD];
  89. memset(p, -1, IF_FEATURE_NFIELDS * sizeof(uint32_t));
  90. }
  91. static inline void iflag_set_cpu(iflag_t *a, unsigned int cpu)
  92. {
  93. a->field[0] = 0; /* Not applicable to the CPU type */
  94. iflag_set_all_features(a); /* All feature masking bits set for now */
  95. a->field[IF_CPU_FIELD] &= ~IF_CPU_LEVEL_MASK;
  96. iflag_set(a, cpu);
  97. }
  98. static inline void iflag_set_default_cpu(iflag_t *a)
  99. {
  100. iflag_set_cpu(a, IF_PLEVEL);
  101. }
  102. static inline iflag_t _iflag_pfmask(const iflag_t *a)
  103. {
  104. iflag_t r;
  105. iflag_clear_all(&r);
  106. if (iflag_test(a, IF_CYRIX))
  107. iflag_set(&r, IF_CYRIX);
  108. if (iflag_test(a, IF_AMD))
  109. iflag_set(&r, IF_AMD);
  110. return r;
  111. }
  112. #define iflag_pfmask(itemp) _iflag_pfmask(&insns_flags[(itemp)->iflag_idx])
  113. #endif /* NASM_IFLAG_H */