iflag.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #ifndef NASM_IFLAG_H
  2. #define NASM_IFLAG_H
  3. #include "compiler.h"
  4. #include "ilog2.h"
  5. #include <string.h>
  6. #include "iflaggen.h"
  7. #define IF_GENBIT(bit) (UINT32_C(1) << (bit))
  8. static inline bool iflag_test(const iflag_t *f, unsigned int bit)
  9. {
  10. return !!(f->field[bit >> 5] & IF_GENBIT(bit & 31));
  11. }
  12. static inline void iflag_set(iflag_t *f, unsigned int bit)
  13. {
  14. f->field[bit >> 5] |= IF_GENBIT(bit & 31);
  15. }
  16. static inline void iflag_clear(iflag_t *f, unsigned int bit)
  17. {
  18. f->field[bit >> 5] &= ~IF_GENBIT(bit & 31);
  19. }
  20. static inline void iflag_clear_all(iflag_t *f)
  21. {
  22. memset(f, 0, sizeof(*f));
  23. }
  24. static inline void iflag_set_all(iflag_t *f)
  25. {
  26. memset(f, ~0, sizeof(*f));
  27. }
  28. #define iflag_for_each_field(v) for ((v) = 0; (v) < IF_FIELD_COUNT; (v)++)
  29. static inline int iflag_cmp(const iflag_t *a, const iflag_t *b)
  30. {
  31. int i;
  32. /* This is intentionally a reverse loop! */
  33. for (i = IF_FIELD_COUNT-1; i >= 0; i--) {
  34. if (a->field[i] == b->field[i])
  35. continue;
  36. return (int)(a->field[i] - b->field[i]);
  37. }
  38. return 0;
  39. }
  40. #define IF_GEN_HELPER(name, op) \
  41. static inline iflag_t iflag_##name(const iflag_t *a, const iflag_t *b) \
  42. { \
  43. unsigned int i; \
  44. iflag_t res; \
  45. \
  46. iflag_for_each_field(i) \
  47. res.field[i] = a->field[i] op b->field[i]; \
  48. \
  49. return res; \
  50. }
  51. IF_GEN_HELPER(xor, ^)
  52. /* Some helpers which are to work with predefined masks */
  53. #define IF_SMASK \
  54. (IF_GENBIT(IF_SB) |\
  55. IF_GENBIT(IF_SW) |\
  56. IF_GENBIT(IF_SD) |\
  57. IF_GENBIT(IF_SQ) |\
  58. IF_GENBIT(IF_SO) |\
  59. IF_GENBIT(IF_SY) |\
  60. IF_GENBIT(IF_SZ) |\
  61. IF_GENBIT(IF_SIZE))
  62. #define IF_ARMASK \
  63. (IF_GENBIT(IF_AR0) |\
  64. IF_GENBIT(IF_AR1) |\
  65. IF_GENBIT(IF_AR2) |\
  66. IF_GENBIT(IF_AR3) |\
  67. IF_GENBIT(IF_AR4))
  68. #define _itemp_smask(idx) (insns_flags[(idx)].field[0] & IF_SMASK)
  69. #define _itemp_armask(idx) (insns_flags[(idx)].field[0] & IF_ARMASK)
  70. #define _itemp_arg(idx) ((_itemp_armask(idx) >> IF_AR0) - 1)
  71. #define itemp_smask(itemp) _itemp_smask((itemp)->iflag_idx)
  72. #define itemp_arg(itemp) _itemp_arg((itemp)->iflag_idx)
  73. #define itemp_armask(itemp) _itemp_armask((itemp)->iflag_idx)
  74. /*
  75. * IF_8086 is the first CPU level flag and IF_PLEVEL the last
  76. */
  77. #if IF_8086 & 31
  78. #error "IF_8086 must be on a uint32_t boundary"
  79. #endif
  80. #define IF_PLEVEL IF_IA64
  81. #define IF_CPU_FIELD (IF_8086 >> 5)
  82. #define IF_CPU_LEVEL_MASK ((IF_GENBIT(IF_PLEVEL & 31) << 1) - 1)
  83. /*
  84. * IF_PRIV is the firstr instruction filtering flag
  85. */
  86. #if IF_PRIV & 31
  87. #error "IF_PRIV must be on a uint32_t boundary"
  88. #endif
  89. #define IF_FEATURE_FIELD (IF_PRIV >> 5)
  90. static inline int iflag_cmp_cpu(const iflag_t *a, const iflag_t *b)
  91. {
  92. return (int)(a->field[IF_CPU_FIELD] - b->field[IF_CPU_FIELD]);
  93. }
  94. static inline uint32_t _iflag_cpu_level(const iflag_t *a)
  95. {
  96. return a->field[IF_CPU_FIELD] & IF_CPU_LEVEL_MASK;
  97. }
  98. static inline int iflag_cmp_cpu_level(const iflag_t *a, const iflag_t *b)
  99. {
  100. uint32_t aa = _iflag_cpu_level(a);
  101. uint32_t bb = _iflag_cpu_level(b);
  102. return (int)(aa - bb);
  103. }
  104. /* Returns true if the CPU level is at least a certain value */
  105. static inline bool iflag_cpu_level_ok(const iflag_t *a, unsigned int bit)
  106. {
  107. return _iflag_cpu_level(a) >= IF_GENBIT(bit & 31);
  108. }
  109. static inline void iflag_set_all_features(iflag_t *a)
  110. {
  111. size_t i;
  112. for (i = IF_FEATURE_FIELD; i < IF_CPU_FIELD; i++)
  113. a->field[i] = ~UINT32_C(0);
  114. }
  115. static inline void iflag_set_cpu(iflag_t *a, unsigned int cpu)
  116. {
  117. a->field[0] = 0; /* Not applicable to the CPU type */
  118. iflag_set_all_features(a); /* All feature masking bits set for now */
  119. a->field[IF_CPU_FIELD] &= ~IF_CPU_LEVEL_MASK;
  120. iflag_set(a, cpu);
  121. }
  122. static inline void iflag_set_default_cpu(iflag_t *a)
  123. {
  124. iflag_set_cpu(a, IF_PLEVEL);
  125. }
  126. static inline iflag_t _iflag_pfmask(const iflag_t *a)
  127. {
  128. iflag_t r;
  129. iflag_clear_all(&r);
  130. if (iflag_test(a, IF_CYRIX))
  131. iflag_set(&r, IF_CYRIX);
  132. if (iflag_test(a, IF_AMD))
  133. iflag_set(&r, IF_AMD);
  134. return r;
  135. }
  136. #define iflag_pfmask(itemp) _iflag_pfmask(&insns_flags[(itemp)->iflag_idx])
  137. #endif /* NASM_IFLAG_H */