formatIII.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. MSP430 Emulator
  3. Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)
  4. "MSP430 Emulator" is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. "MSP430 Emulator" is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. //##########+++ Decode Format III Instructions +++#########
  16. //# Format III are jump instructions of the form:
  17. //# [001C][CCXX][XXXX][XXXX]
  18. //#
  19. //# Where C = Condition, X = 10-bit signed offset
  20. //#
  21. //########################################################
  22. #include "decoder.h"
  23. void decode_formatIII(Emulator *emu, uint16_t instruction, bool disassemble)
  24. {
  25. Cpu *cpu = emu->cpu;
  26. Debugger *debugger = emu->debugger;
  27. uint8_t condition = (instruction & 0x1C00) >> 10;
  28. int16_t signed_offset = (instruction & 0x03FF) * 2;
  29. bool negative = signed_offset >> 9;
  30. char value[20];
  31. char mnemonic[100] = {0};
  32. /* String to show hex value of instruction */
  33. char hex_str[100] = {0};
  34. sprintf(hex_str, "%04X", instruction);
  35. if (negative) { /* Sign Extend for Arithmetic Operations */
  36. signed_offset |= 0xF800;
  37. }
  38. if (!disassemble) {
  39. switch(condition){
  40. /* JNE/JNZ Jump if not equal/zero
  41. *
  42. * If Z = 0: PC + 2 offset → PC
  43. * If Z = 1: execute following instruction
  44. */
  45. case 0x0:{
  46. if (cpu->sr.zero == false) {
  47. cpu->pc += signed_offset;
  48. }
  49. break;
  50. }
  51. /* JEQ/JZ Jump is equal/zero
  52. * If Z = 1: PC + 2 offset → PC
  53. * If Z = 0: execute following instruction
  54. */
  55. case 0x1:{
  56. if (cpu->sr.zero == true) {
  57. cpu->pc += signed_offset;
  58. }
  59. break;
  60. }
  61. /* JNC/JLO Jump if no carry/lower
  62. *
  63. * if C = 0: PC + 2 offset → PC
  64. * if C = 1: execute following instruction
  65. */
  66. case 0x2:{
  67. if (cpu->sr.carry == false) {
  68. cpu->pc += signed_offset;
  69. }
  70. break;
  71. }
  72. /* JC/JHS Jump if carry/higher or same
  73. *
  74. * If C = 1: PC + 2 offset → PC
  75. * If C = 0: execute following instruction
  76. */
  77. case 0x3:{
  78. if (cpu->sr.carry == true) {
  79. cpu->pc += signed_offset;
  80. }
  81. break;
  82. }
  83. /* JN Jump if negative
  84. *
  85. * if N = 1: PC + 2 ×offset → PC
  86. * if N = 0: execute following instruction
  87. */
  88. case 0x4:{
  89. if (cpu->sr.negative == true) {
  90. cpu->pc += signed_offset;
  91. }
  92. break;
  93. }
  94. /* JGE Jump if greater or equal (N == V)
  95. *
  96. * If (N .XOR. V) = 0 then jump to label: PC + 2 P offset → PC
  97. * If (N .XOR. V) = 1 then execute the following instruction
  98. */
  99. case 0x5:{
  100. if ((cpu->sr.negative ^ cpu->sr.overflow) == false) {
  101. cpu->pc += signed_offset;
  102. }
  103. break;
  104. }
  105. /* JL Jump if less (N != V)
  106. *
  107. * If (N .XOR. V) = 1 then jump to label: PC + 2 offset → PC
  108. * If (N .XOR. V) = 0 then execute following instruction
  109. */
  110. case 0x6:{
  111. if ((cpu->sr.negative ^ cpu->sr.overflow) == true) {
  112. cpu->pc += signed_offset;
  113. }
  114. break;
  115. }
  116. /* JMP Jump Unconditionally
  117. *
  118. * PC + 2 × offset → PC
  119. *
  120. */
  121. case 0x7:{
  122. cpu->pc += signed_offset;
  123. break;
  124. }
  125. default:{
  126. puts("Undefined Jump operation!\n");
  127. return;
  128. }
  129. } //# End of Switch
  130. } //# end if
  131. else {
  132. switch(condition){
  133. case 0x0:{
  134. sprintf(mnemonic, "JNZ");
  135. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  136. break;
  137. }
  138. case 0x1:{
  139. sprintf(mnemonic, "JZ");
  140. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  141. break;
  142. }
  143. case 0x2:{
  144. sprintf(mnemonic, "JNC");
  145. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  146. break;
  147. }
  148. case 0x3:{
  149. sprintf(mnemonic, "JC");
  150. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  151. break;
  152. }
  153. case 0x4:{
  154. sprintf(mnemonic, "JN");
  155. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  156. break;
  157. }
  158. case 0x5:{
  159. sprintf(mnemonic, "JGE");
  160. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  161. break;
  162. }
  163. case 0x6:{
  164. sprintf(mnemonic, "JL");
  165. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  166. break;
  167. }
  168. case 0x7:{
  169. sprintf(mnemonic, "JMP");
  170. sprintf(value, "0x%04X", cpu->pc + signed_offset);
  171. break;
  172. }
  173. default:{
  174. puts("Undefined Jump operation!\n");
  175. return;
  176. }
  177. } //# End of Switch
  178. strncat(mnemonic, "\t", sizeof(mnemonic));
  179. strncat(mnemonic, value, sizeof(mnemonic));
  180. strncat(mnemonic, "\n", sizeof(mnemonic));
  181. if (disassemble && emu->debugger->debug_mode) {
  182. int i;
  183. char one = 0, two = 0;
  184. // Make little endian big endian
  185. for (i = 0;i < strlen(hex_str);i += 4) {
  186. one = hex_str[i];
  187. two = hex_str[i + 1];
  188. hex_str[i] = hex_str[i + 2];
  189. hex_str[i + 1] = hex_str[i + 3];
  190. hex_str[i + 2] = one;
  191. hex_str[i + 3] = two;
  192. }
  193. printf("%s", hex_str);
  194. print_console(emu, hex_str);
  195. for (i = strlen(hex_str);i < 12;i++) {
  196. printf(" ");
  197. print_console(emu, " ");
  198. }
  199. printf("\t%s", mnemonic);
  200. print_console(emu, "\t");
  201. print_console(emu, mnemonic);
  202. }
  203. }
  204. }