11#include " fixmatheval.h"
22
3+ #include " common/math/bit_ops.h"
4+ #include " memory/address.h"
5+
36#include < climits>
47#include < utility>
58
69using namespace fixmatheval ;
710
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+
824FmeSymbolDb::~FmeSymbolDb () = default ;
925
1026bool FmeSymbolDb::getValue (FmeValue &value, QString name) {
@@ -48,9 +64,14 @@ FmeNodeConstant::FmeNodeConstant(FmeValue value) : FmeNode(INT_MAX) {
4864
4965FmeNodeConstant::~FmeNodeConstant () = default ;
5066
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;
5475 value = this ->value ;
5576 return true ;
5677}
@@ -65,15 +86,19 @@ FmeNodeSymbol::FmeNodeSymbol(QString &name) : FmeNode(INT_MAX) {
6586
6687FmeNodeSymbol::~FmeNodeSymbol () = default ;
6788
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+
6996 if (!symdb) {
7097 error = QString (" no symbol table to find value for %1" ).arg (name);
7198 return false ;
7299 }
73100 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); }
77102 return ok;
78103}
79104
@@ -83,7 +108,7 @@ QString FmeNodeSymbol::dump() {
83108
84109FmeNodeUnaryOp::FmeNodeUnaryOp (
85110 int priority,
86- FmeValue (*op)(FmeValue &a),
111+ FmeValue (*op)(FmeValue &a, machine::Address inst_addr ),
87112 QString description)
88113 : FmeNode(priority) {
89114 this ->operand_a = nullptr ;
@@ -98,15 +123,12 @@ FmeNodeUnaryOp::~FmeNodeUnaryOp() {
98123bool FmeNodeUnaryOp::FmeNodeUnaryOp::eval (
99124 FmeValue &value,
100125 FmeSymbolDb *symdb,
101- QString &error) {
126+ QString &error,
127+ machine::Address inst_addr) {
102128 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);
110132 return true ;
111133}
112134
@@ -120,8 +142,7 @@ bool FmeNodeUnaryOp::insert(FmeNode *node) {
120142}
121143
122144QString FmeNodeUnaryOp::dump () {
123- return " (" + description + " " + (operand_a ? operand_a->dump () : " nullptr" )
124- + " )" ;
145+ return " (" + description + " " + (operand_a ? operand_a->dump () : " nullptr" ) + " )" ;
125146}
126147
127148FmeNodeBinaryOp::FmeNodeBinaryOp (
@@ -141,14 +162,16 @@ FmeNodeBinaryOp::~FmeNodeBinaryOp() {
141162 delete operand_b;
142163}
143164
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) {
145170 FmeValue value_a;
146171 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)) {
152175 return false ;
153176 }
154177 value = op (value_a, value_b);
@@ -165,8 +188,8 @@ bool FmeNodeBinaryOp::insert(FmeNode *node) {
165188}
166189
167190QString 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" ) + " )" ;
170193}
171194
172195FmeExpression::FmeExpression () : FmeNode(0 ) {
@@ -185,11 +208,9 @@ bool FmeExpression::parse(const QString &expression, QString &error) {
185208 QString optxtx;
186209 for (i = 0 ; true ; i++) {
187210 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 ; }
193214 if (in_word) {
194215 FmeNode *new_node = nullptr ;
195216 QString word = expression.mid (word_start, i - word_start);
@@ -212,63 +233,80 @@ bool FmeExpression::parse(const QString &expression, QString &error) {
212233
213234 in_word = false ;
214235 is_unary = false ;
215- if (i >= expression.size ()) {
216- break ;
217- }
218236 }
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 ;
224240 int prio = base_prio;
225241
226242 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 == ' ~' ) {
228282 prio += 90 ;
229- unary_op = [](FmeValue &a) -> FmeValue { return ~a; };
283+ unary_op = [](FmeValue &a, machine::Address ) -> FmeValue { return ~a; };
230284 } else if (ch == ' -' ) {
231285 if (is_unary) {
232286 prio += 90 ;
233- unary_op = [](FmeValue &a) -> FmeValue { return -a; };
287+ unary_op = [](FmeValue &a, machine::Address ) -> FmeValue { return -a; };
234288 } 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; };
238290 prio += 20 ;
239291 }
240292 } 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; };
247295 prio += 20 ;
248296 } 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; };
252298 prio += 30 ;
253299 } 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; };
257301 prio += 30 ;
258302 } 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; };
262304 prio += 10 ;
263305 } 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; };
267307 prio += 15 ;
268308 } 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; };
272310 prio += 15 ;
273311 } else if (ch == ' (' ) {
274312 base_prio += 100 ;
@@ -280,37 +318,29 @@ bool FmeExpression::parse(const QString &expression, QString &error) {
280318 break ;
281319 }
282320 } else {
283- error
284- = QString (" Unknow character \" %1\" in expression." ).arg (ch);
321+ error = QString (" Unknow character \" %1\" in expression." ).arg (ch);
285322 ok = false ;
286323 break ;
287324 }
288325 if ((binary_op != nullptr ) || (unary_op != nullptr )) {
289326 FmeNode *node;
290327 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 ; }
296330 }
297331 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));
300333 is_unary = true ;
301334 } else {
302- ok = node->insert (
303- new FmeNodeUnaryOp (prio, unary_op, optxtx));
335+ ok = node->insert (new FmeNodeUnaryOp (prio, unary_op, optxtx));
304336 }
305337 if (!ok) {
306338 error = QString (" parse stuck at \" %1\" " ).arg (QString (ch));
307339 break ;
308340 }
309341 }
310342 } else {
311- if (!in_word) {
312- word_start = i;
313- }
343+ if (!in_word) { word_start = i; }
314344 in_word = true ;
315345 }
316346 }
@@ -323,11 +353,13 @@ FmeExpression::~FmeExpression() {
323353 root = nullptr ;
324354}
325355
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);
331363}
332364
333365bool FmeExpression::insert (FmeNode *node) {
0 commit comments