OSDN Git Service

Almost programmed as CDL editor. -e option.
[sau-decompiler/master.git] / state_machine.cpp
1 #include "state_machine.hpp"
2
3 bool StateMachine::isOverflowAddtion(Byte a, Byte b, Byte result)
4 {
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));
9 }
10 bool StateMachine::isOverflowSubtraction(Byte a, Byte b, Byte result)
11 {
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));
16 }
17 void StateMachine::pushWord(Word word)
18 {
19         Byte high = word>>8;
20         Byte low = word&0xFF;
21         push(high); // higher is upper.
22         push(low);
23 }
24 Word StateMachine::pullWord()
25 {
26         Byte low = pull();
27         Byte high = pull();
28         return bit8::lowHigh(low, high);
29 }
30
31 Word StateMachine::rts()
32 {
33         if (m_call_stack.size() > 2) {
34                 m_call_stack.pop_back();
35                 m_call_stack.pop_back();
36         }
37         return pullWord();
38 }
39 void StateMachine::call(Word dest_addr, Word ret_addr)
40 {
41         m_call_stack.push_back(dest_addr);
42         m_call_stack.push_back(ret_addr);
43         pushWord(ret_addr);
44         m_return_addr = ret_addr;
45         m_pc = dest_addr;
46                 
47 }
48 void StateMachine::compare(Byte left, Byte right)
49 {
50         setPS(PS_N, left < right);
51         setPS(PS_Z, left == right);
52         setPS(PS_C, left >= right);
53 }
54
55 void StateMachine::execute(PInstruction instr)
56 {
57         m_pc = instr->next();
58         Byte& m = target(instr->mode(), instr->operand());
59                 
60         Byte& a = m_reg[R_A];
61         Byte& x = m_reg[R_X];
62         Byte& y = m_reg[R_Y];
63         
64         bool temp_flag=false;
65         Byte result;
66                 
67         switch (instr->type()) {
68         case opcode::LDA:
69                 a = m;
70                 cond(a);
71                 return;
72         case opcode::LDX: x = m; cond(x); return;
73         case opcode::LDY: y = m; cond(y); return;
74         case opcode::ADC:
75                 temp_flag = ps(PS_C);
76                 result = a + m + (temp_flag?1:0);
77                 setPS(PS_C, (result < a));
78                 setPS(PS_V, isOverflowAddtion(a, m, result));
79                 a = result;
80                 cond(a);
81                 return; 
82         case opcode::SBC:
83                 temp_flag = ps(PS_C);
84                 result = a - m - (temp_flag ? 0:1);
85                 setPS(PS_C, (result > a));
86                 setPS(PS_V, isOverflowSubtraction(a, m, result));
87                 a = result;
88                 a -= m;
89                 cond(a);
90                 return;
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;
94         case opcode::BIT:
95                 setPS(PS_N, bit8::signBit(m));
96                 setPS(PS_Z, a == m);
97                 setPS(PS_V, bit8::byteBit(m,6));
98                 return;
99         case opcode::CMP: compare(a,m); return;
100         case opcode::CPX: compare(x,m); return;
101         case opcode::CPY: compare(y,m); return;
102                 
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;
112         case opcode::ASL:
113                 setPS(PS_C, bit8::byteBit(m, HIGHEST_BIT)); // carry bit
114                 m <<= 1; cond(m);
115                 return;
116         case opcode::LSR:
117                 setPS(PS_C,bit8::byteBit(m, 0));
118                 m >>= 1; cond(m);
119                 return;
120         case opcode::ROL:
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);
124                 cond(m);
125                 return;
126         case opcode::ROR:
127                 temp_flag = ps(PS_C);
128                 setPS(PS_C,bit8::byteBit(m, 0));
129                 m = m >> 1 | (temp_flag?(1<<7):0);
130                 cond(m);
131                 return;
132                 
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;
137                         
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;
145                         
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;
152                         
153         case opcode::JMP:
154                 if (instr->mode()==opcode::IND) {
155                         MemoryID id = m_mapper.id(instr->operand());
156                         m_pc = m_mapper.wordData(id);
157                 } else {
158                         m_pc = instr->operand();
159                 }
160                 return;
161                         
162         case opcode::JSR:
163                 if (instr->mode()==opcode::IND) {
164                         MemoryID id = m_mapper.id(instr->operand());
165                         call(m_mapper.wordData(id), instr->next()-1);
166                 } else {
167                         call(instr->operand(), instr->next()-1);
168                 }
169                 return;
170                         
171         case opcode::RTS: m_pc = rts()+1; return;
172                         
173         case opcode::BRK:
174                 call(m_mapper.irq(), instr->next()+1);//increment (not byte length)
175                 push(m_reg[R_PS]);
176                 return;
177         case opcode::RTI:
178                 m_reg[R_PS] = pull();
179                 m_pc = rts() - 1;
180                 return;
181                         
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;
190                         
191         case opcode::NOP:
192                 return;//do nothing
193         default:
194                 return;
195         }
196 }
197
198 // read the value of operand.
199 Byte& StateMachine::target(AddressingMode mode, Word operand)
200 {
201         MemoryID id = m_mapper.id(operand);
202         switch (mode) {
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]);
213         case opcode::IMM:
214                 m_temp = operand;
215                 return m_temp;
216         case opcode::REG_A:
217                 return m_reg[R_A];
218         case opcode::IND: // this returns Word but
219         default:
220                 return m_temp;
221         }
222 }
223 MemoryID StateMachine::targetID(AddressingMode mode,
224                               Word operand)
225 {
226         MemoryID id = m_mapper.id(operand);
227         switch (mode) {
228         case opcode::ZERO: case opcode::ABS:
229                 return id;
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);
240         case opcode::IMM:
241         case opcode::REG_A:
242         default:
243                 return id;
244         }
245 }
246