1 #include "state_machine.hpp"
3 bool StateMachine::isOverflowAddtion(Byte a, Byte b, Byte result)
5 bool sa = bit8::signBit(a);
6 bool sb = bit8::signBit(b);
7 bool sr = bit8::signBit(result);
8 return ((~sa & ~sb) & sr) | ((sa & sb) & (~sr));
10 bool StateMachine::isOverflowSubtraction(Byte a, Byte b, Byte result)
12 bool sa = bit8::signBit(a);
13 bool sb = bit8::signBit(b);
14 bool sr = bit8::signBit(result);
15 return ((~sa & sb) & sr) | ((sa & ~sb) & (~sr));
17 void StateMachine::pushWord(Word word)
21 push(high); // higher is upper.
24 Word StateMachine::pullWord()
28 return bit8::lowHigh(low, high);
31 Word StateMachine::rts()
33 if (m_call_stack.size() > 2) {
34 m_call_stack.pop_back();
35 m_call_stack.pop_back();
39 void StateMachine::call(Word dest_addr, Word ret_addr)
41 m_call_stack.push_back(dest_addr);
42 m_call_stack.push_back(ret_addr);
44 m_return_addr = ret_addr;
48 void StateMachine::compare(Byte left, Byte right)
50 setPS(PS_N, left < right);
51 setPS(PS_Z, left == right);
52 setPS(PS_C, left >= right);
55 void StateMachine::execute(PInstruction instr)
58 Byte& m = target(instr->mode(), instr->operand());
67 switch (instr->type()) {
72 case opcode::LDX: x = m; cond(x); return;
73 case opcode::LDY: y = m; cond(y); return;
76 result = a + m + (temp_flag?1:0);
77 setPS(PS_C, (result < a));
78 setPS(PS_V, isOverflowAddtion(a, m, result));
84 result = a - m - (temp_flag ? 0:1);
85 setPS(PS_C, (result > a));
86 setPS(PS_V, isOverflowSubtraction(a, m, result));
91 case opcode::AND: a &= m; cond(a); return;
92 case opcode::EOR: a ^= m; cond(a); return;
93 case opcode::ORA: a |= m; cond(a); return;
95 setPS(PS_N, bit8::signBit(m));
97 setPS(PS_V, bit8::byteBit(m,6));
99 case opcode::CMP: compare(a,m); return;
100 case opcode::CPX: compare(x,m); return;
101 case opcode::CPY: compare(y,m); return;
103 case opcode::STA: m = a; return;
104 case opcode::STX: m = x; return;
105 case opcode::STY: m = y; return;
106 case opcode::INC: m++; cond(m); return;
107 case opcode::INX: x++; cond(x); return;
108 case opcode::INY: y++; cond(y); return;
109 case opcode::DEC: m--; cond(m); return;
110 case opcode::DEX: x--; cond(x); return;
111 case opcode::DEY: y--; cond(y); return;
113 setPS(PS_C, bit8::byteBit(m, HIGHEST_BIT)); // carry bit
117 setPS(PS_C,bit8::byteBit(m, 0));
121 temp_flag = ps(PS_C);
122 setPS(PS_C,bit8::byteBit(m, HIGHEST_BIT)); // carry bit
123 m = m << 1 | (temp_flag?1:0);
127 temp_flag = ps(PS_C);
128 setPS(PS_C,bit8::byteBit(m, 0));
129 m = m >> 1 | (temp_flag?(1<<7):0);
133 case opcode::PHA: push(a); return;
134 case opcode::PHP: push(m_reg[R_PS]); return;
135 case opcode::PLA: a = pull(); cond(a); return;
136 case opcode::PLP: m_reg[R_PS] = pull();return;
138 case opcode::CLC: setPS(PS_C, false); return;
139 case opcode::CLD: setPS(PS_D, false); return;
140 case opcode::CLI: setPS(PS_I, false); return;
141 case opcode::CLV: setPS(PS_V, false); return;
142 case opcode::SEC: setPS(PS_C, true); return;
143 case opcode::SED: setPS(PS_D, true); return;
144 case opcode::SEI: setPS(PS_I, true); return;
146 case opcode::TAX: x = a; cond(x); return;
147 case opcode::TAY: y = a; cond(y); return;
148 case opcode::TSX: x = m_reg[R_SP]; cond(x); return;
149 case opcode::TXA: a = x; cond(x); return;
150 case opcode::TXS: m_reg[R_SP] = x ; cond(x); return;
151 case opcode::TYA: a = y; cond(y); return;
154 if (instr->mode()==opcode::IND) {
155 MemoryID id = m_mapper.id(instr->operand());
156 m_pc = m_mapper.wordData(id);
158 m_pc = instr->operand();
163 if (instr->mode()==opcode::IND) {
164 MemoryID id = m_mapper.id(instr->operand());
165 call(m_mapper.wordData(id), instr->next()-1);
167 call(instr->operand(), instr->next()-1);
171 case opcode::RTS: m_pc = rts()+1; return;
174 call(m_mapper.irq(), instr->next()+1);//increment (not byte length)
178 m_reg[R_PS] = pull();
182 case opcode::BEQ: m_cond_flag = ps(PS_Z); return;
183 case opcode::BNE: m_cond_flag = !ps(PS_Z); return;
184 case opcode::BCS: m_cond_flag = ps(PS_C); return;
185 case opcode::BCC: m_cond_flag = !ps(PS_C); return;
186 case opcode::BVC: m_cond_flag = ps(PS_V); return;
187 case opcode::BVS: m_cond_flag = !ps(PS_V); return;
188 case opcode::BMI: m_cond_flag = ps(PS_N); return;
189 case opcode::BPL: m_cond_flag = !ps(PS_N); return;
198 // read the value of operand.
199 Byte& StateMachine::target(AddressingMode mode, Word operand)
201 MemoryID id = m_mapper.id(operand);
203 case opcode::ZERO: case opcode::ABS:
204 return m_mapper.data(id);
205 case opcode::ZERO_X: case opcode::ABS_X:
206 return m_mapper.indexedData(id, m_reg[R_X]);
207 case opcode::ZERO_Y: case opcode::ABS_Y:
208 return m_mapper.indexedData(id, m_reg[R_Y]);
209 case opcode::PRE_IND: // ex. lda ($50, x)
210 return m_mapper.preindirectData(id, m_reg[R_X]);
211 case opcode::POST_IND:// ex. lda ($50), y
212 return m_mapper.postindirectData(id, m_reg[R_Y]);
218 case opcode::IND: // this returns Word but
223 MemoryID StateMachine::targetID(AddressingMode mode,
226 MemoryID id = m_mapper.id(operand);
228 case opcode::ZERO: case opcode::ABS:
230 case opcode::ZERO_X: case opcode::ABS_X:
231 return m_mapper.index(id, m_reg[R_X]);
232 case opcode::ZERO_Y: case opcode::ABS_Y:
233 return m_mapper.index(id, m_reg[R_Y]);
234 case opcode::PRE_IND: // ex. lda ($50, x)
235 return m_mapper.preindirectID(id, m_reg[R_X]);
236 case opcode::POST_IND:// ex. lda ($50), y
237 return m_mapper.postindirectID(id, m_reg[R_Y]);
238 case opcode::IND: // this returns Word but
239 return m_mapper.preindirectID(id, 0);