1 | //============================================================================ |
2 | // |
3 | // SSSS tt lll lll |
4 | // SS SS tt ll ll |
5 | // SS tttttt eeee ll ll aaaa |
6 | // SSSS tt ee ee ll ll aa |
7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
8 | // SS SS tt ee ll ll aa aa |
9 | // SSSS ttt eeeee llll llll aaaaa |
10 | // |
11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
12 | // and the Stella Team |
13 | // |
14 | // See the file "License.txt" for information on usage and redistribution of |
15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
16 | //============================================================================ |
17 | |
18 | #ifndef DEBUGGER_EXPRESSIONS_HXX |
19 | #define DEBUGGER_EXPRESSIONS_HXX |
20 | |
21 | #include <functional> |
22 | |
23 | #include "bspf.hxx" |
24 | #include "CartDebug.hxx" |
25 | #include "CpuDebug.hxx" |
26 | #include "TIADebug.hxx" |
27 | #include "Debugger.hxx" |
28 | #include "Expression.hxx" |
29 | |
30 | /** |
31 | All expressions currently supported by the debugger. |
32 | @author B. Watson and Stephen Anthony |
33 | */ |
34 | |
35 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
36 | class BinAndExpression : public Expression |
37 | { |
38 | public: |
39 | BinAndExpression(Expression* left, Expression* right) : Expression(left, right) { } |
40 | Int32 evaluate() const override |
41 | { return myLHS->evaluate() & myRHS->evaluate(); } |
42 | }; |
43 | |
44 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
45 | class BinNotExpression : public Expression |
46 | { |
47 | public: |
48 | BinNotExpression(Expression* left) : Expression(left) { } |
49 | Int32 evaluate() const override |
50 | { return ~(myLHS->evaluate()); } |
51 | }; |
52 | |
53 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
54 | class BinOrExpression : public Expression |
55 | { |
56 | public: |
57 | BinOrExpression(Expression* left, Expression* right) : Expression(left, right) { } |
58 | Int32 evaluate() const override |
59 | { return myLHS->evaluate() | myRHS->evaluate(); } |
60 | }; |
61 | |
62 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
63 | class BinXorExpression : public Expression |
64 | { |
65 | public: |
66 | BinXorExpression(Expression* left, Expression* right) : Expression(left, right) { } |
67 | Int32 evaluate() const override |
68 | { return myLHS->evaluate() ^ myRHS->evaluate(); } |
69 | }; |
70 | |
71 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
72 | class ByteDerefExpression : public Expression |
73 | { |
74 | public: |
75 | ByteDerefExpression(Expression* left): Expression(left) { } |
76 | Int32 evaluate() const override |
77 | { return Debugger::debugger().peek(myLHS->evaluate()); } |
78 | }; |
79 | |
80 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
81 | class ByteDerefOffsetExpression : public Expression |
82 | { |
83 | public: |
84 | ByteDerefOffsetExpression(Expression* left, Expression* right) : Expression(left, right) { } |
85 | Int32 evaluate() const override |
86 | { return Debugger::debugger().peek(myLHS->evaluate() + myRHS->evaluate()); } |
87 | }; |
88 | |
89 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
90 | class ConstExpression : public Expression |
91 | { |
92 | public: |
93 | ConstExpression(const int value) : Expression(), myValue(value) { } |
94 | Int32 evaluate() const override |
95 | { return myValue; } |
96 | |
97 | private: |
98 | int myValue; |
99 | }; |
100 | |
101 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
102 | class CpuMethodExpression : public Expression |
103 | { |
104 | public: |
105 | CpuMethodExpression(CpuMethod method) : Expression(), myMethod(std::mem_fn(method)) { } |
106 | Int32 evaluate() const override |
107 | { return myMethod(Debugger::debugger().cpuDebug()); } |
108 | |
109 | private: |
110 | std::function<int(const CpuDebug&)> myMethod; |
111 | }; |
112 | |
113 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
114 | class DivExpression : public Expression |
115 | { |
116 | public: |
117 | DivExpression(Expression* left, Expression* right) : Expression(left, right) { } |
118 | Int32 evaluate() const override |
119 | { int denom = myRHS->evaluate(); |
120 | return denom == 0 ? 0 : myLHS->evaluate() / denom; } |
121 | }; |
122 | |
123 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
124 | class EqualsExpression : public Expression |
125 | { |
126 | public: |
127 | EqualsExpression(Expression* left, Expression* right) : Expression(left, right) { } |
128 | Int32 evaluate() const override |
129 | { return myLHS->evaluate() == myRHS->evaluate(); } |
130 | }; |
131 | |
132 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
133 | class EquateExpression : public Expression |
134 | { |
135 | public: |
136 | EquateExpression(const string& label) : Expression(), myLabel(label) { } |
137 | Int32 evaluate() const override |
138 | { return Debugger::debugger().cartDebug().getAddress(myLabel); } |
139 | |
140 | private: |
141 | string myLabel; |
142 | }; |
143 | |
144 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
145 | class FunctionExpression : public Expression |
146 | { |
147 | public: |
148 | FunctionExpression(const string& label) : Expression(), myLabel(label) { } |
149 | Int32 evaluate() const override |
150 | { return Debugger::debugger().getFunction(myLabel).evaluate(); } |
151 | |
152 | private: |
153 | string myLabel; |
154 | }; |
155 | |
156 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
157 | class GreaterEqualsExpression : public Expression |
158 | { |
159 | public: |
160 | GreaterEqualsExpression(Expression* left, Expression* right) : Expression(left, right) { } |
161 | Int32 evaluate() const override |
162 | { return myLHS->evaluate() >= myRHS->evaluate(); } |
163 | }; |
164 | |
165 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
166 | class GreaterExpression : public Expression |
167 | { |
168 | public: |
169 | GreaterExpression(Expression* left, Expression* right) : Expression(left, right) { } |
170 | Int32 evaluate() const override |
171 | { return myLHS->evaluate() > myRHS->evaluate(); } |
172 | }; |
173 | |
174 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
175 | class HiByteExpression : public Expression |
176 | { |
177 | public: |
178 | HiByteExpression(Expression* left) : Expression(left) { } |
179 | Int32 evaluate() const override |
180 | { return 0xff & (myLHS->evaluate() >> 8); } |
181 | }; |
182 | |
183 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
184 | class LessEqualsExpression : public Expression |
185 | { |
186 | public: |
187 | LessEqualsExpression(Expression* left, Expression* right) : Expression(left, right) { } |
188 | Int32 evaluate() const override |
189 | { return myLHS->evaluate() <= myRHS->evaluate(); } |
190 | }; |
191 | |
192 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
193 | class LessExpression : public Expression |
194 | { |
195 | public: |
196 | LessExpression(Expression* left, Expression* right) : Expression(left, right) { } |
197 | Int32 evaluate() const override |
198 | { return myLHS->evaluate() < myRHS->evaluate(); } |
199 | }; |
200 | |
201 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
202 | class LoByteExpression : public Expression |
203 | { |
204 | public: |
205 | LoByteExpression(Expression* left) : Expression(left) { } |
206 | Int32 evaluate() const override |
207 | { return 0xff & myLHS->evaluate(); } |
208 | }; |
209 | |
210 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
211 | class LogAndExpression : public Expression |
212 | { |
213 | public: |
214 | LogAndExpression(Expression* left, Expression* right) : Expression(left, right) { } |
215 | Int32 evaluate() const override |
216 | { return myLHS->evaluate() && myRHS->evaluate(); } |
217 | }; |
218 | |
219 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
220 | class LogNotExpression : public Expression |
221 | { |
222 | public: |
223 | LogNotExpression(Expression* left) : Expression(left) { } |
224 | Int32 evaluate() const override |
225 | { return !(myLHS->evaluate()); } |
226 | }; |
227 | |
228 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
229 | class LogOrExpression : public Expression |
230 | { |
231 | public: |
232 | LogOrExpression(Expression* left, Expression* right) : Expression(left, right) { } |
233 | Int32 evaluate() const override |
234 | { return myLHS->evaluate() || myRHS->evaluate(); } |
235 | }; |
236 | |
237 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
238 | class MinusExpression : public Expression |
239 | { |
240 | public: |
241 | MinusExpression(Expression* left, Expression* right) : Expression(left, right) { } |
242 | Int32 evaluate() const override |
243 | { return myLHS->evaluate() - myRHS->evaluate(); } |
244 | }; |
245 | |
246 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
247 | class ModExpression : public Expression |
248 | { |
249 | public: |
250 | ModExpression(Expression* left, Expression* right) : Expression(left, right) { } |
251 | Int32 evaluate() const override |
252 | { int rhs = myRHS->evaluate(); |
253 | return rhs == 0 ? 0 : myLHS->evaluate() % rhs; } |
254 | }; |
255 | |
256 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
257 | class MultExpression : public Expression |
258 | { |
259 | public: |
260 | MultExpression(Expression* left, Expression* right) : Expression(left, right) { } |
261 | Int32 evaluate() const override |
262 | { return myLHS->evaluate() * myRHS->evaluate(); } |
263 | }; |
264 | |
265 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
266 | class NotEqualsExpression : public Expression |
267 | { |
268 | public: |
269 | NotEqualsExpression(Expression* left, Expression* right) : Expression(left, right) { } |
270 | Int32 evaluate() const override |
271 | { return myLHS->evaluate() != myRHS->evaluate(); } |
272 | }; |
273 | |
274 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
275 | class PlusExpression : public Expression |
276 | { |
277 | public: |
278 | PlusExpression(Expression* left, Expression* right) : Expression(left, right) { } |
279 | Int32 evaluate() const override |
280 | { return myLHS->evaluate() + myRHS->evaluate(); } |
281 | }; |
282 | |
283 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
284 | class CartMethodExpression : public Expression |
285 | { |
286 | public: |
287 | CartMethodExpression(CartMethod method) : Expression(), myMethod(std::mem_fn(method)) { } |
288 | Int32 evaluate() const override |
289 | { return myMethod(Debugger::debugger().cartDebug()); } |
290 | |
291 | private: |
292 | std::function<int(CartDebug&)> myMethod; |
293 | }; |
294 | |
295 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
296 | class ShiftLeftExpression : public Expression |
297 | { |
298 | public: |
299 | ShiftLeftExpression(Expression* left, Expression* right) : Expression(left, right) { } |
300 | Int32 evaluate() const override |
301 | { return myLHS->evaluate() << myRHS->evaluate(); } |
302 | }; |
303 | |
304 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
305 | class ShiftRightExpression : public Expression |
306 | { |
307 | public: |
308 | ShiftRightExpression(Expression* left, Expression* right) : Expression(left, right) { } |
309 | Int32 evaluate() const override |
310 | { return myLHS->evaluate() >> myRHS->evaluate(); } |
311 | }; |
312 | |
313 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
314 | class TiaMethodExpression : public Expression |
315 | { |
316 | public: |
317 | TiaMethodExpression(TiaMethod method) : Expression(), myMethod(std::mem_fn(method)) { } |
318 | Int32 evaluate() const override |
319 | { return myMethod(Debugger::debugger().tiaDebug()); } |
320 | |
321 | private: |
322 | std::function<int(const TIADebug&)> myMethod; |
323 | }; |
324 | |
325 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
326 | class UnaryMinusExpression : public Expression |
327 | { |
328 | public: |
329 | UnaryMinusExpression(Expression* left) : Expression(left) { } |
330 | Int32 evaluate() const override |
331 | { return -(myLHS->evaluate()); } |
332 | }; |
333 | |
334 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
335 | class WordDerefExpression : public Expression |
336 | { |
337 | public: |
338 | WordDerefExpression(Expression* left) : Expression(left) { } |
339 | Int32 evaluate() const override |
340 | { return Debugger::debugger().dpeekAsInt(myLHS->evaluate()); } |
341 | }; |
342 | |
343 | #endif |
344 | |