opstats.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include <assert.h>
  2. #include <stdbool.h>
  3. #include <stdint.h>
  4. #include "../codegen/codegen.h"
  5. #include "../shared.h"
  6. #if ENABLE_PROFILER_OPSTATS
  7. static struct {
  8. uint32_t opcode[0x100];
  9. uint32_t opcode_0f[0x100];
  10. } opstats_buffer = {
  11. .opcode = { 0 },
  12. .opcode_0f = { 0 },
  13. };
  14. #endif
  15. void gen_opstats(uint32_t instruction)
  16. {
  17. #if ENABLE_PROFILER_OPSTATS
  18. bool is_0f = false;
  19. for(int32_t i = 0; i < 4; i++)
  20. {
  21. int32_t opcode = instruction & 0xFF;
  22. instruction >>= 8;
  23. // TODO:
  24. // - If instruction depends on middle bits of modrm_byte, split
  25. // - Split depending on memory or register variant
  26. // - If the instruction uses 4 or more prefixes, only the prefixes will be counted
  27. if(is_0f)
  28. {
  29. gen_increment_mem32((int32_t)&opstats_buffer.opcode_0f[opcode]);
  30. break;
  31. }
  32. else
  33. {
  34. gen_increment_mem32((int32_t)&opstats_buffer.opcode[opcode]);
  35. if(opcode == 0x0F)
  36. {
  37. is_0f = true;
  38. }
  39. else if(opcode == 0x26 || opcode == 0x2E || opcode == 0x36 || opcode == 0x3E ||
  40. opcode == 0x64 || opcode == 0x65 || opcode == 0x66 || opcode == 0x67 ||
  41. opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3)
  42. {
  43. // prefix
  44. }
  45. else
  46. {
  47. break;
  48. }
  49. }
  50. }
  51. #else
  52. UNUSED(instruction);
  53. #endif
  54. }
  55. int32_t get_opstats_buffer(int32_t index)
  56. {
  57. assert(index >= 0 && index < 0x200);
  58. #if ENABLE_PROFILER_OPSTATS
  59. if(index < 0x100)
  60. {
  61. return opstats_buffer.opcode[index];
  62. }
  63. else
  64. {
  65. return opstats_buffer.opcode_0f[index - 0x100];
  66. }
  67. #else
  68. UNUSED(index);
  69. return 0;
  70. #endif
  71. }