formatI.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  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 I Instructions +++##########
  16. //# Format I are double operand of the form:
  17. //# [CCCC][SSSS][ABaa][DDDD]
  18. //#
  19. //# Where C = Opcode, B = Byte/Word flag,
  20. //# A = Addressing mode for destination
  21. //# a = Addressing mode for s_reg_name
  22. //# S = S_Reg_Name, D = Destination
  23. //########################################################
  24. #include "formatI.h"
  25. void decode_formatI(Emulator *emu, uint16_t instruction, bool disassemble)
  26. {
  27. Cpu *cpu = emu->cpu;
  28. Debugger *debugger = emu->debugger;
  29. uint8_t opcode = (instruction & 0xF000) >> 12;
  30. uint8_t source = (instruction & 0x0F00) >> 8;
  31. uint8_t as_flag = (instruction & 0x0030) >> 4;
  32. uint8_t destination = (instruction & 0x000F);
  33. uint8_t ad_flag = (instruction & 0x0080) >> 7;
  34. uint8_t bw_flag = (instruction & 0x0040) >> 6;
  35. char s_reg_name[10], d_reg_name[10];
  36. char mnemonic[100] = {0};
  37. /* String to show hex value of instruction */
  38. char hex_str[100] = {0};
  39. char hex_str_part[10] = {0};
  40. sprintf(hex_str, "%04X", instruction);
  41. /* Source Register pointer */
  42. int16_t *s_reg = get_reg_ptr(emu, source);
  43. /* Destination Register pointer */
  44. int16_t *d_reg = get_reg_ptr(emu, destination);
  45. reg_num_to_name(source, s_reg_name); /* Get source register name */
  46. reg_num_to_name(destination, d_reg_name); /* Get destination register name */
  47. uint8_t constant_generator_active = 0; /* Specifies if CG1/CG2 active */
  48. int16_t immediate_constant = 0; /* Generated Constant */
  49. /* Spot CG1 and CG2 Constant generator instructions */
  50. if ( (source == 2 && as_flag > 1) || source == 3 ) {
  51. constant_generator_active = 1;
  52. immediate_constant = run_constant_generator(source, as_flag);
  53. }
  54. else {
  55. constant_generator_active = 0;
  56. }
  57. /* Identify the nature of instruction operand addressing modes */
  58. int16_t source_value, source_offset;
  59. int16_t destination_offset;
  60. uint16_t *destination_addr;
  61. char asm_operands[21] = {0}, asm_op2[20] = {0};
  62. /* Register - Register; Ex: MOV Rs, Rd */
  63. /* Constant Gen - Register; Ex: MOV #C, Rd */ /* 0 */
  64. if (as_flag == 0 && ad_flag == 0) {
  65. if (constant_generator_active) { /* Source Constant */
  66. source_value = immediate_constant;
  67. sprintf(asm_operands, "#0x%04X, %s",
  68. (uint16_t) source_value, d_reg_name);
  69. }
  70. else { /* Source register */
  71. source_value = *s_reg;
  72. sprintf(asm_operands, "%s, %s", s_reg_name, d_reg_name);
  73. }
  74. destination_addr = (uint16_t *)d_reg; // Destination Register
  75. if (!disassemble) {
  76. bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0;
  77. }
  78. }
  79. /* Register - Indexed; Ex: MOV Rs, 0x0(Rd) */
  80. /* Register - Symbolic; Ex: MOV Rs, 0xD */
  81. /* Register - Absolute; Ex: MOV Rs, &0xD */
  82. /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* 0 */
  83. /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* 0 */
  84. /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* 0 */
  85. else if (as_flag == 0 && ad_flag == 1) {
  86. destination_offset = fetch(emu);
  87. sprintf(hex_str_part, "%04X", (uint16_t) destination_offset);
  88. strncat(hex_str, hex_str_part, sizeof hex_str);
  89. destination_addr = get_addr_ptr(*d_reg + destination_offset);
  90. if (constant_generator_active) { /* Source Constant */
  91. source_value = immediate_constant;
  92. sprintf(asm_operands, "#0x%04X, ", source_value);
  93. }
  94. else { /* Source from register */
  95. source_value = *s_reg;
  96. sprintf(asm_operands, "%s, ", s_reg_name);
  97. }
  98. if (destination == 0) { /* Destination Symbolic */
  99. uint16_t virtual_addr = *d_reg + destination_offset - 2;
  100. destination_addr = get_addr_ptr(virtual_addr);
  101. sprintf(asm_op2, "0x%04X", (uint16_t) virtual_addr);
  102. }
  103. else if (destination == 2) { /* Destination Absolute */
  104. destination_addr = get_addr_ptr(destination_offset);
  105. sprintf(asm_op2, "&0x%04X", (uint16_t) destination_offset);
  106. }
  107. else { /* Destination Indexed */
  108. sprintf(asm_op2, "0x%04X(%s)",
  109. (uint16_t) destination_offset, d_reg_name);
  110. }
  111. strncat(asm_operands, asm_op2, sizeof asm_op2);
  112. }
  113. /* Indexed - Register; Ex: MOV 0x0(Rs), Rd */
  114. /* Symbolic - Register; Ex: MOV 0xS, Rd */
  115. /* Absolute - Register; Ex: MOV &0xS, Rd */
  116. /* Constant Gen - Register; Ex: MOV #C, Rd */ /* 1 */
  117. else if (as_flag == 1 && ad_flag == 0) {
  118. if (constant_generator_active) { /* Source Constant */
  119. source_value = immediate_constant;
  120. sprintf(asm_operands, "#0x%04X, %s", source_value, d_reg_name);
  121. }
  122. else if (source == 0) { /* Source Symbolic */
  123. source_offset = fetch(emu);
  124. uint16_t virtual_addr = *s_reg + source_offset - 2;
  125. source_value = *get_addr_ptr(virtual_addr);
  126. sprintf(hex_str_part, "%04X", (uint16_t) source_offset);
  127. strncat(hex_str, hex_str_part, sizeof hex_str);
  128. sprintf(asm_operands, "0x%04X, %s", virtual_addr, d_reg_name);
  129. }
  130. else if (source == 2) { /* Source Absolute */
  131. source_offset = fetch(emu);
  132. source_value = *get_addr_ptr(source_offset);
  133. sprintf(hex_str_part, "%04X", (uint16_t) source_offset);
  134. strncat(hex_str, hex_str_part, sizeof hex_str);
  135. sprintf(asm_operands, "&0x%04X, %s",
  136. (uint16_t) source_offset, d_reg_name);
  137. }
  138. else { /* Source Indexed */
  139. source_offset = fetch(emu);
  140. source_value = *get_addr_ptr(*s_reg + source_offset);
  141. sprintf(hex_str_part, "%04X", (uint16_t) source_offset);
  142. strncat(hex_str, hex_str_part, sizeof hex_str);
  143. sprintf(asm_operands, "0x%04X(%s), %s",
  144. (uint16_t) source_offset, s_reg_name, d_reg_name);
  145. }
  146. destination_addr = (uint16_t *)d_reg; /* Destination register */
  147. if (!disassemble) {
  148. bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0;
  149. }
  150. }
  151. /* Indexed - Indexed; Ex: MOV 0x0(Rs), 0x0(Rd) */
  152. /* Symbolic - Indexed; Ex: MOV 0xS, 0x0(Rd) */
  153. /* Indexed - Symbolic; Ex: MOV 0x0(Rd), 0xD */
  154. /* Symbolic - Symbolic; Ex: MOV 0xS, 0xD */
  155. /* Absolute - Indexed; Ex: MOV &0xS, 0x0(Rd) */
  156. /* Indexed - Absolute; Ex: MOV 0x0(Rs), &0xD */
  157. /* Absolute - Absolute; Ex: MOV &0xS, &0xD */
  158. /* Absolute - Symbolic; Ex: MOV &0xS, 0xD */
  159. /* Symbolic - Absolute; Ex: MOV 0xS, &0xD */
  160. /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* 1 */
  161. /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* 1 */
  162. /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* 1 */
  163. else if (as_flag == 1 && ad_flag == 1) {
  164. if (constant_generator_active) { /* Source Constant */
  165. source_value = immediate_constant;
  166. sprintf(asm_operands, "#0x%04X, ", source_value);
  167. }
  168. else if (source == 0) { /* Source Symbolic */
  169. source_offset = fetch(emu);
  170. uint16_t virtual_addr = cpu->pc + source_offset - 4;
  171. source_value = *get_addr_ptr(virtual_addr);
  172. sprintf(hex_str_part, "%04X", (uint16_t) source_offset);
  173. strncat(hex_str, hex_str_part, sizeof hex_str);
  174. sprintf(asm_operands, "0x%04X, ", virtual_addr);
  175. }
  176. else if (source == 2) { /* Source Absolute */
  177. source_offset = fetch(emu);
  178. source_value = *get_addr_ptr(source_offset);
  179. sprintf(hex_str_part, "%04X", (uint16_t) source_offset);
  180. strncat(hex_str, hex_str_part, sizeof hex_str);
  181. sprintf(asm_operands, "&0x%04X, ", (uint16_t) source_offset);
  182. }
  183. else { /* Source Indexed */
  184. source_offset = fetch(emu);
  185. source_value = *get_addr_ptr(*s_reg + source_offset);
  186. sprintf(hex_str_part, "%04X", (uint16_t)source_offset);
  187. strncat(hex_str, hex_str_part, sizeof hex_str);
  188. sprintf(asm_operands, "0x%04X(%s), ",
  189. (uint16_t) source_offset, s_reg_name);
  190. }
  191. destination_offset = fetch(emu);
  192. sprintf(hex_str_part, "%04X", (uint16_t) destination_offset);
  193. strncat(hex_str, hex_str_part, sizeof hex_str);
  194. if (destination == 0) { /* Destination Symbolic */
  195. uint16_t virtual_addr = cpu->pc + destination_offset - 2;
  196. destination_addr = get_addr_ptr(virtual_addr);
  197. sprintf(asm_op2, "0x%04X", virtual_addr);
  198. }
  199. else if (destination == 2) { /* Destination Absolute */
  200. destination_addr = get_addr_ptr(destination_offset);
  201. sprintf(asm_op2, "&0x%04X", (uint16_t) destination_offset);
  202. }
  203. else { /* Destination indexed */
  204. destination_addr = get_addr_ptr(*d_reg + destination_offset);
  205. sprintf(asm_op2, "0x%04X(%s)", (uint16_t)destination_offset, d_reg_name);
  206. }
  207. strncat(asm_operands, asm_op2, sizeof asm_op2);
  208. }
  209. /* Indirect - Register; Ex: MOV @Rs, Rd */
  210. /* Constant Gen - Register; Ex: MOV #C, Rd */ /* 2, 4 */
  211. else if (as_flag == 2 && ad_flag == 0) {
  212. if (constant_generator_active) { /* Source Constant */
  213. source_value = immediate_constant;
  214. sprintf(asm_operands, "#0x%04X, %s", immediate_constant, d_reg_name);
  215. }
  216. else { /* Source Indirect */
  217. source_value = *get_addr_ptr(*s_reg);
  218. sprintf(asm_operands, "@%s, %s", s_reg_name, d_reg_name);
  219. }
  220. destination_addr = (uint16_t*)d_reg; /* Destination Register */
  221. if (!disassemble) {
  222. bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0;
  223. }
  224. }
  225. /* Indirect - Indexed; Ex: MOV @Rs, 0x0(Rd) */
  226. /* Indirect - Symbolic; Ex: MOV @Rs, 0xD */
  227. /* Indirect - Absolute; Ex: MOV @Rs, &0xD */
  228. /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* 2, 4 */
  229. /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* 2, 4 */
  230. /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* 2, 4 */
  231. else if (as_flag == 2 && ad_flag == 1) {
  232. destination_offset = fetch(emu);
  233. sprintf(hex_str_part, "%04X", (uint16_t) destination_offset);
  234. strncat(hex_str, hex_str_part, sizeof hex_str);
  235. if (constant_generator_active) { /* Source Constant */
  236. source_value = immediate_constant;
  237. sprintf(asm_operands, "#0x%04X, ", source_value);
  238. }
  239. else { /* Source Indirect */
  240. source_value = *get_addr_ptr(*s_reg);
  241. sprintf(asm_operands, "@%s, ", s_reg_name);
  242. }
  243. if (destination == 0) { /* Destination Symbolic */
  244. uint16_t virtual_addr = cpu->pc + destination_offset - 2;
  245. destination_addr = get_addr_ptr(virtual_addr);
  246. sprintf(asm_op2, "0x%04X", virtual_addr);
  247. }
  248. else if (destination == 2) { /* Destination Absolute */
  249. destination_addr = get_addr_ptr(destination_offset);
  250. sprintf(asm_op2, "&0x%04X", destination_offset);
  251. }
  252. else { /* Destination Indexed */
  253. destination_addr = get_addr_ptr(*d_reg + destination_offset);
  254. sprintf(asm_op2, "0x%04X(%s)", (uint16_t)destination_offset, d_reg_name);
  255. }
  256. strncat(asm_operands, asm_op2, sizeof asm_op2);
  257. }
  258. /* Indirect Inc - Register; Ex: MOV @Rs+, Rd */
  259. /* Immediate - Register; Ex: MOV #S, Rd */
  260. /* Constant Gen - Register; Ex: MOV #C, Rd */ /* -1, 8 */
  261. else if (as_flag == 3 && ad_flag == 0) {
  262. if (constant_generator_active) { /* Source Constant */
  263. source_value = immediate_constant;
  264. sprintf(asm_operands, "#0x%04X, %s",
  265. (uint16_t) source_value, d_reg_name);
  266. }
  267. else if (source == 0) { /* Source Immediate */
  268. source_value = fetch(emu);
  269. sprintf(hex_str_part, "%04X", (uint16_t) source_value);
  270. strncat(hex_str, hex_str_part, sizeof hex_str);
  271. if (bw_flag == EMU_WORD) {
  272. sprintf(asm_operands, "#0x%04X, %s",
  273. (uint16_t) source_value, d_reg_name);
  274. }
  275. else if (bw_flag == EMU_BYTE) {
  276. sprintf(asm_operands, "#0x%04X, %s",
  277. (uint8_t) source_value, d_reg_name);
  278. }
  279. }
  280. else { /* Source Indirect AutoIncrement */
  281. source_value = *get_addr_ptr(*s_reg);
  282. sprintf(asm_operands, "@%s+, %s", s_reg_name, d_reg_name);
  283. if (!disassemble) {
  284. bw_flag == EMU_WORD ? *s_reg += 2 : (*s_reg += 1);
  285. }
  286. }
  287. destination_addr = (uint16_t*)d_reg; /* Destination Register */
  288. if (!disassemble) {
  289. bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0;
  290. }
  291. }
  292. /* Indirect Inc - Indexed; Ex: MOV @Rs+, 0x0(Rd) */
  293. /* Indirect Inc - Symbolic; Ex: MOV @Rs+, 0xD */
  294. /* Indirect Inc - Absolute; Ex: MOV @Rs+, &0xD */
  295. /* Immediate - Indexed; Ex: MOV #S, 0x0(Rd) */
  296. /* Immediate - Symbolic; Ex: MOV #S, 0xD */
  297. /* Immediate - Absolute; Ex: MOV #S, &0xD */
  298. /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* -1, 8 */
  299. /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* -1, 8 */
  300. /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* -1, 8 */
  301. else if (as_flag == 3 && ad_flag == 1) {
  302. if (constant_generator_active) { /* Source Constant */
  303. source_value = immediate_constant;
  304. sprintf(asm_operands, "#0x%04X, ", (uint16_t)source_value);
  305. }
  306. else if (source == 0) { /* Source Immediate */
  307. source_value = fetch(emu);
  308. sprintf(hex_str_part, "%04X", (uint16_t) source_value);
  309. strncat(hex_str, hex_str_part, sizeof hex_str);
  310. sprintf(asm_operands, "#0x%04X, ", (uint16_t)source_value);
  311. }
  312. else { /* Source Indirect Auto Increment */
  313. source_value = *get_addr_ptr(*s_reg);
  314. sprintf(asm_operands, "@%s+, ", s_reg_name);
  315. if (!disassemble) {
  316. bw_flag == EMU_WORD ? *s_reg += 2 : (*s_reg += 1);
  317. }
  318. }
  319. destination_offset = fetch(emu);
  320. sprintf(hex_str_part, "%04X", (uint16_t) destination_offset);
  321. strncat(hex_str, hex_str_part, sizeof hex_str);
  322. if (destination == 0) { /* Destination Symbolic */
  323. uint16_t virtual_addr = cpu->pc + destination_offset - 2;
  324. destination_addr = get_addr_ptr(virtual_addr);
  325. sprintf(asm_op2, "0x%04X", virtual_addr);
  326. }
  327. else if (destination == 2) { /* Destination Absolute */
  328. destination_addr = get_addr_ptr(destination_offset);
  329. sprintf(asm_op2, "&0x%04X", (uint16_t) destination_offset);
  330. }
  331. else { /* Destination Indexed */
  332. destination_addr = get_addr_ptr(*d_reg + destination_offset);
  333. sprintf(asm_op2, "0x%04X(%s)",
  334. (uint16_t) destination_offset, d_reg_name);
  335. }
  336. strncat(asm_operands, asm_op2, sizeof asm_op2);
  337. }
  338. if (!disassemble) {
  339. switch (opcode) {
  340. /* MOV SOURCE, DESTINATION
  341. * Ex: MOV #4, R6
  342. *
  343. * SOURCE = DESTINATION
  344. *
  345. * The source operand is moved to the destination. The source operand is
  346. * not affected. The previous contents of the destination are lost.
  347. *
  348. */
  349. case 0x4: {
  350. if (bw_flag == EMU_WORD) {
  351. *destination_addr = source_value;
  352. }
  353. else if (bw_flag == EMU_BYTE) {
  354. *((uint8_t *) destination_addr) = (uint8_t) source_value;
  355. }
  356. break;
  357. }
  358. /* ADD SOURCE, DESTINATION
  359. * Ex: ADD R5, R4
  360. *
  361. * The source operand is added to the destination operand. The source op
  362. * is not affected. The previous contents of the destination are lost.
  363. *
  364. * DESTINATION = SOURCE + DESTINATION
  365. *
  366. * N: Set if result is negative, reset if positive
  367. * Z: Set if result is zero, reset otherwise
  368. * C: Set if there is a carry from the result, cleared if not
  369. * V: Set if an arithmetic overflow occurs, otherwise reset
  370. *
  371. */
  372. case 0x5:{
  373. uint16_t original_dst_value = *destination_addr;
  374. if (bw_flag == EMU_WORD) {
  375. *destination_addr += source_value;
  376. }
  377. else if (bw_flag == EMU_BYTE) {
  378. *((uint8_t *) destination_addr) += (uint8_t) source_value;
  379. }
  380. cpu->sr.zero = is_zero(destination_addr, bw_flag);
  381. cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag);
  382. cpu->sr.carry = is_carried(original_dst_value, source_value, bw_flag);
  383. cpu->sr.overflow = is_overflowed(source_value, original_dst_value,
  384. destination_addr, bw_flag);
  385. break;
  386. }
  387. /* ADDC SOURCE, DESTINATION
  388. * Ex: ADDC R5, R4
  389. *
  390. * DESTINATION += (SOURCE + C)
  391. *
  392. * N: Set if result is negative, reset if positive
  393. * Z: Set if result is zero, reset otherwise
  394. * C: Set if there is a carry from the result, cleared if not
  395. * V: Set if an arithmetic overflow occurs, otherwise reset
  396. *
  397. */
  398. case 0x6:{
  399. uint16_t original_dst_value = *destination_addr;
  400. if (bw_flag == EMU_WORD) {
  401. *destination_addr += source_value + cpu->sr.carry;
  402. }
  403. else if (bw_flag == EMU_BYTE) {
  404. *((uint8_t *) destination_addr) += (uint8_t) source_value + cpu->sr.carry;
  405. }
  406. cpu->sr.zero = is_zero(destination_addr, bw_flag);
  407. cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag);
  408. cpu->sr.carry = is_carried(original_dst_value, source_value, bw_flag);
  409. cpu->sr.overflow = is_overflowed(source_value, original_dst_value,
  410. destination_addr, bw_flag);
  411. break;
  412. }
  413. /* SUBC SOURCE, DESTINATION
  414. * Ex: SUB R4, R5
  415. *
  416. * DST += ~SRC + C
  417. *
  418. * N: Set if result is negative, reset if positive
  419. * Z: Set if result is zero, reset otherwise
  420. * C: Set if there is a carry from the MSB of the result, reset otherwise.
  421. * Set to 1 if no borrow, reset if borrow.
  422. * V: Set if an arithmetic overflow occurs, otherwise reset
  423. *
  424. *
  425. */
  426. case 0x7:{
  427. int16_t original_dst_value = *destination_addr;
  428. source_value = ~source_value; /* 1's comp */
  429. if (bw_flag == EMU_WORD) {
  430. *(int16_t *)destination_addr += source_value + cpu->sr.carry;
  431. }
  432. else if (bw_flag == EMU_BYTE) {
  433. *(int8_t *)destination_addr += (int8_t) source_value + cpu->sr.carry;
  434. }
  435. cpu->sr.zero = is_zero(destination_addr, bw_flag);
  436. cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag);
  437. cpu->sr.carry = is_carried(original_dst_value, source_value, bw_flag);
  438. cpu->sr.overflow = is_overflowed(source_value, original_dst_value,
  439. destination_addr, bw_flag);
  440. break;
  441. }
  442. /* SUB SOURCE, DESTINATION
  443. * Ex: SUB R4, R5
  444. *
  445. * DST -= SRC
  446. *
  447. * N: Set if result is negative, reset if positive
  448. * Z: Set if result is zero, reset otherwise
  449. * C: Set if there is a carry from the MSB of the result, reset otherwise.
  450. * Set to 1 if no borrow, reset if borrow.
  451. * V: Set if an arithmetic overflow occurs, otherwise reset
  452. * TODO: SUBTRACTION OVERFLOW FLAG ERROR
  453. */
  454. case 0x8:{
  455. int16_t original_dst_value = *destination_addr;
  456. source_value = ~source_value + 1;
  457. if (bw_flag == EMU_WORD) {
  458. *(uint16_t *)destination_addr += source_value;
  459. }
  460. else if (bw_flag == EMU_BYTE) {
  461. *(uint8_t *)destination_addr += (uint8_t) source_value;
  462. }
  463. cpu->sr.zero = is_zero(destination_addr, bw_flag);
  464. cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag);
  465. if ( is_carried(~source_value, 1, bw_flag) ||
  466. is_carried(original_dst_value, source_value, bw_flag) ) {
  467. cpu->sr.carry = true;
  468. }
  469. cpu->sr.overflow = is_overflowed(source_value, original_dst_value,
  470. destination_addr, bw_flag);
  471. break;
  472. }
  473. /* CMP SOURCE, DESTINATION
  474. *
  475. * N: Set if result is negative, reset if positive (src ≥ dst)
  476. * Z: Set if result is zero, reset otherwise (src = dst)
  477. * C: Set if there is a carry from the MSB of the result, reset otherwise
  478. * V: Set if an arithmetic overflow occurs, otherwise reset
  479. * TODO: Fix overflow error
  480. */
  481. case 0x9:{
  482. int16_t original_dst_value = *destination_addr;
  483. uint16_t unsigned_source_value = ((uint16_t)~source_value + 1);
  484. int16_t result;
  485. bool early_carry = is_carried((uint16_t)~source_value, 1, bw_flag);
  486. if (bw_flag == EMU_WORD) {
  487. result = *destination_addr + (uint16_t) unsigned_source_value;
  488. }
  489. else if (bw_flag == EMU_BYTE) {
  490. result = *(uint8_t *)destination_addr + (uint8_t)unsigned_source_value;
  491. }
  492. cpu->sr.negative = is_negative(&result, bw_flag);
  493. cpu->sr.zero = is_zero((uint16_t*)&result, bw_flag);
  494. /* Check if the carry happens durring conversion to 2's comp */
  495. if (! early_carry) {
  496. cpu->sr.carry = is_carried(original_dst_value, unsigned_source_value, bw_flag);
  497. }
  498. else {
  499. cpu->sr.carry = true;
  500. }
  501. cpu->sr.overflow = is_overflowed(unsigned_source_value, original_dst_value, (uint16_t*)&result, bw_flag);
  502. break;
  503. }
  504. /* DADD SOURCE, DESTINATION
  505. *
  506. */
  507. case 0xA:{
  508. if (bw_flag == EMU_WORD) {
  509. }
  510. else if (bw_flag == EMU_BYTE) {
  511. }
  512. break;
  513. }
  514. /* BIT SOURCE, DESTINATION
  515. *
  516. * N: Set if MSB of result is set, reset otherwise
  517. * Z: Set if result is zero, reset otherwise
  518. * C: Set if result is not zero, reset otherwise (.NOT. Zero)
  519. * V: Reset
  520. */
  521. case 0xB:{
  522. if (bw_flag == EMU_WORD) {
  523. uint16_t result = ((uint16_t) source_value) & (*destination_addr);
  524. cpu->sr.zero = (result == 0);
  525. cpu->sr.negative = result >> 15;
  526. cpu->sr.carry = (result != 0);
  527. }
  528. else if (bw_flag == EMU_BYTE) {
  529. uint8_t result =
  530. ((uint8_t) source_value) & (*(uint8_t *) destination_addr);
  531. cpu->sr.zero = (result == 0);
  532. cpu->sr.negative = result >> 7;
  533. cpu->sr.carry = (result != 0);
  534. }
  535. cpu->sr.overflow = false;
  536. break;
  537. }
  538. /* BIC SOURCE, DESTINATION
  539. *
  540. * No status bits affected
  541. */
  542. case 0xC:{
  543. if (bw_flag == EMU_WORD) {
  544. // If calling __bic_SR_register_on_exit
  545. if (destination == 0x02 && ad_flag == 0) {
  546. uint16_t sr = sr_to_value(emu);
  547. set_sr_value(emu, sr & ~source_value);
  548. } else {
  549. *destination_addr &= (uint16_t) ~source_value;
  550. }
  551. }
  552. else if (bw_flag == EMU_BYTE) {
  553. // If calling __bic_SR_register_on_exit
  554. if (destination == 0x02 && ad_flag == 0) {
  555. uint16_t sr = sr_to_value(emu);
  556. set_sr_value(emu, sr & (~source_value | 0xFF00));
  557. } else {
  558. *(uint8_t *) destination_addr &= (uint8_t) ~source_value;
  559. }
  560. }
  561. break;
  562. }
  563. /* BIS SOURCE, DESTINATION
  564. *
  565. */
  566. case 0xD:{
  567. // If calling __bis_SR_register
  568. if (destination == 0x02 && ad_flag == 0) {
  569. uint16_t sr = sr_to_value(emu);
  570. set_sr_value(emu, sr | source_value);
  571. }
  572. else if (bw_flag == EMU_WORD) {
  573. *destination_addr |= (uint16_t) source_value;
  574. }
  575. else if (bw_flag == EMU_BYTE) {
  576. *(uint8_t *) destination_addr |= (uint8_t) source_value;
  577. }
  578. break;
  579. }
  580. /* XOR SOURCE, DESTINATION
  581. *
  582. * N: Set if result MSB is set, reset if not set
  583. * Z: Set if result is zero, reset otherwise
  584. * C: Set if result is not zero, reset otherwise ( = .NOT. Zero)
  585. * V: Set if both operands are negative
  586. */
  587. case 0xE:{
  588. if (bw_flag == EMU_WORD) {
  589. cpu->sr.overflow =
  590. (*destination_addr >> 15) && ((uint16_t)source_value >> 15);
  591. *destination_addr ^= (uint16_t)source_value;
  592. cpu->sr.negative = (*destination_addr) >> 15;
  593. cpu->sr.zero = (*destination_addr == 0);
  594. cpu->sr.carry = (*destination_addr != 0);
  595. }
  596. else if (bw_flag == EMU_BYTE) {
  597. cpu->sr.overflow =
  598. (*(uint8_t *)destination_addr >> 7) && ((uint8_t)source_value >> 7);
  599. *(uint8_t *) destination_addr ^= (uint8_t) source_value;
  600. cpu->sr.negative = (*(uint8_t *) destination_addr) >> 7;
  601. cpu->sr.zero = (*(uint8_t *)destination_addr == 0);
  602. cpu->sr.carry = (*(uint8_t *)destination_addr != 0);
  603. }
  604. break;
  605. }
  606. /* AND SOURCE, DESTINATION
  607. *
  608. * N: Set if result MSB is set, reset if not set
  609. * Z: Set if result is zero, reset otherwise
  610. * C: Set if result is not zero, reset otherwise ( = .NOT. Zero)
  611. * V: Reset
  612. */
  613. case 0xF:{
  614. if (bw_flag == EMU_WORD) {
  615. *destination_addr &= (uint16_t)source_value;
  616. cpu->sr.negative = (*destination_addr) >> 15;
  617. cpu->sr.zero = (*destination_addr == 0);
  618. cpu->sr.carry = (*destination_addr != 0);
  619. }
  620. else if (bw_flag == EMU_BYTE) {
  621. *(uint8_t *) destination_addr &= (uint8_t) source_value;
  622. cpu->sr.negative = (*(uint8_t *) destination_addr) >> 7;
  623. cpu->sr.zero = (*(uint8_t *)destination_addr == 0);
  624. cpu->sr.carry = (*(uint8_t *)destination_addr != 0);
  625. }
  626. cpu->sr.overflow = false;
  627. break;
  628. }
  629. } //# End of switch
  630. } // End of if
  631. // DISASSEMBLY MODE
  632. else {
  633. switch (opcode) {
  634. case 0x4: {
  635. bw_flag == EMU_WORD ?
  636. strncpy(mnemonic, "MOV", sizeof mnemonic) :
  637. strncpy(mnemonic, "MOV.B", sizeof mnemonic);
  638. break;
  639. }
  640. case 0x5: {
  641. bw_flag == EMU_WORD ?
  642. strncpy(mnemonic, "ADD", sizeof mnemonic) :
  643. strncpy(mnemonic, "ADD.B", sizeof mnemonic);
  644. break;
  645. }
  646. case 0x6: {
  647. bw_flag == EMU_WORD ?
  648. strncpy(mnemonic, "ADDC", sizeof mnemonic) :
  649. strncpy(mnemonic, "ADDC.B", sizeof mnemonic);
  650. break;
  651. }
  652. case 0x7: {
  653. bw_flag == EMU_WORD ?
  654. strncpy(mnemonic, "SUBC", sizeof mnemonic) :
  655. strncpy(mnemonic, "SUBC.B", sizeof mnemonic);
  656. break;
  657. }
  658. case 0x8: {
  659. bw_flag == EMU_WORD ?
  660. strncpy(mnemonic, "SUB", sizeof mnemonic) :
  661. strncpy(mnemonic, "SUB.B", sizeof mnemonic);
  662. break;
  663. }
  664. case 0x9: {
  665. bw_flag == EMU_WORD ?
  666. strncpy(mnemonic, "CMP", sizeof mnemonic) :
  667. strncpy(mnemonic, "CMP.B", sizeof mnemonic);
  668. break;
  669. }
  670. case 0xA: {
  671. bw_flag == EMU_WORD ?
  672. strncpy(mnemonic, "DADD", sizeof mnemonic) :
  673. strncpy(mnemonic, "DADD.B", sizeof mnemonic);
  674. break;
  675. }
  676. case 0xB: {
  677. bw_flag == EMU_WORD ?
  678. strncpy(mnemonic, "BIT", sizeof mnemonic) :
  679. strncpy(mnemonic, "BIT.B", sizeof mnemonic);
  680. break;
  681. }
  682. case 0xC: {
  683. bw_flag == EMU_WORD ?
  684. strncpy(mnemonic, "BIC", sizeof mnemonic) :
  685. strncpy(mnemonic, "BIC.B", sizeof mnemonic);
  686. break;
  687. }
  688. case 0xD: {
  689. bw_flag == EMU_WORD ?
  690. strncpy(mnemonic, "BIS", sizeof mnemonic) :
  691. strncpy(mnemonic, "BIS.B", sizeof mnemonic);
  692. break;
  693. }
  694. case 0xE: {
  695. bw_flag == EMU_WORD ?
  696. strncpy(mnemonic, "XOR", sizeof mnemonic) :
  697. strncpy(mnemonic, "XOR.B", sizeof mnemonic);
  698. break;
  699. }
  700. case 0xF: {
  701. bw_flag == EMU_WORD ?
  702. strncpy(mnemonic, "AND", sizeof mnemonic) :
  703. strncpy(mnemonic, "AND.B", sizeof mnemonic);
  704. break;
  705. }
  706. } //# End of switch
  707. strncat(mnemonic, "\t", sizeof mnemonic);
  708. strncat(mnemonic, asm_operands, sizeof mnemonic);
  709. strncat(mnemonic, "\n", sizeof mnemonic);
  710. if (disassemble && emu->debugger->debug_mode) {
  711. int i;
  712. char one = 0, two = 0;
  713. // Make little endian big endian
  714. for (i = 0;i < strlen(hex_str);i += 4) {
  715. one = hex_str[i];
  716. two = hex_str[i + 1];
  717. hex_str[i] = hex_str[i + 2];
  718. hex_str[i + 1] = hex_str[i + 3];
  719. hex_str[i + 2] = one;
  720. hex_str[i + 3] = two;
  721. }
  722. printf("%s", hex_str);
  723. print_console(emu, hex_str);
  724. for (i = strlen(hex_str);i < 12;i++) {
  725. printf(" ");
  726. print_console(emu, " ");
  727. }
  728. printf("\t%s", mnemonic);
  729. print_console(emu, "\t");
  730. print_console(emu, mnemonic);
  731. }
  732. }
  733. };