diff --git a/simulate/msp430.cpp b/simulate/msp430.cpp index 1056f3a2..58a8bf78 100644 --- a/simulate/msp430.cpp +++ b/simulate/msp430.cpp @@ -18,13 +18,6 @@ #include "disasm/msp430.h" #include "simulate/msp430.h" -/* - - 8 7 6 5 4 3 2 1 0 -Status: V SCG1 SCG0 OSCOFF CPUOFF GIE N Z C - -*/ - #define SHOW_STACK sp, memory->read8(sp + 1), memory->read8(sp) #define READ_RAM(a) memory->read8(a) #define WRITE_RAM(a,b) \ @@ -34,88 +27,7 @@ Status: V SCG1 SCG0 OSCOFF CPUOFF GIE N Z C } \ memory->write8(a, b); -#define GET_V() ((reg[2] >> 8) & 1) -#define GET_SCG1() ((reg[2] >> 7) & 1) -#define GET_SCG0() ((reg[2] >> 6) & 1) -#define GET_OSCOFF() ((reg[2] >> 5) & 1) -#define GET_CPUOFF() ((reg[2] >> 4) & 1) -#define GET_GIE() ((reg[2] >> 3) & 1) -#define GET_N() ((reg[2] >> 2) & 1) -#define GET_Z() ((reg[2] >> 1) & 1) -#define GET_C() ((reg[2]) & 1) - -#define SET_V() reg[2] |= 256; -#define SET_SCG1() reg[2] |= 128; -#define SET_SCG0() reg[2] |= 64; -#define SET_OSCOFF() reg[2] |= 32; -#define SET_CPUOFF() reg[2] |= 16; -#define SET_GIE() reg[2] |= 8; -#define SET_N() reg[2] |= 4; -#define SET_Z() reg[2] |= 2; -#define SET_C() reg[2] |= 1; - -#define CLEAR_V() reg[2] &= (0xffff^256); -#define CLEAR_SCG1() reg[2] &= (0xffff^128); -#define CLEAR_SCG0() reg[2] &= (0xffff^64); -#define CLEAR_OSCOFF() reg[2] &= (0xffff^32); -#define CLEAR_CPUOFF() reg[2] &= (0xffff^16); -#define CLEAR_GIE() reg[2] &= (0xffff^8); -#define CLEAR_N() reg[2] &= (0xffff^4); -#define CLEAR_Z() reg[2] &= (0xffff^2); -#define CLEAR_C() reg[2] &= (0xffff^1); - -#define AFFECTS_NZ(a) \ - if (bw == 0) \ - { \ - if (a & 0x8000) { SET_N(); } else { CLEAR_N(); } \ - } \ - else \ - { \ - if (a & 0x80) { SET_N(); } else { CLEAR_N(); } \ - } \ - if (a == 0) { SET_Z(); } else { CLEAR_Z(); } - -#define CHECK_CARRY(a) \ - if (bw == 0) \ - { \ - if ((a & 0xffff0000) == 0) { CLEAR_C(); } else { SET_C(); } \ - } \ - else \ - { \ - if ((a & 0xffffff00) == 0) { CLEAR_C(); } else { SET_C(); } \ - } - -#define CHECK_OVERFLOW() \ - if (bw == 0) \ - { \ - if (((((uint16_t)dst) & 0x8000) == (((uint16_t)src) & 0x8000)) && (((((uint16_t)result) & 0x8000)) != (((uint16_t)dst) & 0x8000))) { SET_V(); } else { CLEAR_V(); } \ - } \ - else \ - { \ - if (((((uint8_t)dst) & 0x80) == (((uint8_t)src) & 0x80)) && (((((uint8_t)result) & 0x80))!=(((uint8_t)dst) & 0x80))) { SET_V(); } else { CLEAR_V(); } \ - } - -#define CHECK_OVERFLOW_WITH_C() \ - if (bw==0) \ - { \ - if ((((int32_t)dst + (int32_t)src + GET_C()) & 0xffff0000) != 0) { SET_V(); } else { CLEAR_V(); } \ - } \ - else \ - { \ - if ((((int32_t)dst + (int32_t)src + GET_C()) & 0xffffff00) != 0) { SET_V(); } else { CLEAR_V(); } \ - } - -#define CHECK_Z() \ - if (bw == 0) \ - { \ - if (result & 0x8000) { SET_N(); } else { CLEAR_N(); } \ - } \ - else \ - { \ - if (result & 0x80) { SET_N(); } else { CLEAR_N(); } \ - } - -static const char *flags[] = +const char *SimulateMsp430::flags[] = { "C", "Z", @@ -691,16 +603,16 @@ int SimulateMsp430::one_operand_exe(uint16_t opcode) { pc = reg[0]; src = get_data(reg_index, As, bw); - int c = GET_C(); - if ((src & 1) == 1) { SET_C(); } else { CLEAR_C(); } + int c = get_c(); + if ((src & 1) == 1) { set_c(); } else { clear_c(); } if (bw == 0) { result = (c << 15) | (((uint16_t)src) >> 1); } else { result = (c << 7) | (((uint8_t)src) >> 1); } put_data(pc, reg_index, As, bw, result); update_reg(reg_index, As, bw); - AFFECTS_NZ(result); - CLEAR_V(); + update_nz(result, bw); + clear_v(); break; } case 1: // SWPB (no bw) @@ -716,15 +628,15 @@ int SimulateMsp430::one_operand_exe(uint16_t opcode) { pc = reg[0]; src = get_data(reg_index, As, bw); - if ((src & 1) == 1) { SET_C(); } else { CLEAR_C(); } + if ((src & 1) == 1) { set_c(); } else { clear_c(); } if (bw == 0) { result = ((int16_t)src) >> 1; } else { result = ((int8_t)src) >> 1; } put_data(pc, reg_index, As, bw, result); update_reg(reg_index, As, bw); - AFFECTS_NZ(result); - CLEAR_V(); + update_nz(result, bw); + clear_v(); break; } case 3: // SXT (no bw) @@ -734,9 +646,9 @@ int SimulateMsp430::one_operand_exe(uint16_t opcode) result = (int16_t)((int8_t)((uint8_t)src)); put_data(pc, reg_index, As, bw, result); update_reg(reg_index, As, bw); - AFFECTS_NZ(result); - CHECK_CARRY(result); - CLEAR_V(); + update_nz(result, bw); + update_c(result, bw); + clear_v(); break; } case 4: // PUSH @@ -789,25 +701,25 @@ int SimulateMsp430::relative_jump_exe(uint16_t opcode) switch (o) { case 0: // JNE/JNZ Z==0 - if (GET_Z() == 0) { reg[0] += offset; } + if (get_z() == 0) { reg[0] += offset; } break; case 1: // JEQ/JZ Z==1 - if (GET_Z() == 1) { reg[0] += offset; } + if (get_z() == 1) { reg[0] += offset; } break; case 2: // JNC/JLO C==0 - if (GET_C() == 0) { reg[0] += offset; } + if (get_c() == 0) { reg[0] += offset; } break; case 3: // JC/JHS C==1 - if (GET_C() == 1) { reg[0] += offset; } + if (get_c() == 1) { reg[0] += offset; } break; case 4: // JN N==1 - if (GET_N() == 1) { reg[0] += offset; } + if (get_n() == 1) { reg[0] += offset; } break; case 5: // JGE (N^V)==0 - if ((GET_N() ^ GET_V()) == 0) { reg[0] += offset; } + if ((get_n() ^ get_v()) == 0) { reg[0] += offset; } break; case 6: // JL (N^V)==1 - if ((GET_N() ^ GET_V()) == 1) { reg[0] += offset; } + if ((get_n() ^ get_v()) == 1) { reg[0] += offset; } break; case 7: // JMP reg[0] += offset; @@ -856,24 +768,23 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) pc = reg[0]; dst = get_data(dst_reg, Ad, bw); result = (uint16_t)dst + (uint16_t)src; - CHECK_OVERFLOW(); + update_v(dst, src, result, bw); dst = result & 0xffff; put_data(pc, dst_reg, Ad, bw, dst); - AFFECTS_NZ(dst); - CHECK_CARRY(result); + update_nz(dst, bw); + update_c(result, bw); break; case 6: // ADDC src = get_data(src_reg, As, bw); update_reg(src_reg, As, bw); pc = reg[0]; dst = get_data(dst_reg, Ad, bw); - result = (uint16_t)dst + (uint16_t)src + GET_C(); - //CHECK_OVERFLOW_WITH_C(); - CHECK_OVERFLOW(); + result = (uint16_t)dst + (uint16_t)src + get_c(); + update_v(dst, src, result, bw); dst = result & 0xffff; put_data(pc, dst_reg, Ad, bw, dst); - AFFECTS_NZ(dst); - CHECK_CARRY(result) + update_nz(dst, bw); + update_c(result, bw); break; case 7: // SUBC src = get_data(src_reg, As, bw); @@ -882,15 +793,14 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) dst = get_data(dst_reg, Ad, bw); //src =~ ((uint16_t)src)+1; src = ((~((uint16_t)src)) & 0xffff); - //result = (uint16_t)dst + (uint16_t)src + GET_C(); - // FIXME - Added GET_C(). Test it. - result = dst + src + GET_C(); - //CHECK_OVERFLOW_WITH_C(); - CHECK_OVERFLOW(); + //result = (uint16_t)dst + (uint16_t)src + get_c(); + // FIXME - Added get_c(). Test it. + result = dst + src + get_c(); + update_v(dst, src, result, bw); dst = result & 0xffff; put_data(pc, dst_reg, Ad, bw, dst); - AFFECTS_NZ(dst); - CHECK_CARRY(result) + update_nz(dst, bw); + update_c(result, bw); break; case 8: // SUB src = get_data(src_reg, As, bw); @@ -899,11 +809,11 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) dst = get_data(dst_reg, Ad, bw); src = ((~((uint16_t)src)) & 0xffff) + 1; result = dst + src; - CHECK_OVERFLOW(); + update_v(dst, src, result, bw); dst = result & 0xffff; put_data(pc, dst_reg, Ad, bw, dst); - AFFECTS_NZ(dst); - CHECK_CARRY(result) + update_nz(dst, bw); + update_c(result, bw); break; case 9: // CMP src = get_data(src_reg, As, bw); @@ -913,38 +823,38 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) src = ((~((uint16_t)src)) & 0xffff) + 1; //result = (uint16_t)dst + (uint16_t)src; result = dst + src; - CHECK_OVERFLOW(); + update_v(dst, src, result, bw); dst = result & 0xffff; //put_data(pc, dst_reg, Ad, bw, dst); - AFFECTS_NZ(dst); - CHECK_CARRY(result) + update_nz(dst, bw); + update_c(result, bw); break; case 10: // DADD src = get_data(src_reg, As, bw); update_reg(src_reg, As, bw); pc = reg[0]; dst = get_data(dst_reg, Ad, bw); - result = src + dst + GET_C(); + result = src + dst + get_c(); if (bw == 0) { int a; - a = (src & 0xf) + (dst & 0xf) + GET_C(); + a = (src & 0xf) + (dst & 0xf) + get_c(); a = ((((src >> 4) & 0xf) + ((dst >> 4) & 0xf) + ((a >> 0)/10)) << 4) | (((a >> 0) % 10)<<0); a = ((((src >> 8) & 0xf) + ((dst >> 8) & 0xf) + ((a >> 4)/10)) << 8) | (((a >> 4) % 10)<<4) | (a & 0xf); a = ((((src >> 12) & 0xf) + ((dst >> 12) & 0xf) + ((a >> 8)/10)) << 12) | (((a >> 8) % 10)<<8) | (a & 0xff); - if( (a>>12) >= 10 ) { a = (((a >> 12) % 10)<<12) | (a&0xfff); SET_C(); } else { CLEAR_C(); } + if( (a>>12) >= 10 ) { a = (((a >> 12) % 10)<<12) | (a&0xfff); set_c(); } else { clear_c(); } result = a; } else { int a; - a = (src & 0xf) + (dst & 0xf) + GET_C(); + a = (src & 0xf) + (dst & 0xf) + get_c(); a = ((((src >> 4) & 0xf) + ((dst >> 4) & 0xf) + ((a >> 0)/10)) << 4) | (((a >> 0) % 10)<<0); - if( (a>>4) >= 10 ) { a = (((a >> 4) % 10) << 4) | (a & 0x0f); SET_C(); } else {CLEAR_C(); } + if( (a>>4) >= 10 ) { a = (((a >> 4) % 10) << 4) | (a & 0x0f); set_c(); } else {clear_c(); } result = a; } put_data(pc, dst_reg, Ad, bw, result); - AFFECTS_NZ(result); + update_nz(result, bw); break; case 11: // BIT (dest & src) src = get_data(src_reg, As, bw); @@ -952,9 +862,9 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) pc = reg[0]; dst = get_data(dst_reg, Ad, bw); result = src & dst; - AFFECTS_NZ(result); - if (result != 0) { SET_C(); } else { CLEAR_C(); } - CLEAR_V(); + update_nz(result, bw); + if (result != 0) { set_c(); } else { clear_c(); } + clear_v(); break; case 12: // BIC (dest &= ~src) src = get_data(src_reg, As, bw); @@ -979,9 +889,9 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) dst = get_data(dst_reg, Ad, bw); result = src ^ dst; put_data(pc, dst_reg, Ad, bw, result); - AFFECTS_NZ(result); - if (result != 0) { SET_C(); } else { CLEAR_C(); } - if ((src & 0x8000) && (dst & 0x8000)) { SET_V(); } else { CLEAR_V(); } + update_nz(result, bw); + if (result != 0) { set_c(); } else { clear_c(); } + if ((src & 0x8000) && (dst & 0x8000)) { set_v(); } else { clear_v(); } break; case 15: // AND src = get_data(src_reg, As, bw); @@ -990,9 +900,9 @@ int SimulateMsp430::two_operand_exe(uint16_t opcode) dst = get_data(dst_reg, Ad, bw); result = src & dst; put_data(pc, dst_reg, Ad, bw, result); - AFFECTS_NZ(result); - if (result != 0) { SET_C(); } else { CLEAR_C(); } - CLEAR_V(); + update_nz(result, bw); + if (result != 0) { set_c(); } else { clear_c(); } + clear_v(); break; default: return -1; diff --git a/simulate/msp430.h b/simulate/msp430.h index bfd76757..861a3d1f 100644 --- a/simulate/msp430.h +++ b/simulate/msp430.h @@ -41,7 +41,126 @@ class SimulateMsp430 : public Simulate int relative_jump_exe(uint16_t opcode); int two_operand_exe(uint16_t opcode); + // 8 7 6 5 4 3 2 1 0 + // Status: V SCG1 SCG0 OSCOFF CPUOFF GIE N Z C + + enum Flag + { + FLAG_V = 0x100, + FLAG_SCG1 = 0x80, + FLAG_SCG0 = 0x40, + FLAG_OSCOFF = 0x20, + FLAG_CPUOFF = 0x10, + FLAG_GIE = 0x08, + FLAG_N = 0x04, + FLAG_Z = 0x02, + FLAG_C = 0x01 + }; + +#if 0 + void set_flag(Flag flag) + { + reg[2] |= flag; + } + + void clear_flag(Flag flag) + { + reg[2] &= flag ^ 0xffff; + } +#endif + + int get_v() { return (reg[2] & FLAG_V) == 0 ? 0 : 1; } + int get_scg1() { return (reg[2] & FLAG_SCG1) == 0 ? 0 : 1; } + int get_scg0() { return (reg[2] & FLAG_SCG0) == 0 ? 0 : 1; } + int get_oscoff() { return (reg[2] & FLAG_OSCOFF) == 0 ? 0 : 1; } + int get_cpuoff() { return (reg[2] & FLAG_CPUOFF) == 0 ? 0 : 1; } + int get_gie() { return (reg[2] & FLAG_GIE) == 0 ? 0 : 1; } + int get_n() { return (reg[2] & FLAG_N) == 0 ? 0 : 1; } + int get_z() { return (reg[2] & FLAG_Z) == 0 ? 0 : 1; } + int get_c() { return (reg[2] & FLAG_C) == 0 ? 0 : 1; } + + void clear_v() { reg[2] &= (0xffff ^ FLAG_V); } + void clear_scg1() { reg[2] &= (0xffff ^ FLAG_SCG1); } + void clear_scg0() { reg[2] &= (0xffff ^ FLAG_SCG0); } + void clear_oscoff() { reg[2] &= (0xffff ^ FLAG_OSCOFF); } + void clear_cpuoff() { reg[2] &= (0xffff ^ FLAG_CPUOFF); } + void clear_gie() { reg[2] &= (0xffff ^ FLAG_GIE); } + void clear_n() { reg[2] &= (0xffff ^ FLAG_N); } + void clear_z() { reg[2] &= (0xffff ^ FLAG_Z); } + void clear_c() { reg[2] &= (0xffff ^ FLAG_C); } + + void set_v() { reg[2] |= FLAG_V; } + void set_scg1() { reg[2] |= FLAG_SCG1; } + void set_scg0() { reg[2] |= FLAG_SCG0; } + void set_oscoff() { reg[2] |= FLAG_OSCOFF; } + void set_cpuoff() { reg[2] |= FLAG_CPUOFF; } + void set_gie() { reg[2] |= FLAG_GIE; } + void set_n() { reg[2] |= FLAG_N; } + void set_z() { reg[2] |= FLAG_Z; } + void set_c() { reg[2] |= FLAG_C; } + + void update_nz(int value, int bw) + { + if (bw == 0) + { + if (value & 0x8000) { set_n(); } else { clear_n(); } + } + else + { + if (value & 0x80) { set_n(); } else { clear_n(); } + } + + if (value == 0) { set_z(); } else { clear_z(); } + } + + void update_c(int value, int bw) + { + if (bw == 0) + { + if ((value & 0xffff0000) == 0) { clear_c(); } else { set_c(); } + } + else + { + if ((value & 0xffffff00) == 0) { clear_c(); } else { set_c(); } + } + } + + void update_v(int dst, int src, int result, int bw) + { + if (bw == 0) + { + uint16_t d = ((uint16_t)dst) & 0x8000; + uint16_t s = ((uint16_t)src) & 0x8000; + uint16_t r = ((uint16_t)result) & 0x8000; + + if (d == s && r != d) { set_v(); } else { clear_v(); } + } + else + { + uint8_t d = ((uint8_t)dst) & 0x80; + uint8_t s = ((uint8_t)src) & 0x80; + uint8_t r = ((uint8_t)result) & 0x80; + + if (d == s && r != d) { set_v(); } else { clear_v(); } + } + } + +#if 0 + void update_z(int result, int bw) + { + if (bw == 0) + { + if (result & 0x8000) { set_n(); } else { clear_n(); } + } + else + { + if (result & 0x80) { set_n(); } else { clear_n(); } + } + } +#endif + uint16_t reg[16]; + static const char *flags[]; }; #endif