1
1
#include " fixmatheval.h"
2
2
3
+ #include " common/math/bit_ops.h"
4
+ #include " memory/address.h"
5
+
3
6
#include < climits>
4
7
#include < utility>
5
8
6
9
using namespace fixmatheval ;
7
10
11
+ // Consumes part of string that is a valid symbol name, returns it and removes it from the input
12
+ // string.
13
+ QStringView tokenize_symbol (QStringView &expression) {
14
+ QStringView symbol = expression;
15
+ int i = 0 ;
16
+ for (QChar ch : expression) {
17
+ if (!(ch.isLetterOrNumber () || (ch == ' _' ))) { break ; }
18
+ i++;
19
+ }
20
+ expression = expression.mid (i);
21
+ return symbol;
22
+ }
23
+
8
24
FmeSymbolDb::~FmeSymbolDb () = default ;
9
25
10
26
bool FmeSymbolDb::getValue (FmeValue &value, QString name) {
@@ -48,9 +64,14 @@ FmeNodeConstant::FmeNodeConstant(FmeValue value) : FmeNode(INT_MAX) {
48
64
49
65
FmeNodeConstant::~FmeNodeConstant () = default ;
50
66
51
- bool FmeNodeConstant::eval (FmeValue &value, FmeSymbolDb *symdb, QString &error) {
52
- (void )symdb;
53
- (void )error;
67
+ bool FmeNodeConstant::eval (
68
+ FmeValue &value,
69
+ FmeSymbolDb *symdb,
70
+ QString &error,
71
+ machine::Address inst_addr) {
72
+ std::ignore = symdb;
73
+ std::ignore = error;
74
+ std::ignore = inst_addr;
54
75
value = this ->value ;
55
76
return true ;
56
77
}
@@ -65,15 +86,19 @@ FmeNodeSymbol::FmeNodeSymbol(QString &name) : FmeNode(INT_MAX) {
65
86
66
87
FmeNodeSymbol::~FmeNodeSymbol () = default ;
67
88
68
- bool FmeNodeSymbol::eval (FmeValue &value, FmeSymbolDb *symdb, QString &error) {
89
+ bool FmeNodeSymbol::eval (
90
+ FmeValue &value,
91
+ FmeSymbolDb *symdb,
92
+ QString &error,
93
+ machine::Address inst_addr) {
94
+ std::ignore = inst_addr;
95
+
69
96
if (!symdb) {
70
97
error = QString (" no symbol table to find value for %1" ).arg (name);
71
98
return false ;
72
99
}
73
100
bool ok = symdb->getValue (value, name);
74
- if (!ok) {
75
- error = QString (" value for symbol \" %1\" not found" ).arg (name);
76
- }
101
+ if (!ok) { error = QString (" value for symbol \" %1\" not found" ).arg (name); }
77
102
return ok;
78
103
}
79
104
@@ -83,7 +108,7 @@ QString FmeNodeSymbol::dump() {
83
108
84
109
FmeNodeUnaryOp::FmeNodeUnaryOp (
85
110
int priority,
86
- FmeValue (*op)(FmeValue &a),
111
+ FmeValue (*op)(FmeValue &a, machine::Address inst_addr ),
87
112
QString description)
88
113
: FmeNode(priority) {
89
114
this ->operand_a = nullptr ;
@@ -98,15 +123,12 @@ FmeNodeUnaryOp::~FmeNodeUnaryOp() {
98
123
bool FmeNodeUnaryOp::FmeNodeUnaryOp::eval (
99
124
FmeValue &value,
100
125
FmeSymbolDb *symdb,
101
- QString &error) {
126
+ QString &error,
127
+ machine::Address inst_addr) {
102
128
FmeValue value_a;
103
- if (!operand_a) {
104
- return false ;
105
- }
106
- if (!operand_a->eval (value_a, symdb, error)) {
107
- return false ;
108
- }
109
- value = op (value_a);
129
+ if (!operand_a) { return false ; }
130
+ if (!operand_a->eval (value_a, symdb, error, inst_addr)) { return false ; }
131
+ value = op (value_a, inst_addr);
110
132
return true ;
111
133
}
112
134
@@ -120,8 +142,7 @@ bool FmeNodeUnaryOp::insert(FmeNode *node) {
120
142
}
121
143
122
144
QString FmeNodeUnaryOp::dump () {
123
- return " (" + description + " " + (operand_a ? operand_a->dump () : " nullptr" )
124
- + " )" ;
145
+ return " (" + description + " " + (operand_a ? operand_a->dump () : " nullptr" ) + " )" ;
125
146
}
126
147
127
148
FmeNodeBinaryOp::FmeNodeBinaryOp (
@@ -141,14 +162,16 @@ FmeNodeBinaryOp::~FmeNodeBinaryOp() {
141
162
delete operand_b;
142
163
}
143
164
144
- bool FmeNodeBinaryOp::eval (FmeValue &value, FmeSymbolDb *symdb, QString &error) {
165
+ bool FmeNodeBinaryOp::eval (
166
+ FmeValue &value,
167
+ FmeSymbolDb *symdb,
168
+ QString &error,
169
+ machine::Address inst_addr) {
145
170
FmeValue value_a;
146
171
FmeValue value_b;
147
- if (!operand_a || !operand_b) {
148
- return false ;
149
- }
150
- if (!operand_a->eval (value_a, symdb, error)
151
- || !operand_b->eval (value_b, symdb, error)) {
172
+ if (!operand_a || !operand_b) { return false ; }
173
+ if (!operand_a->eval (value_a, symdb, error, inst_addr)
174
+ || !operand_b->eval (value_b, symdb, error, inst_addr)) {
152
175
return false ;
153
176
}
154
177
value = op (value_a, value_b);
@@ -165,8 +188,8 @@ bool FmeNodeBinaryOp::insert(FmeNode *node) {
165
188
}
166
189
167
190
QString FmeNodeBinaryOp::dump () {
168
- return " (" + (operand_a ? operand_a->dump () : " nullptr" ) + " " + description
169
- + " " + (operand_b ? operand_b->dump () : " nullptr" ) + " )" ;
191
+ return " (" + (operand_a ? operand_a->dump () : " nullptr" ) + " " + description + " "
192
+ + (operand_b ? operand_b->dump () : " nullptr" ) + " )" ;
170
193
}
171
194
172
195
FmeExpression::FmeExpression () : FmeNode(0 ) {
@@ -185,11 +208,9 @@ bool FmeExpression::parse(const QString &expression, QString &error) {
185
208
QString optxtx;
186
209
for (i = 0 ; true ; i++) {
187
210
QChar ch {};
188
- if (i < expression.size ()) {
189
- ch = expression.at (i);
190
- }
191
- if (!(ch.isLetterOrNumber () || (ch == ' _' ))
192
- || (i >= expression.size ())) {
211
+ if (i < expression.size ()) { ch = expression.at (i); }
212
+ if (!(ch.isLetterOrNumber () || (ch == ' _' )) || (i >= expression.size ())) {
213
+ if (ch.isSpace ()) { continue ; }
193
214
if (in_word) {
194
215
FmeNode *new_node = nullptr ;
195
216
QString word = expression.mid (word_start, i - word_start);
@@ -212,63 +233,80 @@ bool FmeExpression::parse(const QString &expression, QString &error) {
212
233
213
234
in_word = false ;
214
235
is_unary = false ;
215
- if (i >= expression.size ()) {
216
- break ;
217
- }
218
236
}
219
- if (ch.isSpace ()) {
220
- continue ;
221
- }
222
- FmeValue (*binary_op)(FmeValue & a, FmeValue & b) = nullptr ;
223
- FmeValue (*unary_op)(FmeValue & a) = nullptr ;
237
+ if (i >= expression.size ()) { break ; }
238
+ FmeValue (*binary_op)(FmeValue &a, FmeValue &b) = nullptr ;
239
+ FmeValue (*unary_op)(FmeValue &a, machine::Address inst_addr) = nullptr ;
224
240
int prio = base_prio;
225
241
226
242
optxtx = ch;
227
- if (ch == ' ~' ) {
243
+ if (ch == ' %' ) {
244
+ // `%` MODIFIER `(` SYMBOL `)`
245
+ // MODIFIER := `hi` | `lo` | `pcrel_hi` | `pcrel_lo`
246
+
247
+ prio += 90 ;
248
+ // The opening parenthesis is peeked and asserted but not consumed.
249
+ QStringView expr = QStringView (expression).mid (i + 1 );
250
+ if (expr.startsWith (QStringLiteral (" hi(" ))) {
251
+ i += 2 ;
252
+ optxtx = QStringLiteral (" %hi" );
253
+ unary_op = [](FmeValue &a, machine::Address) -> FmeValue {
254
+ return get_bits (a, 31 , 12 );
255
+ };
256
+ } else if (expr.startsWith (QStringLiteral (" lo(" ))) {
257
+ i += 2 ;
258
+ optxtx = QStringLiteral (" %lo" );
259
+ unary_op = [](FmeValue &a, machine::Address) -> FmeValue {
260
+ return sign_extend (get_bits (a, 11 , 0 ), 12 );
261
+ };
262
+ } else if (expr.startsWith (QStringLiteral (" pcrel_hi(" ))) {
263
+ i += 8 ;
264
+ optxtx = QStringLiteral (" %pcrel_hi" );
265
+ unary_op = [](FmeValue &a, machine::Address inst_addr) -> FmeValue {
266
+ return get_bits (a - inst_addr.get_raw (), 31 , 12 )
267
+ + get_bit (a - inst_addr.get_raw (), 11 );
268
+ };
269
+ } else if (expr.startsWith (QStringLiteral (" pcrel_lo(" ))) {
270
+ i += 8 ;
271
+ optxtx = QStringLiteral (" %pcrel_lo" );
272
+ unary_op = [](FmeValue &a, machine::Address inst_addr) -> FmeValue {
273
+ return sign_extend (get_bits (a - inst_addr.get_raw () + 4 , 11 , 0 ), 12 );
274
+ };
275
+ } else {
276
+ auto modifier = tokenize_symbol (expr);
277
+ error = QString (" Unknown modifier \" %1\" " ).arg (modifier);
278
+ ok = false ;
279
+ break ;
280
+ }
281
+ } else if (ch == ' ~' ) {
228
282
prio += 90 ;
229
- unary_op = [](FmeValue &a) -> FmeValue { return ~a; };
283
+ unary_op = [](FmeValue &a, machine::Address ) -> FmeValue { return ~a; };
230
284
} else if (ch == ' -' ) {
231
285
if (is_unary) {
232
286
prio += 90 ;
233
- unary_op = [](FmeValue &a) -> FmeValue { return -a; };
287
+ unary_op = [](FmeValue &a, machine::Address ) -> FmeValue { return -a; };
234
288
} else {
235
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
236
- return a - b;
237
- };
289
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a - b; };
238
290
prio += 20 ;
239
291
}
240
292
} else if (ch == ' +' ) {
241
- if (is_unary) {
242
- continue ;
243
- }
244
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
245
- return a + b;
246
- };
293
+ if (is_unary) { continue ; }
294
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a + b; };
247
295
prio += 20 ;
248
296
} else if (ch == ' *' ) {
249
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
250
- return a * b;
251
- };
297
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a * b; };
252
298
prio += 30 ;
253
299
} else if (ch == ' /' ) {
254
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
255
- return a / b;
256
- };
300
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a / b; };
257
301
prio += 30 ;
258
302
} else if (ch == ' |' ) {
259
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
260
- return a | b;
261
- };
303
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a | b; };
262
304
prio += 10 ;
263
305
} else if (ch == ' &' ) {
264
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
265
- return a & b;
266
- };
306
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a & b; };
267
307
prio += 15 ;
268
308
} else if (ch == ' ^' ) {
269
- binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue {
270
- return a ^ b;
271
- };
309
+ binary_op = [](FmeValue &a, FmeValue &b) -> FmeValue { return a ^ b; };
272
310
prio += 15 ;
273
311
} else if (ch == ' (' ) {
274
312
base_prio += 100 ;
@@ -280,37 +318,29 @@ bool FmeExpression::parse(const QString &expression, QString &error) {
280
318
break ;
281
319
}
282
320
} else {
283
- error
284
- = QString (" Unknow character \" %1\" in expression." ).arg (ch);
321
+ error = QString (" Unknow character \" %1\" in expression." ).arg (ch);
285
322
ok = false ;
286
323
break ;
287
324
}
288
325
if ((binary_op != nullptr ) || (unary_op != nullptr )) {
289
326
FmeNode *node;
290
327
FmeNode *child;
291
- for (node = this ; (child = node->child ()) != nullptr ;
292
- node = child) {
293
- if (child->priority () >= prio) {
294
- break ;
295
- }
328
+ for (node = this ; (child = node->child ()) != nullptr ; node = child) {
329
+ if (child->priority () >= prio) { break ; }
296
330
}
297
331
if (binary_op != nullptr ) {
298
- ok = node->insert (
299
- new FmeNodeBinaryOp (prio, binary_op, child, optxtx));
332
+ ok = node->insert (new FmeNodeBinaryOp (prio, binary_op, child, optxtx));
300
333
is_unary = true ;
301
334
} else {
302
- ok = node->insert (
303
- new FmeNodeUnaryOp (prio, unary_op, optxtx));
335
+ ok = node->insert (new FmeNodeUnaryOp (prio, unary_op, optxtx));
304
336
}
305
337
if (!ok) {
306
338
error = QString (" parse stuck at \" %1\" " ).arg (QString (ch));
307
339
break ;
308
340
}
309
341
}
310
342
} else {
311
- if (!in_word) {
312
- word_start = i;
313
- }
343
+ if (!in_word) { word_start = i; }
314
344
in_word = true ;
315
345
}
316
346
}
@@ -323,11 +353,13 @@ FmeExpression::~FmeExpression() {
323
353
root = nullptr ;
324
354
}
325
355
326
- bool FmeExpression::eval (FmeValue &value, FmeSymbolDb *symdb, QString &error) {
327
- if (!root) {
328
- return false ;
329
- }
330
- return root->eval (value, symdb, error);
356
+ bool FmeExpression::eval (
357
+ FmeValue &value,
358
+ FmeSymbolDb *symdb,
359
+ QString &error,
360
+ machine::Address inst_addr) {
361
+ if (!root) { return false ; }
362
+ return root->eval (value, symdb, error, inst_addr);
331
363
}
332
364
333
365
bool FmeExpression::insert (FmeNode *node) {
0 commit comments