OSDN Git Service

Almost programmed as CDL editor. -e option.
[sau-decompiler/master.git] / state_machine.hpp
1 #pragma once
2
3 #include "basic_type.hpp"
4 #include "nes_memory_map.hpp"
5 #include "instruction.hpp"
6 #include "nes_memory_mapper.hpp"
7 #include "utils/hex_form.hpp"
8
9 /**  emulate. */
10 class StateMachine
11 {
12         enum Constant {
13                 HIGHEST_BIT = 7,
14         };
15         enum ProcessorStateType {
16                 PS_C=0, PS_Z, PS_I, PS_D,
17                 PS_B, PS_U, PS_V, PS_N,
18                 PS_NUM,
19         };
20         enum RegisterType {
21                 R_A=0, R_X, R_Y, R_SP, R_PS,
22                 R_COND, 
23                 REG_NUM,
24         };
25         enum IoRegisterType {
26                 IO_PPU=0, IO_VRAM, IO_CONST,
27                 IO_APU, IO_PAD,
28                 IO_NUM,
29         };
30         
31         Word m_pc; 
32         Byte m_reg[REG_NUM];
33
34         NesMemoryMapper m_mapper;
35         Word m_return_addr; // to test whether return is corresponding.
36         bool m_cond_flag;
37
38         const StateMachine* mp_parent;
39         std::vector<Word> m_call_stack;
40         
41         Byte m_temp;
42 public:
43         StateMachine(Word pc, const NesMemoryMapper& mapper)
44                         :m_pc(pc),
45                          m_mapper(mapper),
46                          m_return_addr(pc),
47                          m_cond_flag(false),
48                          mp_parent(this)
49                          
50         {
51                 for (unsigned i=0; i<REG_NUM; ++i) {
52                         m_reg[i] = 0;
53                 }
54         }
55         /// <<copy>>
56         StateMachine(const StateMachine& that)
57                         :m_pc(that.m_pc),
58                          m_mapper(that.m_mapper),
59                          m_return_addr(that.m_return_addr),
60                          m_cond_flag(that.m_cond_flag),
61                          mp_parent(&that),
62                          m_call_stack(that.m_call_stack)
63         {
64                 for (unsigned i=0; i<REG_NUM; ++i) {
65                         m_reg[i] = that.m_reg[i];
66                 }
67         }
68         void copy(const StateMachine& that)
69         {
70                 m_pc=that.m_pc;
71                 
72                 m_mapper.copy(that.m_mapper);
73                 m_return_addr = that.m_return_addr;
74                 m_cond_flag = that.m_cond_flag;
75
76                 unsigned size = that.m_call_stack.size();
77                 m_call_stack.resize(size);
78                 
79                 for (unsigned i=0; i<size; ++i) {
80                         m_call_stack[i]=that.m_call_stack[i];
81                 }
82                 
83                 for (unsigned i=0; i<REG_NUM; ++i) {
84                         m_reg[i] = that.m_reg[i];
85                 }
86         }
87         const StateMachine& parent()const { return *mp_parent; }
88         
89         unsigned depth()const 
90         {
91                 if (mp_parent == this) {
92                         return 0;
93                 } else {
94                         return mp_parent->depth()+1;
95                 }
96         }
97         
98         void execute(PInstruction instr);
99         void restoreMemory()
100         {
101                 if (mp_parent == this) {
102                         return;
103                 }
104                 for (unsigned i=0; i<REG_NUM; ++i) {
105                         m_reg[i] = mp_parent->m_reg[i];
106                 }
107                 m_mapper.copy(mp_parent->m_mapper);
108                 
109         }
110         
111         const NesMemoryMapper& mapper()const {return m_mapper; }
112         Byte a()const { return m_reg[R_A]; }
113         Byte x()const { return m_reg[R_X]; }
114         Byte y()const { return m_reg[R_Y]; }
115         Word stackAddress()const
116         {
117                 return bit8::addressIndex(nes::STACK_OFFSET, m_reg[R_SP]); 
118         }
119         Word returnAddress()const { return m_return_addr; }
120         
121         Byte sp()const { return m_reg[R_SP]; }
122         void setSP(Byte val) { m_reg[R_SP] = val; }
123         Word pc()const { return m_pc; }
124         void setPC(Word addr)
125     {
126         m_pc =addr;
127     }
128         bool ps(ProcessorStateType bit) {return bit8::byteBit(m_reg[R_PS],bit);}
129         void setPS(ProcessorStateType bit, bool val)
130         {
131                 return bit8::setByteBit(m_reg[R_PS],bit, val);
132         }
133         PInstruction nextInstruction()
134         {
135         
136                 MemoryID id=m_mapper.id(m_pc);
137         return m_mapper.getInstruction(id);
138         /* index behaviour is not good, when reading instruction.
139                 Byte byte=m_mapper.data(id);
140                 Byte low=m_mapper.indexedData(id, 1);
141                 Byte high=m_mapper.indexedData(id, 2);
142                 PInstruction ptr(new Instruction(m_pc, byte, low, high));
143                 return ptr;        */
144         }
145         bool isCorrespondReturn()const { return m_return_addr+1 == m_pc; }
146         
147         void setupMatchCase(PInstruction instr)
148         {
149                 if (m_cond_flag) {
150                         m_pc = instr->operand();
151                 } else {
152                         m_pc = instr->next();
153                 }
154         }
155         void setupOtherCase(PInstruction instr)
156         {
157                 if (m_cond_flag) {
158                         m_pc = instr->next();
159                 } else {
160                         m_pc = instr->operand();
161                 }
162         }
163         void resetCall()
164         {
165                 MemoryID id = m_mapper.id(nes::STACK_OFFSET);
166                 m_return_addr=m_mapper.indexedData(id, m_reg[R_SP]+1);
167                 m_return_addr+=m_mapper.indexedData(id, m_reg[R_SP]+2)<<8;
168         }
169         void dumpCallStack()
170         {
171                 std::cout << "stack trace: ";
172                 unsigned size=m_call_stack.size();
173                 for (unsigned i=0; i<size-1; i+=2){
174                         std::cout << "  [" << HexForm(m_call_stack[size-i-1])
175                                           << " > " << HexForm(m_call_stack[size-i-2])
176                                           << "],";
177                 }
178                 std::cout << std::endl;
179         }
180     MemoryID targetID(AddressingMode mode, Word operand);
181
182 private:
183         Word rts();
184         void call(Word dest_addr, Word ret_addr);
185         // push instruction
186         void push(Byte byte) 
187         {
188                 MemoryID id = m_mapper.id(nes::STACK_OFFSET);
189                 m_mapper.indexedData(id, m_reg[R_SP]) = byte;
190                 m_reg[R_SP]--;
191         }
192         // pull instruction
193         Byte pull() {
194                 m_reg[R_SP]++;
195                 MemoryID id = m_mapper.id(nes::STACK_OFFSET);
196                 return m_mapper.indexedData(id, m_reg[R_SP]);
197         }
198         void pushWord(Word word);
199         Word pullWord();        
200         // read the value of operand.
201         Byte& target(AddressingMode mode, Word operand);
202         
203         void cond(Byte val)
204         {
205                 setPS(PS_N, bit8::signBit(val));
206                 setPS(PS_Z, val == 0);
207         }
208         bool isOverflowAddtion(Byte a, Byte b, Byte result);
209         bool isOverflowSubtraction(Byte a, Byte b, Byte result);
210         void compare(Byte left, Byte right);
211 };