/* MSP430 Emulator Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu) "MSP430 Emulator" is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. "MSP430 Emulator" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ //##########+++ Decode Format I Instructions +++########## //# Format I are double operand of the form: //# [CCCC][SSSS][ABaa][DDDD] //# //# Where C = Opcode, B = Byte/Word flag, //# A = Addressing mode for destination //# a = Addressing mode for s_reg_name //# S = S_Reg_Name, D = Destination //######################################################## #include "formatI.h" void decode_formatI(Emulator *emu, uint16_t instruction, bool disassemble) { Cpu *cpu = emu->cpu; Debugger *debugger = emu->debugger; uint8_t opcode = (instruction & 0xF000) >> 12; uint8_t source = (instruction & 0x0F00) >> 8; uint8_t as_flag = (instruction & 0x0030) >> 4; uint8_t destination = (instruction & 0x000F); uint8_t ad_flag = (instruction & 0x0080) >> 7; uint8_t bw_flag = (instruction & 0x0040) >> 6; char s_reg_name[10], d_reg_name[10]; char mnemonic[100] = {0}; /* String to show hex value of instruction */ char hex_str[100] = {0}; char hex_str_part[10] = {0}; sprintf(hex_str, "%04X", instruction); /* Source Register pointer */ int16_t *s_reg = get_reg_ptr(emu, source); /* Destination Register pointer */ int16_t *d_reg = get_reg_ptr(emu, destination); reg_num_to_name(source, s_reg_name); /* Get source register name */ reg_num_to_name(destination, d_reg_name); /* Get destination register name */ uint8_t constant_generator_active = 0; /* Specifies if CG1/CG2 active */ int16_t immediate_constant = 0; /* Generated Constant */ /* Spot CG1 and CG2 Constant generator instructions */ if ( (source == 2 && as_flag > 1) || source == 3 ) { constant_generator_active = 1; immediate_constant = run_constant_generator(source, as_flag); } else { constant_generator_active = 0; } /* Identify the nature of instruction operand addressing modes */ int16_t source_value, source_offset; int16_t destination_offset; uint16_t *destination_addr; char asm_operands[21] = {0}, asm_op2[20] = {0}; /* Register - Register; Ex: MOV Rs, Rd */ /* Constant Gen - Register; Ex: MOV #C, Rd */ /* 0 */ if (as_flag == 0 && ad_flag == 0) { if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, %s", (uint16_t) source_value, d_reg_name); } else { /* Source register */ source_value = *s_reg; sprintf(asm_operands, "%s, %s", s_reg_name, d_reg_name); } destination_addr = (uint16_t *)d_reg; // Destination Register if (!disassemble) { bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0; } } /* Register - Indexed; Ex: MOV Rs, 0x0(Rd) */ /* Register - Symbolic; Ex: MOV Rs, 0xD */ /* Register - Absolute; Ex: MOV Rs, &0xD */ /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* 0 */ /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* 0 */ /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* 0 */ else if (as_flag == 0 && ad_flag == 1) { destination_offset = fetch(emu); sprintf(hex_str_part, "%04X", (uint16_t) destination_offset); strncat(hex_str, hex_str_part, sizeof hex_str); destination_addr = get_addr_ptr(*d_reg + destination_offset); if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, ", source_value); } else { /* Source from register */ source_value = *s_reg; sprintf(asm_operands, "%s, ", s_reg_name); } if (destination == 0) { /* Destination Symbolic */ uint16_t virtual_addr = *d_reg + destination_offset - 2; destination_addr = get_addr_ptr(virtual_addr); sprintf(asm_op2, "0x%04X", (uint16_t) virtual_addr); } else if (destination == 2) { /* Destination Absolute */ destination_addr = get_addr_ptr(destination_offset); sprintf(asm_op2, "&0x%04X", (uint16_t) destination_offset); } else { /* Destination Indexed */ sprintf(asm_op2, "0x%04X(%s)", (uint16_t) destination_offset, d_reg_name); } strncat(asm_operands, asm_op2, sizeof asm_op2); } /* Indexed - Register; Ex: MOV 0x0(Rs), Rd */ /* Symbolic - Register; Ex: MOV 0xS, Rd */ /* Absolute - Register; Ex: MOV &0xS, Rd */ /* Constant Gen - Register; Ex: MOV #C, Rd */ /* 1 */ else if (as_flag == 1 && ad_flag == 0) { if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, %s", source_value, d_reg_name); } else if (source == 0) { /* Source Symbolic */ source_offset = fetch(emu); uint16_t virtual_addr = *s_reg + source_offset - 2; source_value = *get_addr_ptr(virtual_addr); sprintf(hex_str_part, "%04X", (uint16_t) source_offset); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "0x%04X, %s", virtual_addr, d_reg_name); } else if (source == 2) { /* Source Absolute */ source_offset = fetch(emu); source_value = *get_addr_ptr(source_offset); sprintf(hex_str_part, "%04X", (uint16_t) source_offset); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "&0x%04X, %s", (uint16_t) source_offset, d_reg_name); } else { /* Source Indexed */ source_offset = fetch(emu); source_value = *get_addr_ptr(*s_reg + source_offset); sprintf(hex_str_part, "%04X", (uint16_t) source_offset); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "0x%04X(%s), %s", (uint16_t) source_offset, s_reg_name, d_reg_name); } destination_addr = (uint16_t *)d_reg; /* Destination register */ if (!disassemble) { bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0; } } /* Indexed - Indexed; Ex: MOV 0x0(Rs), 0x0(Rd) */ /* Symbolic - Indexed; Ex: MOV 0xS, 0x0(Rd) */ /* Indexed - Symbolic; Ex: MOV 0x0(Rd), 0xD */ /* Symbolic - Symbolic; Ex: MOV 0xS, 0xD */ /* Absolute - Indexed; Ex: MOV &0xS, 0x0(Rd) */ /* Indexed - Absolute; Ex: MOV 0x0(Rs), &0xD */ /* Absolute - Absolute; Ex: MOV &0xS, &0xD */ /* Absolute - Symbolic; Ex: MOV &0xS, 0xD */ /* Symbolic - Absolute; Ex: MOV 0xS, &0xD */ /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* 1 */ /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* 1 */ /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* 1 */ else if (as_flag == 1 && ad_flag == 1) { if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, ", source_value); } else if (source == 0) { /* Source Symbolic */ source_offset = fetch(emu); uint16_t virtual_addr = cpu->pc + source_offset - 4; source_value = *get_addr_ptr(virtual_addr); sprintf(hex_str_part, "%04X", (uint16_t) source_offset); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "0x%04X, ", virtual_addr); } else if (source == 2) { /* Source Absolute */ source_offset = fetch(emu); source_value = *get_addr_ptr(source_offset); sprintf(hex_str_part, "%04X", (uint16_t) source_offset); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "&0x%04X, ", (uint16_t) source_offset); } else { /* Source Indexed */ source_offset = fetch(emu); source_value = *get_addr_ptr(*s_reg + source_offset); sprintf(hex_str_part, "%04X", (uint16_t)source_offset); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "0x%04X(%s), ", (uint16_t) source_offset, s_reg_name); } destination_offset = fetch(emu); sprintf(hex_str_part, "%04X", (uint16_t) destination_offset); strncat(hex_str, hex_str_part, sizeof hex_str); if (destination == 0) { /* Destination Symbolic */ uint16_t virtual_addr = cpu->pc + destination_offset - 2; destination_addr = get_addr_ptr(virtual_addr); sprintf(asm_op2, "0x%04X", virtual_addr); } else if (destination == 2) { /* Destination Absolute */ destination_addr = get_addr_ptr(destination_offset); sprintf(asm_op2, "&0x%04X", (uint16_t) destination_offset); } else { /* Destination indexed */ destination_addr = get_addr_ptr(*d_reg + destination_offset); sprintf(asm_op2, "0x%04X(%s)", (uint16_t)destination_offset, d_reg_name); } strncat(asm_operands, asm_op2, sizeof asm_op2); } /* Indirect - Register; Ex: MOV @Rs, Rd */ /* Constant Gen - Register; Ex: MOV #C, Rd */ /* 2, 4 */ else if (as_flag == 2 && ad_flag == 0) { if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, %s", immediate_constant, d_reg_name); } else { /* Source Indirect */ source_value = *get_addr_ptr(*s_reg); sprintf(asm_operands, "@%s, %s", s_reg_name, d_reg_name); } destination_addr = (uint16_t*)d_reg; /* Destination Register */ if (!disassemble) { bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0; } } /* Indirect - Indexed; Ex: MOV @Rs, 0x0(Rd) */ /* Indirect - Symbolic; Ex: MOV @Rs, 0xD */ /* Indirect - Absolute; Ex: MOV @Rs, &0xD */ /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* 2, 4 */ /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* 2, 4 */ /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* 2, 4 */ else if (as_flag == 2 && ad_flag == 1) { destination_offset = fetch(emu); sprintf(hex_str_part, "%04X", (uint16_t) destination_offset); strncat(hex_str, hex_str_part, sizeof hex_str); if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, ", source_value); } else { /* Source Indirect */ source_value = *get_addr_ptr(*s_reg); sprintf(asm_operands, "@%s, ", s_reg_name); } if (destination == 0) { /* Destination Symbolic */ uint16_t virtual_addr = cpu->pc + destination_offset - 2; destination_addr = get_addr_ptr(virtual_addr); sprintf(asm_op2, "0x%04X", virtual_addr); } else if (destination == 2) { /* Destination Absolute */ destination_addr = get_addr_ptr(destination_offset); sprintf(asm_op2, "&0x%04X", destination_offset); } else { /* Destination Indexed */ destination_addr = get_addr_ptr(*d_reg + destination_offset); sprintf(asm_op2, "0x%04X(%s)", (uint16_t)destination_offset, d_reg_name); } strncat(asm_operands, asm_op2, sizeof asm_op2); } /* Indirect Inc - Register; Ex: MOV @Rs+, Rd */ /* Immediate - Register; Ex: MOV #S, Rd */ /* Constant Gen - Register; Ex: MOV #C, Rd */ /* -1, 8 */ else if (as_flag == 3 && ad_flag == 0) { if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, %s", (uint16_t) source_value, d_reg_name); } else if (source == 0) { /* Source Immediate */ source_value = fetch(emu); sprintf(hex_str_part, "%04X", (uint16_t) source_value); strncat(hex_str, hex_str_part, sizeof hex_str); if (bw_flag == EMU_WORD) { sprintf(asm_operands, "#0x%04X, %s", (uint16_t) source_value, d_reg_name); } else if (bw_flag == EMU_BYTE) { sprintf(asm_operands, "#0x%04X, %s", (uint8_t) source_value, d_reg_name); } } else { /* Source Indirect AutoIncrement */ source_value = *get_addr_ptr(*s_reg); sprintf(asm_operands, "@%s+, %s", s_reg_name, d_reg_name); if (!disassemble) { bw_flag == EMU_WORD ? *s_reg += 2 : (*s_reg += 1); } } destination_addr = (uint16_t*)d_reg; /* Destination Register */ if (!disassemble) { bw_flag == EMU_BYTE ? *d_reg &= 0x00FF : 0; } } /* Indirect Inc - Indexed; Ex: MOV @Rs+, 0x0(Rd) */ /* Indirect Inc - Symbolic; Ex: MOV @Rs+, 0xD */ /* Indirect Inc - Absolute; Ex: MOV @Rs+, &0xD */ /* Immediate - Indexed; Ex: MOV #S, 0x0(Rd) */ /* Immediate - Symbolic; Ex: MOV #S, 0xD */ /* Immediate - Absolute; Ex: MOV #S, &0xD */ /* Constant Gen - Indexed; Ex: MOV #C, 0x0(Rd) */ /* -1, 8 */ /* Constant Gen - Symbolic; Ex: MOV #C, 0xD */ /* -1, 8 */ /* Constant Gen - Absolute; Ex: MOV #C, &0xD */ /* -1, 8 */ else if (as_flag == 3 && ad_flag == 1) { if (constant_generator_active) { /* Source Constant */ source_value = immediate_constant; sprintf(asm_operands, "#0x%04X, ", (uint16_t)source_value); } else if (source == 0) { /* Source Immediate */ source_value = fetch(emu); sprintf(hex_str_part, "%04X", (uint16_t) source_value); strncat(hex_str, hex_str_part, sizeof hex_str); sprintf(asm_operands, "#0x%04X, ", (uint16_t)source_value); } else { /* Source Indirect Auto Increment */ source_value = *get_addr_ptr(*s_reg); sprintf(asm_operands, "@%s+, ", s_reg_name); if (!disassemble) { bw_flag == EMU_WORD ? *s_reg += 2 : (*s_reg += 1); } } destination_offset = fetch(emu); sprintf(hex_str_part, "%04X", (uint16_t) destination_offset); strncat(hex_str, hex_str_part, sizeof hex_str); if (destination == 0) { /* Destination Symbolic */ uint16_t virtual_addr = cpu->pc + destination_offset - 2; destination_addr = get_addr_ptr(virtual_addr); sprintf(asm_op2, "0x%04X", virtual_addr); } else if (destination == 2) { /* Destination Absolute */ destination_addr = get_addr_ptr(destination_offset); sprintf(asm_op2, "&0x%04X", (uint16_t) destination_offset); } else { /* Destination Indexed */ destination_addr = get_addr_ptr(*d_reg + destination_offset); sprintf(asm_op2, "0x%04X(%s)", (uint16_t) destination_offset, d_reg_name); } strncat(asm_operands, asm_op2, sizeof asm_op2); } if (!disassemble) { switch (opcode) { /* MOV SOURCE, DESTINATION * Ex: MOV #4, R6 * * SOURCE = DESTINATION * * The source operand is moved to the destination. The source operand is * not affected. The previous contents of the destination are lost. * */ case 0x4: { if (bw_flag == EMU_WORD) { *destination_addr = source_value; } else if (bw_flag == EMU_BYTE) { *((uint8_t *) destination_addr) = (uint8_t) source_value; } break; } /* ADD SOURCE, DESTINATION * Ex: ADD R5, R4 * * The source operand is added to the destination operand. The source op * is not affected. The previous contents of the destination are lost. * * DESTINATION = SOURCE + DESTINATION * * N: Set if result is negative, reset if positive * Z: Set if result is zero, reset otherwise * C: Set if there is a carry from the result, cleared if not * V: Set if an arithmetic overflow occurs, otherwise reset * */ case 0x5:{ uint16_t original_dst_value = *destination_addr; if (bw_flag == EMU_WORD) { *destination_addr += source_value; } else if (bw_flag == EMU_BYTE) { *((uint8_t *) destination_addr) += (uint8_t) source_value; } cpu->sr.zero = is_zero(destination_addr, bw_flag); cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag); cpu->sr.carry = is_carried(original_dst_value, source_value, bw_flag); cpu->sr.overflow = is_overflowed(source_value, original_dst_value, destination_addr, bw_flag); break; } /* ADDC SOURCE, DESTINATION * Ex: ADDC R5, R4 * * DESTINATION += (SOURCE + C) * * N: Set if result is negative, reset if positive * Z: Set if result is zero, reset otherwise * C: Set if there is a carry from the result, cleared if not * V: Set if an arithmetic overflow occurs, otherwise reset * */ case 0x6:{ uint16_t original_dst_value = *destination_addr; if (bw_flag == EMU_WORD) { *destination_addr += source_value + cpu->sr.carry; } else if (bw_flag == EMU_BYTE) { *((uint8_t *) destination_addr) += (uint8_t) source_value + cpu->sr.carry; } cpu->sr.zero = is_zero(destination_addr, bw_flag); cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag); cpu->sr.carry = is_carried(original_dst_value, source_value, bw_flag); cpu->sr.overflow = is_overflowed(source_value, original_dst_value, destination_addr, bw_flag); break; } /* SUBC SOURCE, DESTINATION * Ex: SUB R4, R5 * * DST += ~SRC + C * * N: Set if result is negative, reset if positive * Z: Set if result is zero, reset otherwise * C: Set if there is a carry from the MSB of the result, reset otherwise. * Set to 1 if no borrow, reset if borrow. * V: Set if an arithmetic overflow occurs, otherwise reset * * */ case 0x7:{ int16_t original_dst_value = *destination_addr; source_value = ~source_value; /* 1's comp */ if (bw_flag == EMU_WORD) { *(int16_t *)destination_addr += source_value + cpu->sr.carry; } else if (bw_flag == EMU_BYTE) { *(int8_t *)destination_addr += (int8_t) source_value + cpu->sr.carry; } cpu->sr.zero = is_zero(destination_addr, bw_flag); cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag); cpu->sr.carry = is_carried(original_dst_value, source_value, bw_flag); cpu->sr.overflow = is_overflowed(source_value, original_dst_value, destination_addr, bw_flag); break; } /* SUB SOURCE, DESTINATION * Ex: SUB R4, R5 * * DST -= SRC * * N: Set if result is negative, reset if positive * Z: Set if result is zero, reset otherwise * C: Set if there is a carry from the MSB of the result, reset otherwise. * Set to 1 if no borrow, reset if borrow. * V: Set if an arithmetic overflow occurs, otherwise reset * TODO: SUBTRACTION OVERFLOW FLAG ERROR */ case 0x8:{ int16_t original_dst_value = *destination_addr; source_value = ~source_value + 1; if (bw_flag == EMU_WORD) { *(uint16_t *)destination_addr += source_value; } else if (bw_flag == EMU_BYTE) { *(uint8_t *)destination_addr += (uint8_t) source_value; } cpu->sr.zero = is_zero(destination_addr, bw_flag); cpu->sr.negative = is_negative((int16_t*)destination_addr, bw_flag); if ( is_carried(~source_value, 1, bw_flag) || is_carried(original_dst_value, source_value, bw_flag) ) { cpu->sr.carry = true; } cpu->sr.overflow = is_overflowed(source_value, original_dst_value, destination_addr, bw_flag); break; } /* CMP SOURCE, DESTINATION * * N: Set if result is negative, reset if positive (src ≥ dst) * Z: Set if result is zero, reset otherwise (src = dst) * C: Set if there is a carry from the MSB of the result, reset otherwise * V: Set if an arithmetic overflow occurs, otherwise reset * TODO: Fix overflow error */ case 0x9:{ int16_t original_dst_value = *destination_addr; uint16_t unsigned_source_value = ((uint16_t)~source_value + 1); int16_t result; bool early_carry = is_carried((uint16_t)~source_value, 1, bw_flag); if (bw_flag == EMU_WORD) { result = *destination_addr + (uint16_t) unsigned_source_value; } else if (bw_flag == EMU_BYTE) { result = *(uint8_t *)destination_addr + (uint8_t)unsigned_source_value; } cpu->sr.negative = is_negative(&result, bw_flag); cpu->sr.zero = is_zero((uint16_t*)&result, bw_flag); /* Check if the carry happens durring conversion to 2's comp */ if (! early_carry) { cpu->sr.carry = is_carried(original_dst_value, unsigned_source_value, bw_flag); } else { cpu->sr.carry = true; } cpu->sr.overflow = is_overflowed(unsigned_source_value, original_dst_value, (uint16_t*)&result, bw_flag); break; } /* DADD SOURCE, DESTINATION * */ case 0xA:{ if (bw_flag == EMU_WORD) { } else if (bw_flag == EMU_BYTE) { } break; } /* BIT SOURCE, DESTINATION * * N: Set if MSB of result is set, reset otherwise * Z: Set if result is zero, reset otherwise * C: Set if result is not zero, reset otherwise (.NOT. Zero) * V: Reset */ case 0xB:{ if (bw_flag == EMU_WORD) { uint16_t result = ((uint16_t) source_value) & (*destination_addr); cpu->sr.zero = (result == 0); cpu->sr.negative = result >> 15; cpu->sr.carry = (result != 0); } else if (bw_flag == EMU_BYTE) { uint8_t result = ((uint8_t) source_value) & (*(uint8_t *) destination_addr); cpu->sr.zero = (result == 0); cpu->sr.negative = result >> 7; cpu->sr.carry = (result != 0); } cpu->sr.overflow = false; break; } /* BIC SOURCE, DESTINATION * * No status bits affected */ case 0xC:{ if (bw_flag == EMU_WORD) { // If calling __bic_SR_register_on_exit if (destination_offset == 0x0023 || destination_offset == 0x0000) { uint16_t sr = sr_to_value(emu); set_sr_value(emu, sr & ~source_value); } else { *destination_addr &= (uint16_t) ~source_value; } } else if (bw_flag == EMU_BYTE) { // If calling __bic_SR_register_on_exit if (destination_offset == 0x0023 || destination_offset == 0x0000) { uint16_t sr = sr_to_value(emu); set_sr_value(emu, sr & (~source_value | 0xFF00)); } else { *(uint8_t *) destination_addr &= (uint8_t) ~source_value; } } break; } /* BIS SOURCE, DESTINATION * */ case 0xD:{ // If calling __bis_SR_register if (destination_offset == 0x0023 || destination_offset == 0x0000) { uint16_t sr = sr_to_value(emu); set_sr_value(emu, sr | source_value); } else if (bw_flag == EMU_WORD) { *destination_addr |= (uint16_t) source_value; } else if (bw_flag == EMU_BYTE) { *(uint8_t *) destination_addr |= (uint8_t) source_value; } break; } /* XOR SOURCE, DESTINATION * * N: Set if result MSB is set, reset if not set * Z: Set if result is zero, reset otherwise * C: Set if result is not zero, reset otherwise ( = .NOT. Zero) * V: Set if both operands are negative */ case 0xE:{ if (bw_flag == EMU_WORD) { cpu->sr.overflow = (*destination_addr >> 15) && ((uint16_t)source_value >> 15); *destination_addr ^= (uint16_t)source_value; cpu->sr.negative = (*destination_addr) >> 15; cpu->sr.zero = (*destination_addr == 0); cpu->sr.carry = (*destination_addr != 0); } else if (bw_flag == EMU_BYTE) { cpu->sr.overflow = (*(uint8_t *)destination_addr >> 7) && ((uint8_t)source_value >> 7); *(uint8_t *) destination_addr ^= (uint8_t) source_value; cpu->sr.negative = (*(uint8_t *) destination_addr) >> 7; cpu->sr.zero = (*(uint8_t *)destination_addr == 0); cpu->sr.carry = (*(uint8_t *)destination_addr != 0); } break; } /* AND SOURCE, DESTINATION * * N: Set if result MSB is set, reset if not set * Z: Set if result is zero, reset otherwise * C: Set if result is not zero, reset otherwise ( = .NOT. Zero) * V: Reset */ case 0xF:{ if (bw_flag == EMU_WORD) { *destination_addr &= (uint16_t)source_value; cpu->sr.negative = (*destination_addr) >> 15; cpu->sr.zero = (*destination_addr == 0); cpu->sr.carry = (*destination_addr != 0); } else if (bw_flag == EMU_BYTE) { *(uint8_t *) destination_addr &= (uint8_t) source_value; cpu->sr.negative = (*(uint8_t *) destination_addr) >> 7; cpu->sr.zero = (*(uint8_t *)destination_addr == 0); cpu->sr.carry = (*(uint8_t *)destination_addr != 0); } cpu->sr.overflow = false; break; } } //# End of switch } // End of if // DISASSEMBLY MODE else { switch (opcode) { case 0x4: { bw_flag == EMU_WORD ? strncpy(mnemonic, "MOV", sizeof mnemonic) : strncpy(mnemonic, "MOV.B", sizeof mnemonic); break; } case 0x5: { bw_flag == EMU_WORD ? strncpy(mnemonic, "ADD", sizeof mnemonic) : strncpy(mnemonic, "ADD.B", sizeof mnemonic); break; } case 0x6: { bw_flag == EMU_WORD ? strncpy(mnemonic, "ADDC", sizeof mnemonic) : strncpy(mnemonic, "ADDC.B", sizeof mnemonic); break; } case 0x7: { bw_flag == EMU_WORD ? strncpy(mnemonic, "SUBC", sizeof mnemonic) : strncpy(mnemonic, "SUBC.B", sizeof mnemonic); break; } case 0x8: { bw_flag == EMU_WORD ? strncpy(mnemonic, "SUB", sizeof mnemonic) : strncpy(mnemonic, "SUB.B", sizeof mnemonic); break; } case 0x9: { bw_flag == EMU_WORD ? strncpy(mnemonic, "CMP", sizeof mnemonic) : strncpy(mnemonic, "CMP.B", sizeof mnemonic); break; } case 0xA: { bw_flag == EMU_WORD ? strncpy(mnemonic, "DADD", sizeof mnemonic) : strncpy(mnemonic, "DADD.B", sizeof mnemonic); break; } case 0xB: { bw_flag == EMU_WORD ? strncpy(mnemonic, "BIT", sizeof mnemonic) : strncpy(mnemonic, "BIT.B", sizeof mnemonic); break; } case 0xC: { bw_flag == EMU_WORD ? strncpy(mnemonic, "BIC", sizeof mnemonic) : strncpy(mnemonic, "BIC.B", sizeof mnemonic); break; } case 0xD: { bw_flag == EMU_WORD ? strncpy(mnemonic, "BIS", sizeof mnemonic) : strncpy(mnemonic, "BIS.B", sizeof mnemonic); break; } case 0xE: { bw_flag == EMU_WORD ? strncpy(mnemonic, "XOR", sizeof mnemonic) : strncpy(mnemonic, "XOR.B", sizeof mnemonic); break; } case 0xF: { bw_flag == EMU_WORD ? strncpy(mnemonic, "AND", sizeof mnemonic) : strncpy(mnemonic, "AND.B", sizeof mnemonic); break; } } //# End of switch strncat(mnemonic, "\t", sizeof mnemonic); strncat(mnemonic, asm_operands, sizeof mnemonic); strncat(mnemonic, "\n", sizeof mnemonic); if (disassemble && emu->debugger->debug_mode) { int i; char one = 0, two = 0; // Make little endian big endian for (i = 0;i < strlen(hex_str);i += 4) { one = hex_str[i]; two = hex_str[i + 1]; hex_str[i] = hex_str[i + 2]; hex_str[i + 1] = hex_str[i + 3]; hex_str[i + 2] = one; hex_str[i + 3] = two; } printf("%s", hex_str); print_console(emu, hex_str); for (i = strlen(hex_str);i < 12;i++) { printf(" "); print_console(emu, " "); } printf("\t%s", mnemonic); print_console(emu, "\t"); print_console(emu, mnemonic); } } };