pio_disassembler.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <array>
  7. #include <sstream>
  8. #include <iomanip>
  9. #include "pio_disassembler.h"
  10. extern "C" void disassemble(char *buf, int buf_len, uint16_t inst, uint sideset_bits, bool sideset_opt) {
  11. if (buf_len) buf[disassemble(inst, sideset_bits, sideset_opt).copy(buf, buf_len - 1)] = 0;
  12. }
  13. std::string disassemble(uint16_t inst, uint sideset_bits_including_opt, bool sideset_opt) {
  14. std::stringstream ss;
  15. uint major = inst >> 13u;
  16. uint arg1 = ((uint) inst >> 5u) & 0x7u;
  17. uint arg2 = inst & 0x1fu;
  18. auto op = [&](const std::string &s) {
  19. ss << std::left << std::setw(7) << s;
  20. };
  21. auto op_guts = [&](const std::string &s) {
  22. ss << std::left << std::setw(16) << s;
  23. };
  24. bool invalid = false;
  25. switch (major) {
  26. case 0b000: {
  27. static std::array<std::string, 8> conditions{"", "!x, ", "x--, ", "!y, ", "y--, ", "x != y, ", "pin, ",
  28. "!osre, "};
  29. op("jmp");
  30. op_guts(conditions[arg1] + std::to_string(arg2));
  31. break;
  32. }
  33. case 0b001: {
  34. uint source = arg1 & 3u;
  35. std::string guts;
  36. switch (source) {
  37. case 0b00:
  38. guts = "gpio, " + std::to_string(arg2);
  39. break;
  40. case 0b01:
  41. guts = "pin, " + std::to_string(arg2);
  42. break;
  43. case 0b10:
  44. if (arg2 & 0x8u) {
  45. invalid = true;
  46. } else {
  47. guts = "irq, " + std::to_string(arg2 & 7u);
  48. if (arg2 & 0x10u) {
  49. guts += " rel";
  50. }
  51. }
  52. break;
  53. }
  54. if (!invalid) {
  55. guts = ((arg1 & 4u) ? "1 " : "0 ") + guts;
  56. op("wait");
  57. op_guts(guts);
  58. }
  59. break;
  60. }
  61. case 0b010: {
  62. static std::array<std::string, 8> sources { "pins", "x", "y", "null", "", "status", "isr", "osr"};
  63. std::string source = sources[arg1];
  64. if (source.empty()) {
  65. invalid = true;
  66. } else {
  67. op("in");
  68. op_guts(source + ", " + std::to_string(arg2 ? arg2 : 32));
  69. }
  70. break;
  71. }
  72. case 0b011: {
  73. static std::array<std::string, 8> dests { "pins", "x", "y", "null", "pindirs", "pc", "isr", "exec"};
  74. op("out");
  75. op_guts(dests[arg1] + ", " + std::to_string(arg2 ? arg2 : 32));
  76. break;
  77. }
  78. case 0b100: {
  79. if (arg2) {
  80. invalid = true;
  81. } else {
  82. std::string guts = "";
  83. if (arg1 & 4u) {
  84. op("pull");
  85. if (arg1 & 2u) guts = "ifempty";
  86. } else {
  87. op("push");
  88. if (arg1 & 2u) guts = "iffull";
  89. }
  90. guts += (arg1 & 0x1u) ? "block" : "noblock";
  91. op_guts(guts);
  92. }
  93. break;
  94. }
  95. case 0b101: {
  96. static std::array<std::string, 8> dests { "pins", "x", "y", "", "exec", "pc", "isr", "osr"};
  97. static std::array<std::string, 8> sources { "pins", "x", "y", "null", "", "status", "isr", "osr"};
  98. std::string dest = dests[arg1];
  99. std::string source = sources[arg2 & 7u];
  100. uint operation = arg2 >> 3u;
  101. if (source.empty() || dest.empty() || operation == 3) {
  102. invalid = true;
  103. }
  104. if (dest == source && !operation && (arg1 == 1 || arg2 == 2)) {
  105. op("nop");
  106. op_guts("");
  107. } else {
  108. op("mov");
  109. std::string guts = dest + ", ";
  110. if (operation == 1) {
  111. guts += "!";
  112. } else if (operation == 2) {
  113. guts += "::";
  114. }
  115. guts += source;
  116. op_guts(guts);
  117. }
  118. break;
  119. }
  120. case 0b110: {
  121. if ((arg1 & 0x4u) || (arg2 & 0x8u)) {
  122. invalid = true;
  123. } else {
  124. op("irq");
  125. std::string guts;
  126. if (arg1 & 0x2u) {
  127. guts += "clear ";
  128. } else if (arg1 & 0x1u) {
  129. guts += "wait ";
  130. } else {
  131. guts += "nowait ";
  132. }
  133. guts += std::to_string(arg2 & 7u);
  134. if (arg2 & 0x10u) {
  135. guts += " rel";
  136. }
  137. op_guts(guts);
  138. }
  139. break;
  140. }
  141. case 0b111: {
  142. static std::array<std::string, 8> dests{"pins", "x", "y", "", "pindirs", "", "", ""};
  143. std::string dest = dests[arg1];
  144. if (dest.empty()) {
  145. invalid = true;
  146. } else {
  147. op("set");
  148. op_guts(dests[arg1] + ", " + std::to_string(arg2));
  149. }
  150. break;
  151. }
  152. }
  153. if (invalid) {
  154. return "reserved";
  155. }
  156. uint delay = ((uint) inst >> 8u) & 0x1f;
  157. ss << std::left << std::setw(7);
  158. if (sideset_bits_including_opt && (!sideset_opt || (delay & 0x10u))) {
  159. ss << ("side "+ std::to_string((delay & (sideset_opt ? 0xfu : 0x1fu)) >> (5u - sideset_bits_including_opt)));
  160. } else {
  161. ss << "";
  162. }
  163. delay &= ((1u << (5 - sideset_bits_including_opt)) - 1u);
  164. ss << std::left << std::setw(4) << (delay ? ("[" + std::to_string(delay) + "]") : "");
  165. return ss.str();
  166. }