| 1 |
42 |
Agner |
/**************************** assem2.cpp ********************************
|
| 2 |
|
|
* Author: Agner Fog
|
| 3 |
|
|
* Date created: 2017-04-17
|
| 4 |
|
|
* Last modified: 2021-08-11
|
| 5 |
|
|
* Version: 1.11
|
| 6 |
|
|
* Project: Binary tools for ForwardCom instruction set
|
| 7 |
|
|
* Module: assem.cpp
|
| 8 |
|
|
* Description:
|
| 9 |
|
|
* Module for assembling ForwardCom .as files.
|
| 10 |
|
|
* This module contains:
|
| 11 |
|
|
* - expression(): Interpretation of expressions containing operators and
|
| 12 |
|
|
* any type of operands.
|
| 13 |
|
|
* Copyright 2017-2021 GNU General Public License http://www.gnu.org/licenses
|
| 14 |
|
|
******************************************************************************/
|
| 15 |
|
|
#include "stdafx.h"
|
| 16 |
|
|
|
| 17 |
|
|
|
| 18 |
|
|
// Interpret and evaluate expression
|
| 19 |
|
|
SExpression CAssembler::expression(uint32_t tok1, uint32_t maxtok, uint32_t options) {
|
| 20 |
|
|
// tok1: index to first token,
|
| 21 |
|
|
// maxtok: maximum number of tokens to use,
|
| 22 |
|
|
// options: 0: normal,
|
| 23 |
|
|
// 1: unsigned
|
| 24 |
|
|
// 2: inside []. interpret as memory operand
|
| 25 |
|
|
// 4: interpret option = keyword
|
| 26 |
|
|
// 8: inside {}. has no meaning yet
|
| 27 |
|
|
// 0x10: check syntax and count tokens, but do not call functions or report numeric
|
| 28 |
|
|
// overflow, wrong operand types, or unknown names
|
| 29 |
|
|
|
| 30 |
|
|
// This function scans the tokens and finds the operator with lowest priority.
|
| 31 |
|
|
// The function is called recursively for each operand to this operator.
|
| 32 |
|
|
// The level of parantheses is saved in the brackets stack.
|
| 33 |
|
|
// The scanning terminates at any of these conditions:
|
| 34 |
|
|
// * a token that cannot be part of the expression is encountered
|
| 35 |
|
|
// * all tokens are used
|
| 36 |
|
|
// * a comma is encountered
|
| 37 |
|
|
// * an unmatched end bracket is encountered
|
| 38 |
|
|
|
| 39 |
|
|
uint32_t tok; // current token
|
| 40 |
|
|
uint32_t toklow = tok1; // operator with lowest priority
|
| 41 |
|
|
uint32_t tokcolon = 0; // matching triadic operator with lowest priority
|
| 42 |
|
|
uint32_t ntok = 0; // number of tokens used
|
| 43 |
|
|
uint32_t priority = 0; // priority of this operator
|
| 44 |
|
|
uint32_t bracketlevel = 0; // number of brackets in stack
|
| 45 |
|
|
uint32_t state = 0; // 0: expecting value, 1: after value, expecting operator or end
|
| 46 |
|
|
uint32_t i; // loop counter
|
| 47 |
|
|
uint32_t temp; // temporary result
|
| 48 |
|
|
uint32_t tokid; // token.id
|
| 49 |
|
|
int32_t symi; // symbol index
|
| 50 |
|
|
bool is_local = false; // symbol is local constant
|
| 51 |
|
|
uint8_t endbracket; // expected end bracket
|
| 52 |
|
|
|
| 53 |
|
|
SExpression exp1, exp2; // expressions during evaluation
|
| 54 |
|
|
zeroAllMembers(exp1); // reset exp1
|
| 55 |
|
|
exp1.tokens = 1;
|
| 56 |
|
|
|
| 57 |
|
|
for (tok = tok1; tok < tok1 + maxtok; tok++) {
|
| 58 |
|
|
if (lineError) {exp1.etype = 0; return exp1;}
|
| 59 |
|
|
if (tokens[tok].type == TOK_OPR) {
|
| 60 |
|
|
// operator found. search for brackets
|
| 61 |
|
|
if (tokens[tok].priority == 1 || tokens[tok].priority == 14) {
|
| 62 |
|
|
// bracket found. ?: operator treated as bracket here
|
| 63 |
|
|
switch (tokens[tok].id) {
|
| 64 |
|
|
case '?':
|
| 65 |
|
|
if (tokens[tok].priority > priority && bracketlevel == 0) { // if multiple ?:, split by the last one
|
| 66 |
|
|
priority = tokens[tok].priority; toklow = tok;
|
| 67 |
|
|
}
|
| 68 |
|
|
// continue in next case
|
| 69 |
|
|
case '(': case '[': case '{': // opening bracket. push on bracket stack
|
| 70 |
|
|
brackets.push(uint8_t(tokens[tok].id));
|
| 71 |
|
|
bracketlevel++;
|
| 72 |
|
|
state = 0;
|
| 73 |
|
|
break;
|
| 74 |
|
|
case ')': case ']': case '}': case ':': // closing bracket
|
| 75 |
|
|
if (bracketlevel == 0) {
|
| 76 |
|
|
goto EXIT_LOOP; // this end bracket is not part of the expression.
|
| 77 |
|
|
}
|
| 78 |
|
|
// remove matching opening bracket from stack
|
| 79 |
|
|
bracketlevel--;
|
| 80 |
|
|
endbracket = brackets.pop();
|
| 81 |
|
|
switch (endbracket) {
|
| 82 |
|
|
case '(': endbracket = ')'; break;
|
| 83 |
|
|
case '[': endbracket = ']'; break;
|
| 84 |
|
|
case '{': endbracket = '}'; break;
|
| 85 |
|
|
case '?': endbracket = ':'; break;
|
| 86 |
|
|
}
|
| 87 |
|
|
if (endbracket != tokens[tok].id) {
|
| 88 |
|
|
// end bracket does not match begin bracket
|
| 89 |
|
|
errors.report(tokens[tok].pos, tokens[tok].stringLength, ERR_BRACKET_END);
|
| 90 |
|
|
goto EXIT_LOOP;
|
| 91 |
|
|
}
|
| 92 |
|
|
if (tokens[tok].id == ':') {
|
| 93 |
|
|
if (bracketlevel == 0 && priority == 14 && tokcolon == 0) {
|
| 94 |
|
|
tokcolon = tok; // ':' matches current '?' with lowest priority
|
| 95 |
|
|
}
|
| 96 |
|
|
state = 0;
|
| 97 |
|
|
continue;
|
| 98 |
|
|
}
|
| 99 |
|
|
state = 1;
|
| 100 |
|
|
continue; // finished with this token
|
| 101 |
|
|
}
|
| 102 |
|
|
}
|
| 103 |
|
|
if (bracketlevel) continue; // don't search for priority inside brackets
|
| 104 |
|
|
|
| 105 |
|
|
if (state == 1) {
|
| 106 |
|
|
// expecting operator
|
| 107 |
|
|
if (tokens[tok].id == ';') break; // end at semicolon
|
| 108 |
|
|
if (tokens[tok].id == ',' && !(options & 2)) break; // end at comma, except inside []
|
| 109 |
|
|
if (tokens[tok].id == '=' && !(options & 6)) break; // end at =, except inside [] or when interpreting option = value
|
| 110 |
|
|
|
| 111 |
|
|
if (tokens[tok].priority >= priority) { // if multiple operators with same priority, split by the last one to get the first evaluated first
|
| 112 |
|
|
// operator with lower priority found
|
| 113 |
|
|
priority = tokens[tok].priority;
|
| 114 |
|
|
toklow = tok;
|
| 115 |
|
|
}
|
| 116 |
|
|
if (tokens[tok].priority == 3) state = 1; else state = 0; // state 0 except after monadic operator
|
| 117 |
|
|
}
|
| 118 |
|
|
else if (state == 0 && (tokens[tok].id == '-' || tokens[tok].id == '+' || tokens[tok].priority == 3)) {
|
| 119 |
|
|
// monadic operator
|
| 120 |
|
|
if (priority < 3) {
|
| 121 |
|
|
priority = 3; toklow = tok;
|
| 122 |
|
|
}
|
| 123 |
|
|
}
|
| 124 |
|
|
else {
|
| 125 |
|
|
errors.report(tokens[tok]); break; // unexpected operator
|
| 126 |
|
|
}
|
| 127 |
|
|
}
|
| 128 |
|
|
else {
|
| 129 |
|
|
// not an operator
|
| 130 |
|
|
if (bracketlevel) continue; // inside brackets: search only for end bracket
|
| 131 |
|
|
if (state == 0) {
|
| 132 |
|
|
// expecting value
|
| 133 |
|
|
switch (tokens[tok].type) {
|
| 134 |
|
|
case TOK_NAM: case TOK_LAB: case TOK_VAR: case TOK_SEC:
|
| 135 |
|
|
case TOK_NUM: case TOK_FLT: case TOK_CHA: case TOK_STR:
|
| 136 |
|
|
case TOK_REG: case TOK_SYM: case TOK_XPR: case TOK_OPT:
|
| 137 |
|
|
state = 1; // allowed value tokens
|
| 138 |
|
|
break;
|
| 139 |
|
|
case TOK_TYP:
|
| 140 |
|
|
state = 1; // type expression
|
| 141 |
|
|
break;
|
| 142 |
|
|
case TOK_HLL:
|
| 143 |
|
|
if (tokens[tok].id == HLL_FALSE || tokens[tok].id == HLL_TRUE) {
|
| 144 |
|
|
state = 1;
|
| 145 |
|
|
}
|
| 146 |
|
|
else {
|
| 147 |
|
|
errors.report(tokens[tok]);
|
| 148 |
|
|
}
|
| 149 |
|
|
break;
|
| 150 |
|
|
default:
|
| 151 |
|
|
errors.report(tokens[tok]); break;
|
| 152 |
|
|
}
|
| 153 |
|
|
}
|
| 154 |
|
|
else {
|
| 155 |
|
|
break; // no operator found after value. end here
|
| 156 |
|
|
}
|
| 157 |
|
|
}
|
| 158 |
|
|
}
|
| 159 |
|
|
EXIT_LOOP:
|
| 160 |
|
|
if (lineError) {exp1.etype = 0; return exp1;}
|
| 161 |
|
|
// number of tokens used
|
| 162 |
|
|
ntok = tok - tok1;
|
| 163 |
|
|
exp1.tokens = ntok;
|
| 164 |
|
|
if (bracketlevel) {
|
| 165 |
|
|
endbracket = brackets.pop();
|
| 166 |
|
|
errors.report(tokens[tok1].pos, tokens[tok].pos - tokens[tok1].pos, endbracket == '?' ? ERR_QUESTION_MARK : ERR_BRACKET_BEGIN);
|
| 167 |
|
|
if (exp1.etype == 0) exp1.etype = XPR_INT;
|
| 168 |
|
|
return exp1;
|
| 169 |
|
|
}
|
| 170 |
|
|
if (ntok == 0) { // no expression found
|
| 171 |
|
|
if (maxtok == 0 && tok > 0) tok--;
|
| 172 |
|
|
errors.report(tokens[tok].pos, tokens[tok].stringLength, ERR_MISSING_EXPR);
|
| 173 |
|
|
return exp1;
|
| 174 |
|
|
}
|
| 175 |
|
|
|
| 176 |
|
|
switch (priority) {
|
| 177 |
|
|
case 0: // no operator found. just an expression
|
| 178 |
|
|
if (ntok > 2 && tokens[tok1].type == TOK_OPR && tokens[tok1].priority == 1) {
|
| 179 |
|
|
// this is an expression in brackets
|
| 180 |
|
|
uint32_t option1 = options;
|
| 181 |
|
|
if (tokens[tok1].id == '[') {
|
| 182 |
|
|
if (options & 2) errors.report(tokens[tok1]); // nested [[]] not allowed
|
| 183 |
|
|
option1 |= 2;
|
| 184 |
|
|
}
|
| 185 |
|
|
if (tokens[tok1].id == '{') option1 |= 8;
|
| 186 |
|
|
// evaluate expression inside bracket
|
| 187 |
|
|
exp1 = expression(tok1 + 1, ntok - 2, option1);
|
| 188 |
|
|
exp1.tokens += 2;
|
| 189 |
|
|
goto RETURNEXP1;
|
| 190 |
|
|
}
|
| 191 |
|
|
else if (ntok == 1) {
|
| 192 |
|
|
// this is a single token. get value
|
| 193 |
|
|
switch (tokens[tok1].type) {
|
| 194 |
|
|
case TOK_LAB: case TOK_VAR: case TOK_SEC: case TOK_SYM:
|
| 195 |
|
|
exp1.etype = XPR_SYM1; // symbol address
|
| 196 |
|
|
exp1.sym3 = tokens[tok1].id;
|
| 197 |
|
|
symi = findSymbol(exp1.sym3);
|
| 198 |
|
|
// is symbol local with known value?
|
| 199 |
|
|
is_local = symi > 0 && symbols[symi].st_bind == STB_LOCAL && (symbols[symi].st_type == STT_CONSTANT || symbols[symi].st_type == STT_VARIABLE);
|
| 200 |
|
|
if (options & 2) { // symbol inside []
|
| 201 |
|
|
exp1.etype |= XPR_MEM;
|
| 202 |
|
|
exp1.sym3 = 0;
|
| 203 |
|
|
if (is_local) {
|
| 204 |
|
|
exp1.offset_mem = tokens[tok1].value.w;// don't take value from symbol, it may change
|
| 205 |
|
|
exp1.etype &= ~XPR_SYM1; // symbol reference no longer needed
|
| 206 |
|
|
exp1.etype |= XPR_OFFSET; // has offset
|
| 207 |
|
|
}
|
| 208 |
|
|
else {
|
| 209 |
|
|
exp1.sym1 = tokens[tok1].id;
|
| 210 |
|
|
}
|
| 211 |
|
|
if (exp1.etype & (XPR_FLT | XPR_STRING)) { // float or string not allowed in memory operand
|
| 212 |
|
|
errors.report(tokens[tok1].pos, tokens[tok1].stringLength, ERR_WRONG_TYPE);
|
| 213 |
|
|
}
|
| 214 |
|
|
}
|
| 215 |
|
|
else { // symbol outside []
|
| 216 |
|
|
if (is_local) {
|
| 217 |
|
|
if (symbols[symi].st_other & STV_FLOAT) exp1.etype |= XPR_FLT;
|
| 218 |
|
|
else exp1.etype |= XPR_INT;
|
| 219 |
|
|
exp1.value.i = tokens[tok1].value.u; // don't take value from symbol, it may change
|
| 220 |
|
|
if (symbols[symi].st_other & STV_STRING) {
|
| 221 |
|
|
exp1.etype = XPR_STRING;
|
| 222 |
|
|
exp1.sym2 = (uint32_t)symbols[symi].st_unitnum; // sym2 used for string length
|
| 223 |
|
|
}
|
| 224 |
|
|
else {
|
| 225 |
|
|
exp1.etype &= ~XPR_SYM1; // symbol reference no longer needed
|
| 226 |
|
|
exp1.sym3 = 0;
|
| 227 |
|
|
}
|
| 228 |
|
|
}
|
| 229 |
|
|
else {
|
| 230 |
|
|
exp1.etype |= XPR_INT; // type not known yet?
|
| 231 |
|
|
exp1.sym3 = tokens[tok1].id;
|
| 232 |
|
|
}
|
| 233 |
|
|
}
|
| 234 |
|
|
break;
|
| 235 |
|
|
case TOK_NUM:
|
| 236 |
|
|
if (options & 2) { // number inside [] is offset
|
| 237 |
|
|
exp1.etype = XPR_OFFSET; // integer value
|
| 238 |
|
|
exp1.offset_mem = (int32_t)interpretNumber((char*)buf()+tokens[tok1].pos, tokens[tok1].stringLength, &temp);
|
| 239 |
|
|
}
|
| 240 |
|
|
else { // number outside [] is operand
|
| 241 |
|
|
exp1.etype = XPR_INT; // integer value
|
| 242 |
|
|
exp1.value.i = interpretNumber((char*)buf() + tokens[tok1].pos, tokens[tok1].stringLength, &temp);
|
| 243 |
|
|
}
|
| 244 |
|
|
if (temp) errors.report(tokens[tok1]);
|
| 245 |
|
|
break;
|
| 246 |
|
|
case TOK_FLT:
|
| 247 |
|
|
exp1.etype = XPR_FLT; // floating point value
|
| 248 |
|
|
exp1.value.d = interpretFloat((char*)buf()+tokens[tok1].pos, tokens[tok1].stringLength);
|
| 249 |
|
|
if (options & 2) { // float not allowed in memory operand
|
| 250 |
|
|
errors.report(tokens[tok1].pos, tokens[tok1].stringLength, ERR_WRONG_TYPE);
|
| 251 |
|
|
}
|
| 252 |
|
|
break;
|
| 253 |
|
|
case TOK_CHA: { // character(s). convert to integer
|
| 254 |
|
|
exp1.etype = XPR_INT;
|
| 255 |
|
|
exp1.value.u = 0;
|
| 256 |
|
|
bool escape = false; // check for \ escape characters
|
| 257 |
|
|
int j = 0; // count characters
|
| 258 |
|
|
for (i = 0; i < tokens[tok1].stringLength; i++) {
|
| 259 |
|
|
uint8_t c = get<uint8_t>(tokens[tok1].pos + i);
|
| 260 |
|
|
if (c == '\\' && !escape) {
|
| 261 |
|
|
escape = true; continue; // escape next character
|
| 262 |
|
|
}
|
| 263 |
|
|
if (escape) { // special escape characters
|
| 264 |
|
|
switch (c) {
|
| 265 |
|
|
case '\\': break;
|
| 266 |
|
|
case 'n': c = '\n'; break;
|
| 267 |
|
|
case 'r': c = '\r'; break;
|
| 268 |
|
|
case 't': c = '\t'; break;
|
| 269 |
|
|
case '0': c = 0; break;
|
| 270 |
|
|
}
|
| 271 |
|
|
}
|
| 272 |
|
|
escape = false;
|
| 273 |
|
|
exp1.value.u += uint64_t(c) << j*8;
|
| 274 |
|
|
j++;
|
| 275 |
|
|
}
|
| 276 |
|
|
if (options & 2) { // string not allowed in memory operand
|
| 277 |
|
|
errors.report(tokens[tok1].pos, tokens[tok1].stringLength, ERR_WRONG_TYPE);
|
| 278 |
|
|
}
|
| 279 |
|
|
break;}
|
| 280 |
|
|
case TOK_STR: { // string
|
| 281 |
|
|
exp1.etype = XPR_STRING;
|
| 282 |
|
|
exp1.value.u = stringBuffer.dataSize(); // save position of string
|
| 283 |
|
|
exp1.sym2 = tokens[tok1].stringLength; // string length
|
| 284 |
|
|
bool escape = false; // check for \ escape characters
|
| 285 |
|
|
for (i = 0; i < tokens[tok1].stringLength; i++) {
|
| 286 |
|
|
char c = get<char>(tokens[tok1].pos + i);
|
| 287 |
|
|
if (c == '\\' && !escape) {
|
| 288 |
|
|
escape = true; continue; // escape next character
|
| 289 |
|
|
}
|
| 290 |
|
|
if (escape) { // special escape characters
|
| 291 |
|
|
switch (c) {
|
| 292 |
|
|
case '\\': escape = false; break;
|
| 293 |
|
|
case 'n': c = '\n'; break;
|
| 294 |
|
|
case 'r': c = '\r'; break;
|
| 295 |
|
|
case 't': c = '\t'; break;
|
| 296 |
|
|
case '0': c = 0; break;
|
| 297 |
|
|
}
|
| 298 |
|
|
}
|
| 299 |
|
|
if (escape && exp1.sym2) exp1.sym2--; // reduce length
|
| 300 |
|
|
stringBuffer.put(c);
|
| 301 |
|
|
escape = false;
|
| 302 |
|
|
}
|
| 303 |
|
|
stringBuffer.put(char(0)); // terminate string
|
| 304 |
|
|
if (options & 2) { // string not allowed in memory operand
|
| 305 |
|
|
errors.report(tokens[tok1].pos, tokens[tok1].stringLength, ERR_WRONG_TYPE);
|
| 306 |
|
|
}
|
| 307 |
|
|
break;}
|
| 308 |
|
|
case TOK_REG:
|
| 309 |
|
|
if (options & 2) { // register inside [] is base register
|
| 310 |
|
|
exp1.etype = XPR_BASE | XPR_MEM;
|
| 311 |
|
|
exp1.base = uint8_t(tokens[tok1].id);
|
| 312 |
|
|
if ((tokens[tok1].id & 0xFE0) == REG_SPEC) {
|
| 313 |
|
|
exp1.base = tokens[tok1].id >> 16; // special register. to do: check if register type is valid
|
| 314 |
|
|
}
|
| 315 |
|
|
}
|
| 316 |
|
|
else { // normal register operand
|
| 317 |
|
|
exp1.etype = XPR_REG | XPR_REG1;
|
| 318 |
|
|
exp1.reg1 = tokens[tok1].id;
|
| 319 |
|
|
}
|
| 320 |
|
|
break;
|
| 321 |
|
|
case TOK_NAM:
|
| 322 |
|
|
if ((options & 0x10) == 0) errors.report(tokens[tok1]);
|
| 323 |
|
|
exp1.etype |= XPR_UNRESOLV; // unresolved name
|
| 324 |
|
|
break;
|
| 325 |
|
|
case TOK_OPT:
|
| 326 |
|
|
exp1.etype = XPR_OPTION;
|
| 327 |
|
|
if ((tokens[tok1].id) == OPT_SCALAR) {
|
| 328 |
|
|
exp1.etype |= XPR_SCALAR;
|
| 329 |
|
|
}
|
| 330 |
|
|
else {
|
| 331 |
|
|
exp1.value.u = tokens[tok1].id;
|
| 332 |
|
|
}
|
| 333 |
|
|
break;
|
| 334 |
|
|
case TOK_XPR: // expression
|
| 335 |
|
|
if (tokens[tok1].value.u < expressions.numEntries()) {
|
| 336 |
|
|
exp1 = expressions[tokens[tok1].value.w];
|
| 337 |
|
|
exp1.tokens = ntok;
|
| 338 |
|
|
if ((exp1.etype & XPR_REG) && !(exp1.etype & XPR_MEM) && (options & 2)) { // register inside [] is base register
|
| 339 |
|
|
exp1.etype = XPR_BASE | XPR_MEM;
|
| 340 |
|
|
exp1.base = exp1.reg1;
|
| 341 |
|
|
exp1.reg1 = 0;
|
| 342 |
|
|
}
|
| 343 |
|
|
}
|
| 344 |
|
|
else errors.report(tokens[tok1]);
|
| 345 |
|
|
break;
|
| 346 |
|
|
case TOK_TYP:
|
| 347 |
|
|
exp1.etype = XPR_TYPENAME;
|
| 348 |
|
|
exp1.value.u = tokens[tok1].id;
|
| 349 |
|
|
break;
|
| 350 |
|
|
case TOK_HLL:
|
| 351 |
|
|
if (tokens[tok1].id == HLL_FALSE || tokens[tok1].id == HLL_TRUE) { // translate to constant
|
| 352 |
|
|
exp1.etype = XPR_INT;
|
| 353 |
|
|
exp1.value.u = tokens[tok1].id & 1;
|
| 354 |
|
|
}
|
| 355 |
|
|
else {
|
| 356 |
|
|
errors.report(tokens[tok1]);
|
| 357 |
|
|
}
|
| 358 |
|
|
break;
|
| 359 |
|
|
default:
|
| 360 |
|
|
errors.report(tokens[tok1]);
|
| 361 |
|
|
}
|
| 362 |
|
|
if (options & 2) exp1.etype |= XPR_MEM; // inside [], interpret as memory operand
|
| 363 |
|
|
goto RETURNEXP1;
|
| 364 |
|
|
}
|
| 365 |
|
|
else {
|
| 366 |
|
|
// unrecognized token
|
| 367 |
|
|
errors.report(tokens[tok1]);
|
| 368 |
|
|
}
|
| 369 |
|
|
break;
|
| 370 |
|
|
|
| 371 |
|
|
case 3: // monadic operator
|
| 372 |
|
|
if (toklow == tok1) { // operator comes first
|
| 373 |
|
|
exp1 = expression(toklow + 1, maxtok - 1, options); // evaluate the rest
|
| 374 |
|
|
if (exp1.etype & XPR_UNRESOLV) {
|
| 375 |
|
|
exp1.tokens++; // unresolved expression. return unresolved result
|
| 376 |
|
|
goto RETURNEXP1;
|
| 377 |
|
|
}
|
| 378 |
|
|
zeroAllMembers(exp2); // zero exp2
|
| 379 |
|
|
switch (tokens[toklow].id) {
|
| 380 |
|
|
case '+': // value is unchanged
|
| 381 |
|
|
exp1.tokens++;
|
| 382 |
|
|
goto RETURNEXP1;; // value is unchanged
|
| 383 |
|
|
case '-':
|
| 384 |
|
|
if (exp1.etype & (XPR_OP | XPR_REG | XPR_MEM)) {
|
| 385 |
|
|
exp1 = op1minus(exp1); // convert -(A+B) etc.
|
| 386 |
|
|
goto RETURNEXP1;
|
| 387 |
|
|
}
|
| 388 |
|
|
exp2 = exp1; // convert -A to 0-A
|
| 389 |
|
|
exp1.tokens = 0;
|
| 390 |
|
|
exp1.etype = XPR_INT;
|
| 391 |
|
|
exp1.value.i = 0;
|
| 392 |
|
|
tokid = '-';
|
| 393 |
|
|
break; // continue in dyadic operators with 0-exp2
|
| 394 |
|
|
case '!':
|
| 395 |
|
|
exp1.tokens++;
|
| 396 |
|
|
if (exp1.instruction == II_COMPARE
|
| 397 |
|
|
&& (exp1.etype & XPR_REG1) && (exp1.etype & (XPR_REG2 | XPR_INT | XPR_IMMEDIATE))) {
|
| 398 |
|
|
// compare instruction. invert condition
|
| 399 |
|
|
exp1.optionbits ^= 1;
|
| 400 |
|
|
exp1.etype |= XPR_OPTIONS;
|
| 401 |
|
|
if ((exp1.reg1 & REG_V) && (dataType & TYP_FLOAT)) exp1.optionbits ^= 8; // floating point compare. invert gives unordered
|
| 402 |
|
|
goto RETURNEXP1;
|
| 403 |
|
|
}
|
| 404 |
|
|
if (exp1.instruction == II_AND
|
| 405 |
|
|
&& (exp1.etype & XPR_REG1) && (exp1.etype & XPR_INT)) {
|
| 406 |
|
|
// test_bit/test_bits_or/jump instruction. invert condition
|
| 407 |
|
|
exp1.optionbits ^= 4;
|
| 408 |
|
|
exp1.etype |= XPR_OPTIONS;
|
| 409 |
|
|
goto RETURNEXP1;
|
| 410 |
|
|
}
|
| 411 |
|
|
if (exp1.instruction == II_TEST_BITS_AND && (exp1.etype & XPR_REG1) && (exp1.etype & XPR_INT)) {
|
| 412 |
|
|
// test_bits_and/jump instruction. invert condition
|
| 413 |
|
|
exp1.optionbits ^= 1;
|
| 414 |
|
|
exp1.etype |= XPR_OPTIONS;
|
| 415 |
|
|
goto RETURNEXP1;
|
| 416 |
|
|
}
|
| 417 |
|
|
if (exp1.etype & (XPR_MEM | XPR_REG)) { // '!' ambiguous on register and memory operands
|
| 418 |
|
|
errors.report(tokens[toklow].pos, tokens[toklow].stringLength, ERR_NOT_OP_AMBIGUOUS);
|
| 419 |
|
|
}
|
| 420 |
|
|
exp2.tokens = 0;
|
| 421 |
|
|
exp2.etype = XPR_INT;
|
| 422 |
|
|
exp2.value.i = 0;
|
| 423 |
|
|
tokid = '='+D2;
|
| 424 |
|
|
break; // continue in dyadic operators with exp1 == 0
|
| 425 |
|
|
case '~':
|
| 426 |
|
|
exp2.tokens = 0;
|
| 427 |
|
|
exp2.etype = XPR_INT;
|
| 428 |
|
|
exp2.value.i = -1;
|
| 429 |
|
|
tokid = '^';
|
| 430 |
|
|
break; // continue in dyadic operators with exp1 ^ -1
|
| 431 |
|
|
default:
|
| 432 |
|
|
errors.report(tokens[tok1]); // ++ and -- not supported in expression
|
| 433 |
|
|
return exp1;
|
| 434 |
|
|
}
|
| 435 |
|
|
goto DYADIC; // proceed to dyadic operator
|
| 436 |
|
|
}
|
| 437 |
|
|
else { // postfix ++ and --
|
| 438 |
|
|
errors.report(tokens[tok1+1]); // ++ and -- not supported in expression
|
| 439 |
|
|
}
|
| 440 |
|
|
goto RETURNEXP1;
|
| 441 |
|
|
|
| 442 |
|
|
case 14: // triadic operator ?:
|
| 443 |
|
|
// evaluate exp1 ? exp2 : exp3 for all expression types
|
| 444 |
|
|
return op3(tok1, toklow, tokcolon, maxtok, options);
|
| 445 |
|
|
|
| 446 |
|
|
default:; // continue below for dyadic operator
|
| 447 |
|
|
}
|
| 448 |
|
|
// dyadic operator. evaluate two subexpressions
|
| 449 |
|
|
exp1 = expression(tok1, toklow - tok1, options); // evaluate fist expression
|
| 450 |
|
|
if (exp1.tokens != toklow - tok1) errors.report(tokens[tok1 + exp1.tokens]);
|
| 451 |
|
|
if (lineError) return exp1;
|
| 452 |
|
|
|
| 453 |
|
|
exp2 = expression(toklow + 1, tok1 + maxtok - (toklow + 1), options); // evaluate second expression
|
| 454 |
|
|
ntok = toklow - tok1 + 1 + exp2.tokens;
|
| 455 |
|
|
tokid = tokens[toklow].id; // operator id
|
| 456 |
|
|
if (lineError) return exp1;
|
| 457 |
|
|
|
| 458 |
|
|
DYADIC:
|
| 459 |
|
|
exp1 = op2(tokid, exp1, exp2);
|
| 460 |
|
|
|
| 461 |
|
|
RETURNEXP1:
|
| 462 |
|
|
if (lineError) return exp1;
|
| 463 |
|
|
if (exp1.etype & XPR_ERROR) {
|
| 464 |
|
|
errors.report(tokens[toklow].pos, tokens[toklow].stringLength, exp1.value.w);
|
| 465 |
|
|
}
|
| 466 |
|
|
return exp1;
|
| 467 |
|
|
}
|
| 468 |
|
|
|
| 469 |
|
|
// Interpret dyadic expression with any type of operands
|
| 470 |
|
|
SExpression CAssembler::op2(uint32_t op, SExpression & exp1, SExpression & exp2) {
|
| 471 |
|
|
|
| 472 |
|
|
if ((exp1.etype | exp2.etype) & XPR_UNRESOLV) {
|
| 473 |
|
|
exp1.etype = XPR_UNRESOLV; // unresolved operand. make unresolved result
|
| 474 |
|
|
exp1.tokens += exp2.tokens + 1;
|
| 475 |
|
|
}
|
| 476 |
|
|
else if ((exp1.etype & exp2.etype & XPR_MEM)
|
| 477 |
|
|
//&& ((exp1.etype|exp2.etype) & (XPR_BASE|XPR_INDEX|XPR_OPTION|XPR_SYM1|XPR_SYM2|XPR_LIMIT|XPR_LENGTH|XPR_BROADC))
|
| 478 |
|
|
) {
|
| 479 |
|
|
exp1 = op2Memory(op, exp1, exp2); // generation of memory operand. both operands inside [] and contain not only constants
|
| 480 |
|
|
}
|
| 481 |
|
|
else if (exp1.etype == XPR_OPTION && op == '=') {
|
| 482 |
|
|
// option = value is handled by op2Memory
|
| 483 |
|
|
exp1 = op2Memory(op, exp1, exp2);
|
| 484 |
|
|
}
|
| 485 |
|
|
else if (exp1.etype & exp2.etype & XPR_SYM1) {
|
| 486 |
|
|
// adding or subtracting symbols and integers
|
| 487 |
|
|
exp1 = op2Memory(op, exp1, exp2);
|
| 488 |
|
|
}
|
| 489 |
|
|
else if ((exp1.etype & XPR_SYM2) && (exp2.etype & XPR_INT)) {
|
| 490 |
|
|
// (sym1-sym2)/const
|
| 491 |
|
|
exp1 = op2Memory(op, exp1, exp2);
|
| 492 |
|
|
}
|
| 493 |
|
|
// generation of instruction involving registers and/or memory operand:
|
| 494 |
|
|
// (don't rely on XPR_MEM flag here because we would catch expressions involving constants only inside [] )
|
| 495 |
|
|
//!else if ((exp1.etype | exp2.etype) & (XPR_REG | XPR_BASE /*| XPR_SYM1*/)) {
|
| 496 |
|
|
// else if ((exp1.etype | exp2.etype) & (XPR_REG | XPR_BASE | XPR_SYM1)) { //??
|
| 497 |
|
|
else if (((exp1.etype | exp2.etype) & (XPR_REG | XPR_BASE)) || (exp1.sym1 | exp2.sym1)) { //??
|
| 498 |
|
|
exp1 = op2Registers(op, exp1, exp2);
|
| 499 |
|
|
}
|
| 500 |
|
|
else if ((exp1.etype | exp2.etype) & XPR_STRING) {
|
| 501 |
|
|
exp1 = op2String(op, exp1, exp2); // string operation
|
| 502 |
|
|
}
|
| 503 |
|
|
else if ((exp1.etype & 0xF) == XPR_FLT || (exp2.etype & 0xF) == XPR_FLT) {
|
| 504 |
|
|
// dyadic operators for float // floating point operation
|
| 505 |
|
|
exp1 = op2Float(op, exp1, exp2);
|
| 506 |
|
|
}
|
| 507 |
|
|
else if ((exp1.etype & 0xF) == XPR_INT && (exp2.etype & 0xF) == XPR_INT) {
|
| 508 |
|
|
// dyadic operators for integers // integer operation
|
| 509 |
|
|
exp1 = op2Int(op, exp1, exp2);
|
| 510 |
|
|
}
|
| 511 |
|
|
else {
|
| 512 |
|
|
// other types
|
| 513 |
|
|
exp1.etype = XPR_ERROR;
|
| 514 |
|
|
exp1.value.u = ERR_WRONG_TYPE;
|
| 515 |
|
|
}
|
| 516 |
|
|
return exp1;
|
| 517 |
|
|
}
|
| 518 |
|
|
|
| 519 |
|
|
// Interpret dyadic expression with integer operands
|
| 520 |
|
|
SExpression CAssembler::op2Int(uint32_t op, SExpression const & exp1, SExpression const & exp2) {
|
| 521 |
|
|
SExpression expr = exp1;
|
| 522 |
|
|
expr.tokens = exp1.tokens + exp2.tokens + 1;
|
| 523 |
|
|
switch (op & ~OP_UNS) {
|
| 524 |
|
|
case '+':
|
| 525 |
|
|
expr.value.u = exp1.value.u + exp2.value.u;
|
| 526 |
|
|
break;
|
| 527 |
|
|
case '-':
|
| 528 |
|
|
expr.value.u = exp1.value.u - exp2.value.u;
|
| 529 |
|
|
break;
|
| 530 |
|
|
case '*':
|
| 531 |
|
|
expr.value.i = exp1.value.i * exp2.value.i;
|
| 532 |
|
|
break;
|
| 533 |
|
|
case '/':
|
| 534 |
|
|
if (exp2.value.i == 0) {
|
| 535 |
|
|
expr.etype |= XPR_ERROR;
|
| 536 |
|
|
expr.value.u = ERR_OVERFLOW;
|
| 537 |
|
|
break;
|
| 538 |
|
|
}
|
| 539 |
|
|
if (op & OP_UNS) expr.value.u = exp1.value.u / exp2.value.u; // unsigned division
|
| 540 |
|
|
else expr.value.i = exp1.value.i / exp2.value.i; // signed division
|
| 541 |
|
|
break;
|
| 542 |
|
|
case '%':
|
| 543 |
|
|
if (exp2.value.i == 0) {
|
| 544 |
|
|
expr.etype |= XPR_ERROR;
|
| 545 |
|
|
expr.value.u = ERR_OVERFLOW;
|
| 546 |
|
|
break;
|
| 547 |
|
|
}
|
| 548 |
|
|
if (op & OP_UNS) expr.value.u = exp1.value.u % exp2.value.u; // unsigned modulo
|
| 549 |
|
|
else expr.value.i = exp1.value.i % exp2.value.i; // signed modulo
|
| 550 |
|
|
break;
|
| 551 |
|
|
case '<' + D2: // <<
|
| 552 |
|
|
expr.value.u = exp1.value.u << exp2.value.u;
|
| 553 |
|
|
break;
|
| 554 |
|
|
case '>' + D2: // >> shift right signed
|
| 555 |
|
|
if (op & OP_UNS) expr.value.u = exp1.value.u >> exp2.value.u; // unsigned shift right
|
| 556 |
|
|
else expr.value.i = exp1.value.i >> exp2.value.i; // signed shift right
|
| 557 |
|
|
break;
|
| 558 |
|
|
case '>' + D3: // >>> unsigned shift right
|
| 559 |
|
|
expr.value.u = exp1.value.u >> exp2.value.u;
|
| 560 |
|
|
break;
|
| 561 |
|
|
case '<': // < compare
|
| 562 |
|
|
if (op & OP_UNS) expr.value.i = exp1.value.u < exp2.value.u; // unsigned compare
|
| 563 |
|
|
else expr.value.i = exp1.value.i < exp2.value.i; // signed compare
|
| 564 |
|
|
break;
|
| 565 |
|
|
case '<' + EQ: // <= compare
|
| 566 |
|
|
if (op & OP_UNS) expr.value.i = exp1.value.u <= exp2.value.u; // unsigned compare
|
| 567 |
|
|
else expr.value.i = exp1.value.i <= exp2.value.i; // signed compare
|
| 568 |
|
|
break;
|
| 569 |
|
|
case '>': // > compare
|
| 570 |
|
|
if (op & OP_UNS) expr.value.i = exp1.value.u > exp2.value.u; // unsigned compare
|
| 571 |
|
|
else expr.value.i = exp1.value.i > exp2.value.i; // signed compare
|
| 572 |
|
|
break;
|
| 573 |
|
|
case '>' + EQ: // >= compare
|
| 574 |
|
|
if (op & OP_UNS) expr.value.i = exp1.value.u >= exp2.value.u; // unsigned compare
|
| 575 |
|
|
else expr.value.i = exp1.value.i >= exp2.value.i; // signed compare
|
| 576 |
|
|
break;
|
| 577 |
|
|
case '=' + D2: // ==
|
| 578 |
|
|
expr.value.u = exp1.value.u == exp2.value.u;
|
| 579 |
|
|
break;
|
| 580 |
|
|
case '!' + EQ: // !=
|
| 581 |
|
|
expr.value.u = exp1.value.u != exp2.value.u;
|
| 582 |
|
|
break;
|
| 583 |
|
|
case '&': // bitwise and
|
| 584 |
|
|
expr.value.u = exp1.value.u & exp2.value.u;
|
| 585 |
|
|
break;
|
| 586 |
|
|
case '|': // bitwise or
|
| 587 |
|
|
expr.value.u = exp1.value.u | exp2.value.u;
|
| 588 |
|
|
break;
|
| 589 |
|
|
case '^': // bitwise xor
|
| 590 |
|
|
expr.value.u = exp1.value.u ^ exp2.value.u;
|
| 591 |
|
|
break;
|
| 592 |
|
|
case '&' + D2: // logical and
|
| 593 |
|
|
expr.value.u = exp1.value.u && exp2.value.u;
|
| 594 |
|
|
break;
|
| 595 |
|
|
case '|' + D2: // logical or
|
| 596 |
|
|
expr.value.u = exp1.value.u || exp2.value.u;
|
| 597 |
|
|
break;
|
| 598 |
|
|
case '^' + D2: // logical xor
|
| 599 |
|
|
expr.value.u = (exp1.value.u != 0) ^ (exp2.value.u != 0);
|
| 600 |
|
|
break;
|
| 601 |
|
|
default: // unsupported operator
|
| 602 |
|
|
expr.etype |= XPR_ERROR;
|
| 603 |
|
|
expr.value.u = ERR_WRONG_TYPE;
|
| 604 |
|
|
}
|
| 605 |
|
|
return expr;
|
| 606 |
|
|
}
|
| 607 |
|
|
|
| 608 |
|
|
// Interpret dyadic expression with floating point operands
|
| 609 |
|
|
SExpression CAssembler::op2Float(uint32_t op, SExpression & exp1, SExpression & exp2) {
|
| 610 |
|
|
SExpression expr = exp1;
|
| 611 |
|
|
expr.tokens = exp1.tokens + exp2.tokens + 1;
|
| 612 |
|
|
if (exp1.etype == XPR_INT) { // convert exp1 to float
|
| 613 |
|
|
exp1.value.d = (double)exp1.value.i;
|
| 614 |
|
|
expr.etype = XPR_FLT;
|
| 615 |
|
|
}
|
| 616 |
|
|
if (exp2.etype == XPR_INT) { // convert exp2 to float
|
| 617 |
|
|
exp2.value.d = (double)exp2.value.i;
|
| 618 |
|
|
expr.etype = XPR_FLT;
|
| 619 |
|
|
}
|
| 620 |
|
|
// dyadic operator on float
|
| 621 |
|
|
switch (op) {
|
| 622 |
|
|
case '+':
|
| 623 |
|
|
expr.value.d = exp1.value.d + exp2.value.d;
|
| 624 |
|
|
break;
|
| 625 |
|
|
case '-':
|
| 626 |
|
|
expr.value.d = exp1.value.d - exp2.value.d;
|
| 627 |
|
|
break;
|
| 628 |
|
|
case '*':
|
| 629 |
|
|
expr.value.d = exp1.value.d * exp2.value.d;
|
| 630 |
|
|
break;
|
| 631 |
|
|
case '/':
|
| 632 |
|
|
if (exp2.value.d == 0.) {
|
| 633 |
|
|
expr.etype |= XPR_ERROR;
|
| 634 |
|
|
expr.value.u = ERR_OVERFLOW;
|
| 635 |
|
|
break;
|
| 636 |
|
|
}
|
| 637 |
|
|
expr.value.d = exp1.value.d / exp2.value.d;
|
| 638 |
|
|
break;
|
| 639 |
|
|
case '<': // signed compare
|
| 640 |
|
|
expr.value.i = exp1.value.d < exp2.value.d;
|
| 641 |
|
|
expr.etype = XPR_INT;
|
| 642 |
|
|
break;
|
| 643 |
|
|
case '<' + EQ: // <= signed compare
|
| 644 |
|
|
expr.value.i = exp1.value.d <= exp2.value.d;
|
| 645 |
|
|
expr.etype = XPR_INT;
|
| 646 |
|
|
break;
|
| 647 |
|
|
case '>': // signed compare
|
| 648 |
|
|
expr.value.i = exp1.value.d > exp2.value.d;
|
| 649 |
|
|
expr.etype = XPR_INT;
|
| 650 |
|
|
break;
|
| 651 |
|
|
case '>' + EQ: // >= signed compare
|
| 652 |
|
|
expr.value.i = exp1.value.d <= exp2.value.d;
|
| 653 |
|
|
expr.etype = XPR_INT;
|
| 654 |
|
|
break;
|
| 655 |
|
|
case '=' + D2: // ==
|
| 656 |
|
|
expr.value.i = exp1.value.d == exp2.value.d;
|
| 657 |
|
|
expr.etype = XPR_INT;
|
| 658 |
|
|
break;
|
| 659 |
|
|
case '!' + EQ: // !=
|
| 660 |
|
|
expr.value.i = exp1.value.d != exp2.value.d;
|
| 661 |
|
|
expr.etype = XPR_INT;
|
| 662 |
|
|
break;
|
| 663 |
|
|
case '&' + D2: // logical and
|
| 664 |
|
|
expr.value.i = exp1.value.d != 0. && exp2.value.d != 0.;
|
| 665 |
|
|
expr.etype = XPR_INT; break;
|
| 666 |
|
|
break;
|
| 667 |
|
|
case '|' + D2: // logical or
|
| 668 |
|
|
expr.value.i = exp1.value.d != 0. || exp2.value.d != 0.;
|
| 669 |
|
|
expr.etype = XPR_INT; break;
|
| 670 |
|
|
break;
|
| 671 |
|
|
default: // unsupported operator
|
| 672 |
|
|
expr.etype |= XPR_ERROR;
|
| 673 |
|
|
expr.value.u = ERR_WRONG_TYPE;
|
| 674 |
|
|
}
|
| 675 |
|
|
return expr;
|
| 676 |
|
|
}
|
| 677 |
|
|
|
| 678 |
|
|
// Interpret dyadic expression with register or memory operands, generating instruction
|
| 679 |
|
|
SExpression CAssembler::op2Registers(uint32_t op, SExpression const & ex1, SExpression const & ex2) {
|
| 680 |
|
|
SExpression expr = {{0}}; // return expression
|
| 681 |
|
|
uint8_t swapped = false; // operands are swapped
|
| 682 |
|
|
uint8_t cannotSwap = false; // cannot swap operands because both contain vector registers
|
| 683 |
|
|
uint32_t i; // loop counter
|
| 684 |
|
|
|
| 685 |
|
|
// make array of the two expressions
|
| 686 |
|
|
SExpression exp12[2]; // copy of expressions
|
| 687 |
|
|
uint32_t numtokens = ex1.tokens + ex2.tokens + 1; // number of tokens
|
| 688 |
|
|
expr.tokens = numtokens;
|
| 689 |
|
|
|
| 690 |
|
|
// resolve nested expressions
|
| 691 |
|
|
if ((ex1.etype | ex2.etype) & XPR_OP) {
|
| 692 |
|
|
/*
|
| 693 |
|
|
if (op == '&' && (ex1.etype & XPR_REG) && !(ex1.etype & XPR_OP) && ex2.instruction == II_XOR && ((ex2.etype & 0xF) == XPR_INT) && ex2.value.i == -1) {
|
| 694 |
|
|
// A & (B ^ -1) = and_not(A,B). This instruction is removed
|
| 695 |
|
|
expr = ex1; expr.tokens = numtokens;
|
| 696 |
|
|
expr.etype |= XPR_OP;
|
| 697 |
|
|
expr.instruction = II_AND_NOT;
|
| 698 |
|
|
expr.reg2 = ex2.reg1;
|
| 699 |
|
|
return expr;
|
| 700 |
|
|
} */
|
| 701 |
|
|
// simplify both expressions if possible
|
| 702 |
|
|
exp12[0] = ex1; exp12[1] = ex2;
|
| 703 |
|
|
for (i = 0; i < 2; i++) {
|
| 704 |
|
|
if ((exp12[i].etype & (XPR_REG | XPR_MEM)) && (exp12[i].etype & XPR_IMMEDIATE) && exp12[i].value.i == 0) {
|
| 705 |
|
|
if (exp12[i].instruction == II_SUB_REV) {
|
| 706 |
|
|
// expression is -A converted to (0-A). change to register and sign bit
|
| 707 |
|
|
exp12[i].etype &= ~(XPR_OPTIONS | XPR_IMMEDIATE | XPR_OP);
|
| 708 |
|
|
exp12[i].instruction = 0;
|
| 709 |
|
|
exp12[i].optionbits = 1;
|
| 710 |
|
|
}
|
| 711 |
|
|
else if (exp12[i].instruction == II_MUL_ADD && exp12[i].value.i == 0) {
|
| 712 |
|
|
// expression is -A*B converted to (-A*B+0). change to A*B and sign bit
|
| 713 |
|
|
exp12[i].instruction = II_MUL;
|
| 714 |
|
|
exp12[i].optionbits = exp12[i].optionbits & 1;
|
| 715 |
|
|
exp12[i].etype &= ~(XPR_OPTIONS | XPR_IMMEDIATE);
|
| 716 |
|
|
}
|
| 717 |
|
|
else if (exp12[i].instruction == II_ADD_ADD && (exp12[i].etype & (XPR_INT | XPR_FLT)) && (exp12[i].optionbits & 3) == 3 && exp12[i].value.i == 0) {
|
| 718 |
|
|
// expression is -(A+B) converted to (-A-B+0). change to A+B and sign bit
|
| 719 |
|
|
exp12[i].etype &= ~(XPR_INT | XPR_FLT);
|
| 720 |
|
|
exp12[i].instruction = II_ADD;
|
| 721 |
|
|
exp12[i].optionbits ^= 3;
|
| 722 |
|
|
exp12[i].etype &= ~(XPR_OPTIONS | XPR_IMMEDIATE);
|
| 723 |
|
|
}
|
| 724 |
|
|
}
|
| 725 |
|
|
else if (exp12[i].instruction == II_SUB_REV) {
|
| 726 |
|
|
// change -A+B to -(A-B)
|
| 727 |
|
|
exp12[i].instruction = II_SUB;
|
| 728 |
|
|
exp12[i].optionbits ^= 3;
|
| 729 |
|
|
}
|
| 730 |
|
|
}
|
| 731 |
|
|
if ((exp12[0].etype & XPR_IMMEDIATE) && (exp12[1].etype & XPR_IMMEDIATE)) {
|
| 732 |
|
|
// both operands contain an immediate. combine the immediates if possible
|
| 733 |
|
|
|
| 734 |
|
|
bool isfloat[2]; // check if operands are float
|
| 735 |
|
|
for (i = 0; i < 2; i++) isfloat[i] = (exp12[i].etype & XPR_IMMEDIATE) == XPR_FLT;
|
| 736 |
|
|
|
| 737 |
|
|
// convert integer to float if the other operand is float
|
| 738 |
|
|
for (i = 0; i < 2; i++) {
|
| 739 |
|
|
if (isfloat[1-i] && !isfloat[i]) {
|
| 740 |
|
|
exp12[i].value.d = (double)exp12[i].value.i;
|
| 741 |
|
|
isfloat[i] = true;
|
| 742 |
|
|
}
|
| 743 |
|
|
}
|
| 744 |
|
|
|
| 745 |
|
|
if (op == '+' || op == '-') { // add or subtract operands and store in exp12[1]
|
| 746 |
|
|
uint8_t sign = 0;
|
| 747 |
|
|
switch (exp12[0].instruction) {
|
| 748 |
|
|
case II_ADD: case II_SUB_REV:
|
| 749 |
|
|
sign = exp12[0].optionbits >> 1 & 1;
|
| 750 |
|
|
if (op == '-') sign ^= 1;
|
| 751 |
|
|
break;
|
| 752 |
|
|
case II_SUB:
|
| 753 |
|
|
sign = (exp12[0].optionbits >> 1 & 1) ^ 1;
|
| 754 |
|
|
if (op == '-') sign ^= 1;
|
| 755 |
|
|
break;
|
| 756 |
|
|
case II_ADD_ADD:
|
| 757 |
|
|
sign = exp12[0].optionbits >> 2 & 1;
|
| 758 |
|
|
if (op == '-') sign ^= 1;
|
| 759 |
|
|
break;
|
| 760 |
|
|
default: // no other instructions can be combined with + or -
|
| 761 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_OPERANDS;
|
| 762 |
|
|
return expr;
|
| 763 |
|
|
}
|
| 764 |
|
|
if (exp12[1].instruction == II_SUB) sign ^= 1;
|
| 765 |
|
|
|
| 766 |
|
|
// add immediates and store them in exp12[1]
|
| 767 |
|
|
if (sign) {
|
| 768 |
|
|
if (isfloat[1]) exp12[1].value.d -= exp12[0].value.d;
|
| 769 |
|
|
else exp12[1].value.i -= exp12[0].value.i;
|
| 770 |
|
|
}
|
| 771 |
|
|
else {
|
| 772 |
|
|
if (isfloat[1]) exp12[1].value.d += exp12[0].value.d;
|
| 773 |
|
|
else exp12[1].value.i += exp12[0].value.i;
|
| 774 |
|
|
}
|
| 775 |
|
|
exp12[0].value.i = 0;
|
| 776 |
|
|
exp12[0].etype &= ~ (XPR_INT | XPR_FLT);
|
| 777 |
|
|
if (exp12[0].instruction == II_ADD_ADD) {
|
| 778 |
|
|
exp12[0].instruction = II_ADD;
|
| 779 |
|
|
exp12[0].optionbits &= ~ 4;
|
| 780 |
|
|
}
|
| 781 |
|
|
else {
|
| 782 |
|
|
exp12[0].instruction = 0;
|
| 783 |
|
|
}
|
| 784 |
|
|
}
|
| 785 |
|
|
else if (op == '*' && exp12[0].instruction == II_MUL) {
|
| 786 |
|
|
if (isfloat[0]) {
|
| 787 |
|
|
exp12[1].value.d *= exp12[0].value.d;
|
| 788 |
|
|
}
|
| 789 |
|
|
else {
|
| 790 |
|
|
exp12[1].value.i *= exp12[0].value.i;
|
| 791 |
|
|
}
|
| 792 |
|
|
exp12[0].value.i = 0;
|
| 793 |
|
|
exp12[0].etype &= ~ (XPR_INT | XPR_FLT | XPR_OP);
|
| 794 |
|
|
exp12[0].instruction = 0;
|
| 795 |
|
|
} /*
|
| 796 |
|
|
else if (op == '&' && exp12[0].instruction == II_AND && !isfloat[0]) {
|
| 797 |
|
|
exp12[1].value.i &= exp12[0].value.i;
|
| 798 |
|
|
exp12[0].value.i = 0;
|
| 799 |
|
|
exp12[0].etype &= ~ XPR_INT;
|
| 800 |
|
|
exp12[0].instruction = 0;
|
| 801 |
|
|
}
|
| 802 |
|
|
else if (op == '|' && exp12[0].instruction == II_OR && !isfloat[0]) {
|
| 803 |
|
|
exp12[1].value.i |= exp12[0].value.i;
|
| 804 |
|
|
exp12[0].value.i = 0;
|
| 805 |
|
|
exp12[0].etype &= ~ XPR_INT;
|
| 806 |
|
|
exp12[0].instruction = 0;
|
| 807 |
|
|
}
|
| 808 |
|
|
else if (op == '^' && exp12[0].instruction == II_XOR && !isfloat[0]) {
|
| 809 |
|
|
exp12[1].value.i ^= exp12[0].value.i;
|
| 810 |
|
|
exp12[0].value.i = 0;
|
| 811 |
|
|
exp12[0].etype &= ~ XPR_INT;
|
| 812 |
|
|
exp12[0].instruction = 0;
|
| 813 |
|
|
} */
|
| 814 |
|
|
else {
|
| 815 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_OPERANDS;
|
| 816 |
|
|
}
|
| 817 |
|
|
}
|
| 818 |
|
|
|
| 819 |
|
|
// error if two memory operands
|
| 820 |
|
|
uint32_t etyp0 = exp12[0].etype, etyp1 = exp12[1].etype;
|
| 821 |
|
|
//if ((etyp0 & etyp1 & XPR_MEM) || (exp12[0].value.i && exp12[1].value.i)) {
|
| 822 |
|
|
if (etyp0 & etyp1 & XPR_MEM) {
|
| 823 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_OPERANDS;
|
| 824 |
|
|
return expr;
|
| 825 |
|
|
}
|
| 826 |
|
|
|
| 827 |
|
|
// error if too many operands
|
| 828 |
|
|
if (((etyp0 & XPR_REG1) != 0) + ((etyp0 & XPR_REG2) != 0) + ((etyp0 & XPR_REG3) != 0)
|
| 829 |
|
|
+ ((etyp1 & XPR_REG1) != 0) + ((etyp1 & XPR_REG2) != 0) + ((etyp1 & XPR_REG3) != 0)
|
| 830 |
|
|
+ (((etyp0 | etyp1) & XPR_MEM) != 0) + (((etyp0 | etyp1) & XPR_IMMEDIATE) != 0) > 3) {
|
| 831 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_TOO_MANY_OPERANDS;
|
| 832 |
|
|
return expr;
|
| 833 |
|
|
}
|
| 834 |
|
|
|
| 835 |
|
|
// check which operations can swap
|
| 836 |
|
|
if (op != '+' && op != '*' && op != '&' && op != '|' && op != '^' && op != '-') {
|
| 837 |
|
|
cannotSwap = true; // operation is not commutative ('-' is handled with sign bits)
|
| 838 |
|
|
}
|
| 839 |
|
|
|
| 840 |
|
|
// put operands in this order: register, memory, immediate
|
| 841 |
|
|
if ((exp12[0].etype & (XPR_IMMEDIATE | XPR_MEM)) && !(exp12[1].etype & XPR_IMMEDIATE) && !cannotSwap) {
|
| 842 |
|
|
// first operand is immediate or memory, and second operant is not immediate
|
| 843 |
|
|
// swap operands if not two vector registers
|
| 844 |
|
|
if (exp12[0].reg1 & exp12[1].reg1 & REG_V) {
|
| 845 |
|
|
// both operands contain a vector register. cannot swap. make error message later if swapping required
|
| 846 |
|
|
cannotSwap = true;
|
| 847 |
|
|
}
|
| 848 |
|
|
else if ((exp12[1].etype & XPR_MEM) && op == '*') {
|
| 849 |
|
|
// second operand also contains memory
|
| 850 |
|
|
cannotSwap = true;
|
| 851 |
|
|
}
|
| 852 |
|
|
else { // swap operands to get immediate or memory operand last
|
| 853 |
|
|
expr = exp12[0]; exp12[0] = exp12[1]; exp12[1] = expr;
|
| 854 |
|
|
if (op == '-') {
|
| 855 |
|
|
op = '+'; // convert '-' to '+' and flip sign bit to make operation commutative
|
| 856 |
|
|
exp12[0].optionbits ^= 1;
|
| 857 |
|
|
}
|
| 858 |
|
|
swapped = true;
|
| 859 |
|
|
}
|
| 860 |
|
|
}
|
| 861 |
|
|
|
| 862 |
|
|
if (op == '+' || op == '-') {
|
| 863 |
|
|
/* done above:
|
| 864 |
|
|
if (exp12[0].etype & (XPR_IMMEDIATE | XPR_MEM) && exp12[1].instruction == II_MUL && !(exp12[1].etype & (XPR_INT | XPR_FLT))) {
|
| 865 |
|
|
// (memory or constant) + reg*reg. swap operands
|
| 866 |
|
|
expr = exp12[0]; exp12[0] = exp12[1]; exp12[1] = expr;
|
| 867 |
|
|
if (op == '-') {
|
| 868 |
|
|
exp12[0].optionbits ^= 1; // invert signs in both operands
|
| 869 |
|
|
exp12[1].optionbits ^= 1;
|
| 870 |
|
|
}
|
| 871 |
|
|
} */
|
| 872 |
|
|
if (!((exp12[0].etype | exp12[1].etype) & XPR_OP)) {
|
| 873 |
|
|
// +/-R1 +/-R2
|
| 874 |
|
|
if (op == '-') exp12[1].optionbits ^= 1; // sign of second operand
|
| 875 |
|
|
// change sign of constant if this simplifies it
|
| 876 |
|
|
if ((exp12[1].etype & XPR_INT) && (exp12[1].optionbits & 1)) {
|
| 877 |
|
|
exp12[1].value.i = -exp12[1].value.i;
|
| 878 |
|
|
exp12[1].optionbits = 0;
|
| 879 |
|
|
}
|
| 880 |
|
|
else if ((exp12[1].etype & XPR_FLT) && (exp12[1].optionbits & 1)) {
|
| 881 |
|
|
exp12[1].value.d = -exp12[1].value.d;
|
| 882 |
|
|
exp12[1].optionbits = 0;
|
| 883 |
|
|
}
|
| 884 |
|
|
uint8_t s = exp12[0].optionbits | exp12[1].optionbits << 1; // combine signs
|
| 885 |
|
|
expr = exp12[1]; expr.tokens = numtokens;
|
| 886 |
|
|
expr.reg1 = exp12[0].reg1;
|
| 887 |
|
|
if (exp12[1].etype & XPR_REG1) {
|
| 888 |
|
|
expr.reg2 = exp12[1].reg1; expr.etype |= XPR_REG2;
|
| 889 |
|
|
}
|
| 890 |
|
|
expr.etype |= XPR_OP | XPR_REG1;
|
| 891 |
|
|
expr.optionbits = 0;
|
| 892 |
|
|
switch (s) {
|
| 893 |
|
|
case 0: // R1 + R2
|
| 894 |
|
|
expr.instruction = II_ADD; break;
|
| 895 |
|
|
case 1: // -R1 + R2
|
| 896 |
|
|
expr.instruction = II_SUB_REV; break;
|
| 897 |
|
|
case 2: // R1 - R2
|
| 898 |
|
|
expr.instruction = II_SUB; break;
|
| 899 |
|
|
case 3: // -R1 -R2
|
| 900 |
|
|
expr.instruction = II_ADD_ADD;
|
| 901 |
|
|
expr.value.i = 0;
|
| 902 |
|
|
expr.optionbits = s;
|
| 903 |
|
|
expr.etype |= XPR_INT | XPR_OPTIONS;
|
| 904 |
|
|
break;
|
| 905 |
|
|
}
|
| 906 |
|
|
return expr;
|
| 907 |
|
|
}
|
| 908 |
|
|
else if (exp12[0].instruction == II_MUL || exp12[1].instruction == II_MUL) {
|
| 909 |
|
|
// (A*B)+C
|
| 910 |
|
|
if (op == '-') exp12[1].optionbits ^= 1; // change sign if '-'
|
| 911 |
|
|
if (exp12[1].instruction == II_MUL) { // swap expressions if A+(B*C)
|
| 912 |
|
|
if (exp12[0].reg1 & REG_V) {
|
| 913 |
|
|
expr.etype |= XPR_ERROR;
|
| 914 |
|
|
expr.value.w = ERR_CANNOT_SWAP_VECT; // cannot put vector addend as first operand
|
| 915 |
|
|
return expr;
|
| 916 |
|
|
}
|
| 917 |
|
|
expr = exp12[0]; exp12[0] = exp12[1]; exp12[1] = expr; // swap expressions
|
| 918 |
|
|
}
|
| 919 |
|
|
expr = exp12[0] | exp12[1]; // combine expressions
|
| 920 |
|
|
expr.tokens = numtokens;
|
| 921 |
|
|
if ((exp12[0].etype & exp12[1].etype & (XPR_MEM|XPR_IMMEDIATE)) || // two memory or two immediate operands
|
| 922 |
|
|
((exp12[0].etype & (XPR_MEM|XPR_IMMEDIATE)) == (XPR_MEM|XPR_IMMEDIATE))) { // exp12[0] has both memory and immediate
|
| 923 |
|
|
expr.etype |= XPR_ERROR;
|
| 924 |
|
|
expr.value.w = ERR_TOO_COMPLEX;
|
| 925 |
|
|
return expr;
|
| 926 |
|
|
}
|
| 927 |
|
|
expr.instruction = II_MUL_ADD;
|
| 928 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 929 |
|
|
if (((exp12[0].etype & XPR_MEM) && !(exp12[1].etype & XPR_IMMEDIATE)) || (exp12[0].etype & XPR_IMMEDIATE)) {
|
| 930 |
|
|
expr.instruction = II_MUL_ADD2; // get A*C+B
|
| 931 |
|
|
// we don't need to do anything with signs here because the sign options apply to product and addend, not to specific operands
|
| 932 |
|
|
}
|
| 933 |
|
|
expr.etype |= XPR_OP;
|
| 934 |
|
|
expr.reg1 = exp12[0].reg1; expr.reg2 = exp12[0].reg2;
|
| 935 |
|
|
if (exp12[1].etype & XPR_REG) { // C has a register
|
| 936 |
|
|
if (exp12[0].etype & XPR_REG2) { // 3 registers
|
| 937 |
|
|
expr.reg3 = exp12[1].reg1;
|
| 938 |
|
|
expr.etype |= XPR_REG3;
|
| 939 |
|
|
}
|
| 940 |
|
|
else {
|
| 941 |
|
|
expr.reg2 = exp12[1].reg1; // 2 registers
|
| 942 |
|
|
expr.etype |= XPR_REG2;
|
| 943 |
|
|
}
|
| 944 |
|
|
}
|
| 945 |
|
|
// optionbits 0-1 = sign of product. optionbits 2-3 = sign of addend.
|
| 946 |
|
|
expr.optionbits = 3 * (exp12[0].optionbits & 1) | 0xC * (exp12[1].optionbits & 1);
|
| 947 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 948 |
|
|
return expr;
|
| 949 |
|
|
}
|
| 950 |
|
|
else if (exp12[0].instruction == II_ADD || exp12[0].instruction == II_SUB) {
|
| 951 |
|
|
// (A+B)+C
|
| 952 |
|
|
expr = exp12[0] | exp12[1]; // combine expressions
|
| 953 |
|
|
expr.tokens = numtokens;
|
| 954 |
|
|
expr.reg1 = exp12[0].reg1;
|
| 955 |
|
|
expr.etype |= XPR_OP;
|
| 956 |
|
|
expr.instruction = II_ADD_ADD;
|
| 957 |
|
|
|
| 958 |
|
|
if ((exp12[0].etype & XPR_IMMEDIATE) || ((exp12[0].etype & XPR_MEM) && !(exp12[1].etype & XPR_IMMEDIATE))) {
|
| 959 |
|
|
// does not fit
|
| 960 |
|
|
expr.etype |= XPR_ERROR;
|
| 961 |
|
|
expr.value.w = cannotSwap ? ERR_CANNOT_SWAP_VECT : ERR_TOO_COMPLEX;
|
| 962 |
|
|
return expr;
|
| 963 |
|
|
}
|
| 964 |
|
|
|
| 965 |
|
|
if (exp12[1].etype & XPR_REG) { // C has a register
|
| 966 |
|
|
if (exp12[0].etype & XPR_REG2) { // 3 registers
|
| 967 |
|
|
expr.reg3 = exp12[1].reg1;
|
| 968 |
|
|
expr.etype |= XPR_REG3;
|
| 969 |
|
|
}
|
| 970 |
|
|
else if (exp12[0].etype & XPR_REG1) { // 2 registers
|
| 971 |
|
|
expr.reg2 = exp12[1].reg1;
|
| 972 |
|
|
expr.etype |= XPR_REG2;
|
| 973 |
|
|
}
|
| 974 |
|
|
else {
|
| 975 |
|
|
expr.reg1 = exp12[1].reg1; // 1 registers
|
| 976 |
|
|
expr.etype |= XPR_REG1;
|
| 977 |
|
|
}
|
| 978 |
|
|
}
|
| 979 |
|
|
expr.optionbits = (exp12[0].optionbits & 3) | ((exp12[1].optionbits & 1) ^ (op == '-')) << 2;
|
| 980 |
|
|
if (exp12[0].instruction == II_SUB) expr.optionbits ^= 2;
|
| 981 |
|
|
if (swapped && op == '-') expr.optionbits ^= 7;
|
| 982 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 983 |
|
|
return expr;
|
| 984 |
|
|
|
| 985 |
|
|
}
|
| 986 |
|
|
else if (exp12[1].instruction == II_ADD || exp12[1].instruction == II_SUB) {
|
| 987 |
|
|
// A+(B+C)
|
| 988 |
|
|
expr = exp12[0] | exp12[1]; // combine expressions
|
| 989 |
|
|
expr.tokens = numtokens;
|
| 990 |
|
|
expr.reg1 = exp12[0].reg1;
|
| 991 |
|
|
expr.etype |= XPR_OP;
|
| 992 |
|
|
expr.instruction = II_ADD_ADD;
|
| 993 |
|
|
|
| 994 |
|
|
if (exp12[0].etype & exp12[1].etype & (XPR_IMMEDIATE | XPR_MEM)) {
|
| 995 |
|
|
// does not fit
|
| 996 |
|
|
expr.etype |= XPR_ERROR;
|
| 997 |
|
|
expr.value.w = ERR_TOO_COMPLEX;
|
| 998 |
|
|
return expr;
|
| 999 |
|
|
}
|
| 1000 |
|
|
|
| 1001 |
|
|
if (exp12[0].etype & XPR_MEM) {
|
| 1002 |
|
|
// A = mem, B = register, C = immediate. Needs additional reordering
|
| 1003 |
|
|
expr.optionbits = ((exp12[1].optionbits & 1) ^ (op == '-')) // register into first place
|
| 1004 |
|
|
| (exp12[0].optionbits & 1) << 1 // memory in second place
|
| 1005 |
|
|
| ((exp12[1].optionbits >> 1 & 1) ^ (op == '-')) << 2; // immediate in third place
|
| 1006 |
|
|
if (exp12[1].instruction == II_SUB) expr.optionbits ^= 4;
|
| 1007 |
|
|
if (swapped && op == '-') expr.optionbits ^= 7;
|
| 1008 |
|
|
expr.reg1 = exp12[1].reg1;
|
| 1009 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1010 |
|
|
return expr;
|
| 1011 |
|
|
}
|
| 1012 |
|
|
|
| 1013 |
|
|
|
| 1014 |
|
|
if (exp12[1].etype & XPR_REG2) {
|
| 1015 |
|
|
// 3 registers
|
| 1016 |
|
|
expr.reg2 = exp12[1].reg1;
|
| 1017 |
|
|
expr.reg3 = exp12[1].reg2;
|
| 1018 |
|
|
expr.etype |= XPR_REG2 | XPR_REG3;
|
| 1019 |
|
|
}
|
| 1020 |
|
|
else if (exp12[1].etype & XPR_REG1) {
|
| 1021 |
|
|
// 2 registers
|
| 1022 |
|
|
expr.reg2 = exp12[1].reg1;
|
| 1023 |
|
|
expr.etype |= XPR_REG2;
|
| 1024 |
|
|
}
|
| 1025 |
|
|
|
| 1026 |
|
|
expr.optionbits = (exp12[0].optionbits & 1) | 6 * ((exp12[1].optionbits & 1) ^ (op == '-'));
|
| 1027 |
|
|
if (exp12[1].instruction == II_SUB) expr.optionbits ^= 4;
|
| 1028 |
|
|
if (swapped && op == '-') expr.optionbits ^= 7;
|
| 1029 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1030 |
|
|
return expr;
|
| 1031 |
|
|
}
|
| 1032 |
|
|
}
|
| 1033 |
|
|
else if (!((exp12[0].etype | exp12[1].etype) & XPR_OP)
|
| 1034 |
|
|
&& (op == '*' || (op == '/' && !swapped))) {
|
| 1035 |
|
|
// (+/- a) * (+/- b)
|
| 1036 |
|
|
expr = exp12[0] | exp12[1];
|
| 1037 |
|
|
expr.etype |= XPR_OP;
|
| 1038 |
|
|
expr.tokens = numtokens;
|
| 1039 |
|
|
expr.optionbits = exp12[0].optionbits ^ exp12[1].optionbits;
|
| 1040 |
|
|
if (expr.optionbits & 1) { // change sign
|
| 1041 |
|
|
if ((exp12[1].etype & 0xF) == XPR_FLT) {
|
| 1042 |
|
|
expr.value.d = -exp12[1].value.d;
|
| 1043 |
|
|
expr.optionbits = 0;
|
| 1044 |
|
|
}
|
| 1045 |
|
|
else if ((exp12[1].etype & 0xF) == XPR_INT) {
|
| 1046 |
|
|
expr.value.i = -exp12[1].value.i;
|
| 1047 |
|
|
expr.optionbits = 0;
|
| 1048 |
|
|
}
|
| 1049 |
|
|
else if (/*(exp12[1].etype & XPR_REG) &&*/ op == '*' && expr.value.i == 0) {
|
| 1050 |
|
|
// change -a*b to -a*b + 0
|
| 1051 |
|
|
expr.instruction = II_MUL_ADD;
|
| 1052 |
|
|
expr.optionbits = 0x3;
|
| 1053 |
|
|
expr.reg1 = exp12[0].reg1;
|
| 1054 |
|
|
if (exp12[1].etype & XPR_REG1) {
|
| 1055 |
|
|
expr.reg2 = exp12[1].reg1; expr.etype |= XPR_REG2;
|
| 1056 |
|
|
}
|
| 1057 |
|
|
expr.etype |= XPR_INT | XPR_OPTIONS;
|
| 1058 |
|
|
return expr;
|
| 1059 |
|
|
}
|
| 1060 |
|
|
else {
|
| 1061 |
|
|
expr.etype |= XPR_ERROR; expr.value.w = ERR_TOO_COMPLEX;
|
| 1062 |
|
|
return expr;
|
| 1063 |
|
|
}
|
| 1064 |
|
|
}
|
| 1065 |
|
|
expr.reg1 = exp12[0].reg1;
|
| 1066 |
|
|
if (exp12[1].etype & XPR_REG1) {
|
| 1067 |
|
|
expr.reg2 = exp12[1].reg1; expr.etype |= XPR_REG2;
|
| 1068 |
|
|
}
|
| 1069 |
|
|
expr.instruction = (op == '*') ? II_MUL : II_DIV;
|
| 1070 |
|
|
return expr;
|
| 1071 |
|
|
}
|
| 1072 |
|
|
|
| 1073 |
|
|
else if (((exp12[0].etype & exp12[1].etype) & XPR_INT)
|
| 1074 |
|
|
&& (op == '='+D2 || op == '!'+EQ)
|
| 1075 |
|
|
&& exp12[0].value.i == exp12[1].value.i
|
| 1076 |
|
|
&& ((exp12[0].etype | exp12[1].etype) & (XPR_REG1 | XPR_REG2)) == XPR_REG1
|
| 1077 |
|
|
&& (exp12[0].etype & exp12[1].etype & XPR_REG1) == 0) {
|
| 1078 |
|
|
// (r1 & const) == const gives test_bits_and
|
| 1079 |
|
|
expr = exp12[0] | exp12[1];
|
| 1080 |
|
|
expr.etype |= XPR_OP | XPR_OPTIONS;
|
| 1081 |
|
|
expr.tokens = numtokens;
|
| 1082 |
|
|
expr.instruction = II_TEST_BITS_AND;
|
| 1083 |
|
|
if (op == '!'+EQ) expr.optionbits ^= 1;
|
| 1084 |
|
|
return expr;
|
| 1085 |
|
|
}
|
| 1086 |
|
|
else if (op == '&'+D2 || op == '|'+D2 || op == '^' || op == '^'+D2) {
|
| 1087 |
|
|
// possible combination of compare or test with extra boolean operand
|
| 1088 |
|
|
int swap = exp12[1].instruction != 0;
|
| 1089 |
|
|
expr = exp12[swap];
|
| 1090 |
|
|
if (expr.instruction == II_COMPARE && exp12[1-swap].etype == (XPR_REG | XPR_REG1)) {
|
| 1091 |
|
|
// use fallback register as an extra boolean operand on compare instruction
|
| 1092 |
|
|
switch (op & 0xFF) {
|
| 1093 |
|
|
case '&':
|
| 1094 |
|
|
expr.optionbits |= 0x10; break;
|
| 1095 |
|
|
case '|':
|
| 1096 |
|
|
expr.optionbits |= 0x20; break;
|
| 1097 |
|
|
case '^':
|
| 1098 |
|
|
expr.optionbits |= 0x30; break;
|
| 1099 |
|
|
default:
|
| 1100 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_TOO_COMPLEX;
|
| 1101 |
|
|
}
|
| 1102 |
|
|
expr.etype |= XPR_OP | XPR_OPTIONS | XPR_FALLBACK;
|
| 1103 |
|
|
expr.tokens = numtokens;
|
| 1104 |
|
|
expr.fallback = exp12[1-swap].reg1;
|
| 1105 |
|
|
return expr;
|
| 1106 |
|
|
}
|
| 1107 |
|
|
/*else if (expr.instruction >= II_TEST_BIT && expr.instruction <= II_TEST_BITS_OR && exp12[1-swap].etype == (XPR_REG | XPR_REG1)) {
|
| 1108 |
|
|
// Use fallback register as an extra boolean operand on bit test instructions
|
| 1109 |
|
|
// This does not work yet. test_bit cannot be expressed with high level operators
|
| 1110 |
|
|
switch (op & 0xFF) {
|
| 1111 |
|
|
case '&':
|
| 1112 |
|
|
expr.optionbits |= 0x01; break;
|
| 1113 |
|
|
case '|':
|
| 1114 |
|
|
expr.optionbits |= 0x02; break;
|
| 1115 |
|
|
case '^':
|
| 1116 |
|
|
expr.optionbits |= 0x03; break;
|
| 1117 |
|
|
default:
|
| 1118 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_TOO_COMPLEX;
|
| 1119 |
|
|
}
|
| 1120 |
|
|
expr.etype |= XPR_OP | XPR_OPTIONS | XPR_FALLBACK;
|
| 1121 |
|
|
expr.tokens = numtokens;
|
| 1122 |
|
|
expr.fallback = exp12[1-swap].reg1;
|
| 1123 |
|
|
return expr;
|
| 1124 |
|
|
}*/
|
| 1125 |
|
|
}
|
| 1126 |
|
|
}
|
| 1127 |
|
|
|
| 1128 |
|
|
// not a complex expression
|
| 1129 |
|
|
if ((ex1.etype & (XPR_IMMEDIATE | XPR_MEM)) && !((ex1.reg1 & REG_V) || (ex2.etype & XPR_IMMEDIATE))){
|
| 1130 |
|
|
// first operand is integer, float or memory. swap operands if not two vector registers or memory and immediate
|
| 1131 |
|
|
exp12[0] = ex2; exp12[1] = ex1; swapped = true;
|
| 1132 |
|
|
}
|
| 1133 |
|
|
else {
|
| 1134 |
|
|
exp12[0] = ex1; exp12[1] = ex2;
|
| 1135 |
|
|
}
|
| 1136 |
|
|
expr.etype |= (exp12[1].etype & XPR_REG1) << 1; // XPR_REG1 becomes XPR_REG2
|
| 1137 |
|
|
|
| 1138 |
|
|
// combine everything from the two operands
|
| 1139 |
|
|
expr = exp12[0] | exp12[1];
|
| 1140 |
|
|
expr.etype |= XPR_OP;
|
| 1141 |
|
|
expr.tokens = numtokens;
|
| 1142 |
|
|
expr.reg1 = exp12[0].reg1;
|
| 1143 |
|
|
expr.reg2 = exp12[1].reg1;
|
| 1144 |
|
|
expr.etype |= (exp12[1].etype & XPR_REG1) << 1;
|
| 1145 |
|
|
|
| 1146 |
|
|
if (expr.instruction) {
|
| 1147 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_TOO_COMPLEX;
|
| 1148 |
|
|
return expr;
|
| 1149 |
|
|
}
|
| 1150 |
|
|
// 2-operand instruction
|
| 1151 |
|
|
switch (op) {
|
| 1152 |
|
|
case '+':
|
| 1153 |
|
|
expr.instruction = II_ADD; break;
|
| 1154 |
|
|
case '-':
|
| 1155 |
|
|
expr.instruction = swapped ? II_SUB_REV : II_SUB; break;
|
| 1156 |
|
|
case '*':
|
| 1157 |
|
|
expr.instruction = II_MUL; break;
|
| 1158 |
|
|
case '/':
|
| 1159 |
|
|
expr.instruction = swapped ? II_DIV_REV : II_DIV; break;
|
| 1160 |
|
|
case '%':
|
| 1161 |
|
|
if (swapped) {expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_TYPE;}
|
| 1162 |
|
|
expr.instruction = II_REM; break;
|
| 1163 |
|
|
case '&': case '&'+D2: // boolean AND and bitwise AND have same implementation
|
| 1164 |
|
|
expr.instruction = II_AND; break;
|
| 1165 |
|
|
case '|': case '|'+D2: // boolean OR and bitwise OR have same implementation
|
| 1166 |
|
|
expr.instruction = II_OR; break;
|
| 1167 |
|
|
case '^': case '^'+D2:
|
| 1168 |
|
|
expr.instruction = II_XOR; break;
|
| 1169 |
|
|
case '<':
|
| 1170 |
|
|
expr.instruction = II_COMPARE;
|
| 1171 |
|
|
expr.optionbits = 2 ^ swapped;
|
| 1172 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1173 |
|
|
break;
|
| 1174 |
|
|
case '<' + EQ: // <=
|
| 1175 |
|
|
expr.instruction = II_COMPARE;
|
| 1176 |
|
|
expr.optionbits = 5 ^ swapped;
|
| 1177 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1178 |
|
|
break;
|
| 1179 |
|
|
case '>':
|
| 1180 |
|
|
expr.instruction = II_COMPARE;
|
| 1181 |
|
|
expr.optionbits = 4 ^ swapped;
|
| 1182 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1183 |
|
|
break;
|
| 1184 |
|
|
case '>' + EQ: // >=
|
| 1185 |
|
|
expr.instruction = II_COMPARE;
|
| 1186 |
|
|
expr.optionbits = 3 ^ swapped;
|
| 1187 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1188 |
|
|
break;
|
| 1189 |
|
|
case '='+D2: // ==
|
| 1190 |
|
|
expr.instruction = II_COMPARE;
|
| 1191 |
|
|
expr.optionbits = 0;
|
| 1192 |
|
|
//expr.etype |= XPR_OPTIONS;
|
| 1193 |
|
|
break;
|
| 1194 |
|
|
case '!'+EQ: // !=
|
| 1195 |
|
|
expr.instruction = II_COMPARE;
|
| 1196 |
|
|
expr.etype |= XPR_OPTIONS;
|
| 1197 |
|
|
expr.optionbits = 1; // compare for not equal
|
| 1198 |
|
|
if ((expr.reg1 & REG_V) && (dataType & TYP_FLOAT)) {
|
| 1199 |
|
|
expr.optionbits |= 8; // floating point not equal includes unordered
|
| 1200 |
|
|
}
|
| 1201 |
|
|
break;
|
| 1202 |
|
|
case '<' + D2: // <<
|
| 1203 |
|
|
if (swapped) {expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_TYPE;}
|
| 1204 |
|
|
expr.instruction = II_SHIFT_LEFT; break;
|
| 1205 |
|
|
case '>' + D2: // >>
|
| 1206 |
|
|
if (swapped) {expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_TYPE;}
|
| 1207 |
|
|
expr.instruction = II_SHIFT_RIGHT_S; break;
|
| 1208 |
|
|
case '>' + D3: // >>>
|
| 1209 |
|
|
if (swapped) {expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_TYPE;}
|
| 1210 |
|
|
expr.instruction = II_SHIFT_RIGHT_U; break;
|
| 1211 |
|
|
default:
|
| 1212 |
|
|
expr.etype |= XPR_ERROR; expr.value.u = ERR_WRONG_TYPE;
|
| 1213 |
|
|
}
|
| 1214 |
|
|
return expr;
|
| 1215 |
|
|
}
|
| 1216 |
|
|
|
| 1217 |
|
|
|
| 1218 |
|
|
// Interpret dyadic expression generating memory operand.
|
| 1219 |
|
|
// both expressions are inside [] or at least one contains components other than integer constants
|
| 1220 |
|
|
SExpression CAssembler::op2Memory(uint32_t op, SExpression & exp1, SExpression & exp2) {
|
| 1221 |
|
|
SExpression expr; // return value
|
| 1222 |
|
|
SExpression expt; // temporary value
|
| 1223 |
|
|
expr.tokens = exp1.tokens + exp2.tokens + 1; // total number of tokens
|
| 1224 |
|
|
uint64_t f; // temporary factor
|
| 1225 |
|
|
int32_t symi1 = 0, symi2 = 0; // symbol indexes
|
| 1226 |
|
|
|
| 1227 |
|
|
if (!((exp1.etype|exp2.etype) & (XPR_IMMEDIATE|XPR_BASE|XPR_INDEX|XPR_OPTION|XPR_SYM1|XPR_SYM2|XPR_LIMIT|XPR_LENGTH|XPR_BROADC))) {
|
| 1228 |
|
|
// combination of only integer expressions inside []
|
| 1229 |
|
|
// combine everything from the two operands
|
| 1230 |
|
|
expr = exp1 | exp2;
|
| 1231 |
|
|
expr.tokens = exp1.tokens + exp2.tokens + 1;
|
| 1232 |
|
|
expr.etype &= ~XPR_OP; expr.instruction = 0; // operator is resolved here
|
| 1233 |
|
|
switch (op) {
|
| 1234 |
|
|
case '+': // adding offsets
|
| 1235 |
|
|
expr.offset_mem = exp1.offset_mem + exp2.offset_mem;
|
| 1236 |
|
|
break;
|
| 1237 |
|
|
case '-': //
|
| 1238 |
|
|
expr.offset_mem = exp1.offset_mem - exp2.offset_mem;
|
| 1239 |
|
|
break;
|
| 1240 |
|
|
case '*':
|
| 1241 |
|
|
expr.offset_mem = exp1.offset_mem * exp2.offset_mem;
|
| 1242 |
|
|
break;
|
| 1243 |
|
|
case '/':
|
| 1244 |
|
|
if (exp2.offset_mem == 0) {
|
| 1245 |
|
|
expr.etype |= XPR_ERROR;
|
| 1246 |
|
|
expr.value.u = ERR_OVERFLOW;
|
| 1247 |
|
|
break;
|
| 1248 |
|
|
}
|
| 1249 |
|
|
expr.offset_mem = exp1.offset_mem / exp2.offset_mem;
|
| 1250 |
|
|
break;
|
| 1251 |
|
|
case '<' + D2: // <<
|
| 1252 |
|
|
expr.offset_mem = exp1.offset_mem << exp2.offset_mem;
|
| 1253 |
|
|
break;
|
| 1254 |
|
|
case '>' + D2: // >> shift right signed
|
| 1255 |
|
|
expr.offset_mem = exp1.offset_mem >> exp2.offset_mem; // signed shift right
|
| 1256 |
|
|
break;
|
| 1257 |
|
|
case '>' + D3: // >>> unsigned shift right
|
| 1258 |
|
|
expr.offset_mem = uint32_t(exp1.offset_mem) >> uint32_t(exp2.offset_mem); // unsigned shift right
|
| 1259 |
|
|
break;
|
| 1260 |
|
|
default: // wrong operator
|
| 1261 |
|
|
expr.value.u = ERR_WRONG_TYPE;
|
| 1262 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1263 |
|
|
}
|
| 1264 |
|
|
return expr;
|
| 1265 |
|
|
}
|
| 1266 |
|
|
|
| 1267 |
|
|
// not only integer expressions
|
| 1268 |
|
|
if ((exp2.etype & XPR_SYM1) && op == '-') {
|
| 1269 |
|
|
// subtracting two symbol addresses
|
| 1270 |
|
|
if (exp1.sym1) {
|
| 1271 |
|
|
exp2.sym2 = exp2.sym1; exp2.sym1 = 0;
|
| 1272 |
|
|
exp2.etype = (exp2.etype & ~XPR_SYM1) | XPR_SYM2;
|
| 1273 |
|
|
if (exp1.symscale1 == 0) exp1.symscale1 = 1;
|
| 1274 |
|
|
if (exp2.symscale1 == 0) exp2.symscale1 = 1;
|
| 1275 |
|
|
if (exp1.symscale1 != exp2.symscale1 || exp2.sym2 == 0) {
|
| 1276 |
|
|
exp1.value.u = ERR_CONFLICT_TYPE; // conflicting scale factors
|
| 1277 |
|
|
exp1.etype |= XPR_ERROR; return exp1;
|
| 1278 |
|
|
}
|
| 1279 |
|
|
}
|
| 1280 |
|
|
else if (exp1.sym3) {
|
| 1281 |
|
|
exp2.sym4 = exp2.sym3; exp2.sym3 = 0;
|
| 1282 |
|
|
exp2.etype = (exp2.etype & ~XPR_SYM1) | XPR_SYM2;
|
| 1283 |
|
|
if (exp1.symscale3 == 0) exp1.symscale3 = 1;
|
| 1284 |
|
|
if (exp2.symscale3 == 0) exp2.symscale3 = 1;
|
| 1285 |
|
|
if (exp1.symscale3 != exp2.symscale3 || exp2.sym4 == 0) {
|
| 1286 |
|
|
exp1.value.u = ERR_CONFLICT_TYPE; // conflicting scale factors
|
| 1287 |
|
|
exp1.etype |= XPR_ERROR; return exp1;
|
| 1288 |
|
|
}
|
| 1289 |
|
|
}
|
| 1290 |
|
|
else {
|
| 1291 |
|
|
exp1.value.u = ERR_CONFLICT_TYPE; // conflicting scale factors
|
| 1292 |
|
|
exp1.etype |= XPR_ERROR; return exp1;
|
| 1293 |
|
|
}
|
| 1294 |
|
|
}
|
| 1295 |
|
|
// error checks
|
| 1296 |
|
|
if (exp1.etype & exp2.etype & (XPR_SYM1 | XPR_SYM2 | XPR_SYMSCALE | XPR_INDEX
|
| 1297 |
|
|
| XPR_LIMIT | XPR_LENGTH | XPR_BROADC)) {
|
| 1298 |
|
|
exp1.value.u = ERR_MEM_COMPONENT_TWICE; // some component or option specified twice
|
| 1299 |
|
|
exp1.etype |= XPR_ERROR; return exp1;
|
| 1300 |
|
|
}
|
| 1301 |
|
|
if (((exp1.etype | exp2.etype) & (XPR_LIMIT | XPR_OFFSET)) == (XPR_LIMIT | XPR_OFFSET)) {
|
| 1302 |
|
|
exp1.value.u = ERR_LIMIT_AND_OFFSET; // cannot have both offset and limit
|
| 1303 |
|
|
exp1.etype |= XPR_ERROR; return exp1;
|
| 1304 |
|
|
}
|
| 1305 |
|
|
|
| 1306 |
|
|
if ((exp2.etype & XPR_BASE) && ((exp1.etype & XPR_BASE) || op == '-')) {
|
| 1307 |
|
|
// adding two registers or subtracting a register. make the second an index register
|
| 1308 |
|
|
if (exp2.base == 31 && (exp1.etype & XPR_BASE) && !(exp2.etype & XPR_INDEX)) {
|
| 1309 |
|
|
// stack pointer cannot be index. make first register an index instead
|
| 1310 |
|
|
exp1.index = exp1.base; exp1.base = 0;
|
| 1311 |
|
|
exp1.etype = (exp1.etype & ~XPR_BASE) | XPR_INDEX;
|
| 1312 |
|
|
exp1.scale = 1;
|
| 1313 |
|
|
}
|
| 1314 |
|
|
else {
|
| 1315 |
|
|
exp2.index = exp2.base; exp2.base = 0;
|
| 1316 |
|
|
exp2.etype = (exp2.etype & ~XPR_BASE) | XPR_INDEX;
|
| 1317 |
|
|
exp2.scale = 1;
|
| 1318 |
|
|
}
|
| 1319 |
|
|
}
|
| 1320 |
|
|
// combine everything from the two operands
|
| 1321 |
|
|
expr = exp1 | exp2;
|
| 1322 |
|
|
expr.tokens = exp1.tokens + exp2.tokens + 1;
|
| 1323 |
|
|
expr.value.u = exp1.value.u + exp2.value.u; // add values, except for special cases below
|
| 1324 |
|
|
expr.offset_mem = exp1.offset_mem + exp2.offset_mem; // add offsets, except for special cases below
|
| 1325 |
|
|
expr.offset_jump = exp1.offset_jump + exp2.offset_jump; // add jump offsets
|
| 1326 |
|
|
expr.etype &= ~XPR_OP; expr.instruction = 0; // operator is resolved here
|
| 1327 |
|
|
|
| 1328 |
|
|
switch (op) {
|
| 1329 |
|
|
case '+': // adding components. offsets have been added above
|
| 1330 |
|
|
/* Changed: immediate value outside [] cannot be converted to offset:
|
| 1331 |
|
|
if ((expr.etype & (XPR_REG | XPR_BASE | XPR_SYM1)) && (expr.etype & XPR_INT) && (expr.etype & XPR_MEM)) {
|
| 1332 |
|
|
// adding offset. convert value to offset
|
| 1333 |
|
|
expr.offset += expr.value.i;
|
| 1334 |
|
|
expr.value.i = 0;
|
| 1335 |
|
|
expr.etype = (expr.etype | XPR_OFFSET) & ~XPR_IMMEDIATE;
|
| 1336 |
|
|
} */
|
| 1337 |
|
|
break;
|
| 1338 |
|
|
case ',': // combining components. components are combined below
|
| 1339 |
|
|
if (exp1.value.u && exp2.value.u) {
|
| 1340 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot combine integer offsets with comma operator
|
| 1341 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1342 |
|
|
}
|
| 1343 |
|
|
if ((expr.etype & XPR_INDEX) && (expr.etype & (XPR_LENGTH | XPR_BROADC))) { // both index and broadcast
|
| 1344 |
|
|
if (expr.scale == -1) {
|
| 1345 |
|
|
if (expr.index != expr.length) { // scale = -1. index and length must be the same
|
| 1346 |
|
|
expr.value.u = ERR_NEG_INDEX_LENGTH;
|
| 1347 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1348 |
|
|
}
|
| 1349 |
|
|
}
|
| 1350 |
|
|
else { // cannot have index and length/broadcast
|
| 1351 |
|
|
expr.value.u = ERR_INDEX_AND_LENGTH;
|
| 1352 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1353 |
|
|
}
|
| 1354 |
|
|
}
|
| 1355 |
|
|
break;
|
| 1356 |
|
|
case '-': // subtract offsets or registers (symbol addresses subtracted above)
|
| 1357 |
|
|
/* Changed: immediate value outside [] cannot be converted to offset:
|
| 1358 |
|
|
if ((exp1.etype & (XPR_REG | XPR_BASE | XPR_SYM1)) && (exp2.etype & XPR_INT) && (expr.etype & XPR_MEM)) {
|
| 1359 |
|
|
// subtracting offset. convert value to offset
|
| 1360 |
|
|
expr.offset = exp1.offset - exp2.value.i;
|
| 1361 |
|
|
expr.value.i = 0;
|
| 1362 |
|
|
expr.etype = (expr.etype | XPR_OFFSET) & ~XPR_IMMEDIATE;
|
| 1363 |
|
|
}
|
| 1364 |
|
|
else */
|
| 1365 |
|
|
{
|
| 1366 |
|
|
expr.offset_mem = exp1.offset_mem - exp2.offset_mem;
|
| 1367 |
|
|
expr.offset_jump = exp1.offset_jump - exp2.offset_jump;
|
| 1368 |
|
|
expr.value.u = exp1.value.u - exp2.value.u;
|
| 1369 |
|
|
}
|
| 1370 |
|
|
if (exp2.etype & XPR_INDEX) { // subtracting a register gives negative index
|
| 1371 |
|
|
expr.scale = - exp2.scale;
|
| 1372 |
|
|
}
|
| 1373 |
|
|
else if ((exp1.etype & XPR_SYM1) && (exp2.etype & XPR_SYM2)) {
|
| 1374 |
|
|
// subtracting two symbols. has been fixed above
|
| 1375 |
|
|
// check if symbols are in the same domain
|
| 1376 |
|
|
if (exp1.sym1) {
|
| 1377 |
|
|
symi1 = findSymbol(exp1.sym1);
|
| 1378 |
|
|
symi2 = findSymbol(exp2.sym2);
|
| 1379 |
|
|
}
|
| 1380 |
|
|
else if (exp1.sym3) {
|
| 1381 |
|
|
symi1 = findSymbol(exp1.sym3);
|
| 1382 |
|
|
symi2 = findSymbol(exp2.sym4);
|
| 1383 |
|
|
}
|
| 1384 |
|
|
if (symi1 > 0 && symi2 > 0
|
| 1385 |
|
|
&& (symbols[symi1].st_other & symbols[symi2].st_other & (SHF_IP | SHF_DATAP | SHF_THREADP)) == 0
|
| 1386 |
|
|
&& (symbols[symi1].st_type & symbols[symi2].st_type & STT_CONSTANT) == 0) {
|
| 1387 |
|
|
errors.reportLine(ERR_RELOCATION_DOMAIN);
|
| 1388 |
|
|
}
|
| 1389 |
|
|
}
|
| 1390 |
|
|
//else if ((expr.etype & XPR_IMMEDIATE) == XPR_INT) expr.etype |= XPR_OFFSET; // value is offset
|
| 1391 |
|
|
if (exp2.etype & (XPR_SYM1|XPR_SYMSCALE)) {
|
| 1392 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot subtract these components
|
| 1393 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1394 |
|
|
}
|
| 1395 |
|
|
break;
|
| 1396 |
|
|
case '<'+D2: // index << s = index * (1 << s)
|
| 1397 |
|
|
//exp2.value.u = (uint64_t)1 << exp2.value.u;
|
| 1398 |
|
|
exp2.offset_mem = 1 << exp2.offset_mem;
|
| 1399 |
|
|
goto MULTIPLYINDEX; // continue in case '*'
|
| 1400 |
|
|
case '*': // indexregister * scale
|
| 1401 |
|
|
if ((exp1.etype & (XPR_INT|XPR_OFFSET)) && (exp2.etype & (XPR_BASE|XPR_INDEX))){
|
| 1402 |
|
|
// first operand is integer, second operand is register. swap operands
|
| 1403 |
|
|
expt = exp2; exp2 = exp1; exp1 = expt;
|
| 1404 |
|
|
}
|
| 1405 |
|
|
MULTIPLYINDEX:
|
| 1406 |
|
|
if ((exp1.etype & XPR_BASE) && !(exp1.etype & XPR_INDEX)) { // convert base to index
|
| 1407 |
|
|
exp1.index = exp1.base; exp1.base = 0; exp1.scale = 1;
|
| 1408 |
|
|
exp1.etype = (exp1.etype & ~XPR_BASE) | XPR_INDEX;
|
| 1409 |
|
|
}
|
| 1410 |
|
|
if (exp2.etype & XPR_INT) { // convert integer to offset. should not occur
|
| 1411 |
|
|
exp2.offset_mem = exp2.value.w; exp2.value.i = 0;
|
| 1412 |
|
|
exp2.etype = (exp2.etype & ~XPR_INT) | XPR_OFFSET;
|
| 1413 |
|
|
}
|
| 1414 |
|
|
if (!(exp1.etype & XPR_INDEX) || !(exp2.etype & XPR_OFFSET)
|
| 1415 |
|
|
|| ((exp1.etype | exp2.etype) & (XPR_OPTION|XPR_SYM1|XPR_SYM2|XPR_LIMIT|XPR_LENGTH|XPR_BROADC))) {
|
| 1416 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot multiply anything else
|
| 1417 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1418 |
|
|
}
|
| 1419 |
|
|
f = int64_t(exp2.offset_mem) * exp1.scale;
|
| 1420 |
|
|
if ((f & (f - 1)) || f == 0 || f > 16) { // check that scale is a power of 2, not bigger than 16
|
| 1421 |
|
|
expr.value.u = ERR_SCALE_FACTOR; // wrong scale factor
|
| 1422 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1423 |
|
|
}
|
| 1424 |
|
|
expr.base = exp1.base; expr.index = exp1.index;
|
| 1425 |
|
|
expr.scale = (int8_t)f;
|
| 1426 |
|
|
expr.etype = exp1.etype | (exp2.etype & ~(XPR_INT|XPR_OFFSET));
|
| 1427 |
|
|
expr.value.u = 0;
|
| 1428 |
|
|
expr.offset_mem = exp1.offset_mem;
|
| 1429 |
|
|
break;
|
| 1430 |
|
|
case '>'+D2: // divide (sym1-sym2) >> s = (sym1-sym2) / (1 << s)
|
| 1431 |
|
|
exp2.value.u = (uint64_t)1 << exp2.value.u;
|
| 1432 |
|
|
exp2.offset_mem = (uint64_t)1 << exp2.offset_mem;
|
| 1433 |
|
|
// continue in case '/'
|
| 1434 |
|
|
case '/': // divide (sym1-sym2) / scale
|
| 1435 |
|
|
if ((exp2.etype & XPR_OFFSET) && !(exp2.etype & (XPR_REG | XPR_INT | XPR_BASE))) {
|
| 1436 |
|
|
// constant has been interpreted as offset because it is inside []. change it to XPR_INT
|
| 1437 |
|
|
exp2.value.i = exp2.offset_mem; exp2.offset_mem = 0;
|
| 1438 |
|
|
exp2.etype = (exp2.etype & ~(XPR_OFFSET)) | XPR_INT;
|
| 1439 |
|
|
expr.offset_mem = exp1.offset_mem;
|
| 1440 |
|
|
}
|
| 1441 |
|
|
if (!(exp1.etype & XPR_SYM1) || ((exp2.etype & 0xF) != XPR_INT)
|
| 1442 |
|
|
|| ((exp1.etype | exp2.etype) & (XPR_REG|XPR_OPTION|XPR_LIMIT|XPR_LENGTH|XPR_BROADC))) {
|
| 1443 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot divide anything else
|
| 1444 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1445 |
|
|
}
|
| 1446 |
|
|
f = exp2.value.u;
|
| 1447 |
|
|
if (exp1.symscale1) f *= exp1.symscale1;
|
| 1448 |
|
|
if ((f & (f - 1)) || f == 0 || f > 16) { // check that scale is a power of 2, not bigger than 16
|
| 1449 |
|
|
expr.value.u = ERR_SCALE_FACTOR; // wrong scale factor
|
| 1450 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1451 |
|
|
}
|
| 1452 |
|
|
expr.symscale1 = (int8_t)f;
|
| 1453 |
|
|
expr.etype |= XPR_SYMSCALE;
|
| 1454 |
|
|
expr.etype = exp1.etype | (exp2.etype & ~XPR_INT);
|
| 1455 |
|
|
expr.value.u = exp1.value.u;
|
| 1456 |
|
|
break;
|
| 1457 |
|
|
case '=': // option = value
|
| 1458 |
|
|
// check if operands contain anything else
|
| 1459 |
|
|
if (!(exp1.etype & XPR_OPTION) || !(exp2.etype & (XPR_INT | XPR_BASE | XPR_REG))
|
| 1460 |
|
|
|| ((exp1.etype | exp2.etype) & (XPR_SYM1|XPR_SYM2|XPR_REG2|XPR_INDEX|XPR_LIMIT|XPR_LENGTH|XPR_BROADC))) {
|
| 1461 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot uses '=' on anyting else inside []
|
| 1462 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1463 |
|
|
}
|
| 1464 |
|
|
switch (exp1.value.w) {
|
| 1465 |
|
|
case OPT_LENGTH: // length = register
|
| 1466 |
|
|
if ((exp2.etype & XPR_REG1) && (exp2.reg1 & REG_R)) {
|
| 1467 |
|
|
// length = register, outside []
|
| 1468 |
|
|
expr.etype = XPR_LENGTH | XPR_MEM;
|
| 1469 |
|
|
expr.length = exp2.reg1;
|
| 1470 |
|
|
expr.base = 0;
|
| 1471 |
|
|
expr.value.i = 0;
|
| 1472 |
|
|
break;
|
| 1473 |
|
|
}
|
| 1474 |
|
|
// length = register, inside []
|
| 1475 |
|
|
if (!(exp2.etype & XPR_BASE) || (exp2.base & 0xE0) != REG_R) {
|
| 1476 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot uses '=' on anyting else inside []
|
| 1477 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1478 |
|
|
}
|
| 1479 |
|
|
expr.etype = XPR_LENGTH | XPR_MEM;
|
| 1480 |
|
|
expr.length = exp2.base;
|
| 1481 |
|
|
expr.base = 0;
|
| 1482 |
|
|
expr.value.i = 0;
|
| 1483 |
|
|
break;
|
| 1484 |
|
|
case OPT_BROADCAST: // broadcast = register
|
| 1485 |
|
|
if (!(exp2.etype & XPR_BASE) || (exp2.base & 0xE0) != REG_R) {
|
| 1486 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot uses '=' on anyting else inside []
|
| 1487 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1488 |
|
|
}
|
| 1489 |
|
|
expr.etype = XPR_BROADC | XPR_MEM;
|
| 1490 |
|
|
expr.length = exp2.base;
|
| 1491 |
|
|
expr.base = 0;
|
| 1492 |
|
|
expr.value.i = 0;
|
| 1493 |
|
|
break;
|
| 1494 |
|
|
case OPT_LIMIT: // limit = integer
|
| 1495 |
|
|
if (!(exp2.etype & XPR_INT)) {
|
| 1496 |
|
|
expr.value.u = ERR_WRONG_TYPE; // cannot uses '=' on anyting else inside []
|
| 1497 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1498 |
|
|
}
|
| 1499 |
|
|
if (exp1.etype & XPR_OFFSET) { // cannot have both limit and offset
|
| 1500 |
|
|
expr.etype = ERR_LIMIT_AND_OFFSET;
|
| 1501 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1502 |
|
|
}
|
| 1503 |
|
|
expr.etype = XPR_LIMIT | XPR_MEM;
|
| 1504 |
|
|
expr.value.u = exp2.value.u;
|
| 1505 |
|
|
break;
|
| 1506 |
|
|
case OPT_SCALAR: // scalar
|
| 1507 |
|
|
expr.etype = XPR_SCALAR | XPR_MEM;
|
| 1508 |
|
|
expr.value.i = 0;
|
| 1509 |
|
|
break;
|
| 1510 |
|
|
case OPT_MASK:
|
| 1511 |
|
|
if (!(exp2.etype & (XPR_REG | XPR_REG1))) {
|
| 1512 |
|
|
expr.etype = ERR_MASK_NOT_REGISTER;
|
| 1513 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1514 |
|
|
}
|
| 1515 |
|
|
expr.etype = XPR_MASK;
|
| 1516 |
|
|
expr.mask = exp2.reg1;
|
| 1517 |
|
|
expr.reg1 = 0;
|
| 1518 |
|
|
break;
|
| 1519 |
|
|
case OPT_FALLBACK:
|
| 1520 |
|
|
if (exp2.etype == (XPR_REG | XPR_REG1) && (exp2.reg1 & 0x1F) != 0x1F) {
|
| 1521 |
|
|
expr.fallback = exp2.reg1;
|
| 1522 |
|
|
expr.etype = XPR_FALLBACK;
|
| 1523 |
|
|
expr.reg1 = 0;
|
| 1524 |
|
|
}
|
| 1525 |
|
|
else if ((exp2.etype & XPR_IMMEDIATE) && exp2.value.i == 0){
|
| 1526 |
|
|
expr.fallback = (expr.mask & 0xF0) | 0x1F;
|
| 1527 |
|
|
expr.etype = XPR_FALLBACK;
|
| 1528 |
|
|
}
|
| 1529 |
|
|
else {
|
| 1530 |
|
|
expr.value.u = ERR_FALLBACK_WRONG;
|
| 1531 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1532 |
|
|
}
|
| 1533 |
|
|
break;
|
| 1534 |
|
|
case OPT_OPTIONS:
|
| 1535 |
|
|
if ((exp2.etype & 0xF) == XPR_INT) {
|
| 1536 |
|
|
expr.etype = (expr.etype & ~XPR_IMMEDIATE) | XPR_OPTIONS;
|
| 1537 |
|
|
expr.optionbits = (uint8_t)exp2.value.u; // move value to optionbits
|
| 1538 |
|
|
expr.value.i = 0;
|
| 1539 |
|
|
return expr;
|
| 1540 |
|
|
}
|
| 1541 |
|
|
else {
|
| 1542 |
|
|
expr.etype = ERR_WRONG_TYPE;
|
| 1543 |
|
|
expr.etype |= XPR_ERROR;
|
| 1544 |
|
|
return expr;
|
| 1545 |
|
|
}
|
| 1546 |
|
|
break;
|
| 1547 |
|
|
default: // mask and fallback options not allowed inside []
|
| 1548 |
|
|
expr.value.u = ERR_NOT_INSIDE_MEM; // change error message
|
| 1549 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1550 |
|
|
}
|
| 1551 |
|
|
break;
|
| 1552 |
|
|
|
| 1553 |
|
|
default: // wrong operator
|
| 1554 |
|
|
expr.value.u = ERR_WRONG_TYPE;
|
| 1555 |
|
|
expr.etype |= XPR_ERROR; return expr;
|
| 1556 |
|
|
}
|
| 1557 |
|
|
if ((expr.etype & XPR_INT) && !(expr.etype & (XPR_SYM1 | XPR_INDEX))) { // value not used otherwise is offset
|
| 1558 |
|
|
expr.etype = (expr.etype & ~(XPR_INT)) | XPR_OFFSET;
|
| 1559 |
|
|
}
|
| 1560 |
|
|
return expr;
|
| 1561 |
|
|
}
|
| 1562 |
|
|
|
| 1563 |
|
|
|
| 1564 |
|
|
// Interpreted triadic expression exp1 ? exp2 : exp3 at the indicated positions
|
| 1565 |
|
|
SExpression CAssembler::op3(uint32_t tok1, uint32_t toklow, uint32_t tokcolon, uint32_t maxtok, uint32_t options) {
|
| 1566 |
|
|
SExpression exp1, exp2;
|
| 1567 |
|
|
uint32_t cond; // evaluated condition
|
| 1568 |
|
|
|
| 1569 |
|
|
exp1 = expression(tok1, toklow - tok1, options); // evaluate expression before '?'
|
| 1570 |
|
|
if (exp1.tokens != toklow - tok1) errors.report(tokens[tok1 + exp1.tokens]);
|
| 1571 |
|
|
|
| 1572 |
|
|
if ((exp1.etype & XPR_REG) == 0 && (exp1.etype & (XPR_INT | XPR_FLT | XPR_STRING))) {
|
| 1573 |
|
|
// condition is a constant. just choose one of the two operands
|
| 1574 |
|
|
|
| 1575 |
|
|
if ((exp1.etype & 0xF) == XPR_FLT) cond = exp1.value.d != 0.; // evaluate condition to true or false
|
| 1576 |
|
|
else if ((exp1.etype & 0xF) == XPR_STRING) { // string is false if empty or "0"
|
| 1577 |
|
|
cond = (exp1.sym2 != 0 && (exp1.sym2 > 1 || stringBuffer.get<uint16_t>((uint32_t)exp1.value.u) != '0'));
|
| 1578 |
|
|
}
|
| 1579 |
|
|
else cond = exp1.value.i != 0;
|
| 1580 |
|
|
|
| 1581 |
|
|
// the expression that is not selected is evaluated with option = 0x10 to suppress errors but still count the tokens
|
| 1582 |
|
|
exp1 = expression(toklow + 1, tokcolon - (toklow + 1), options | (cond ^ 1) << 4); // evaluate first expression
|
| 1583 |
|
|
if (exp1.tokens != tokcolon - (toklow + 1)) errors.report(tokens[toklow + 1 + exp1.tokens]);
|
| 1584 |
|
|
exp2 = expression(tokcolon + 1, tok1 + maxtok - (tokcolon + 1), options | cond << 4); // evaluate second expression
|
| 1585 |
|
|
|
| 1586 |
|
|
// number of tokens
|
| 1587 |
|
|
exp1.tokens = exp2.tokens = tokcolon - tok1 + 1 + exp2.tokens;
|
| 1588 |
|
|
|
| 1589 |
|
|
// return the chosen expression
|
| 1590 |
|
|
if (cond) return exp1; else return exp2;
|
| 1591 |
|
|
}
|
| 1592 |
|
|
|
| 1593 |
|
|
// condition is not a constant. It must be a mask register
|
| 1594 |
|
|
if ((exp1.etype & XPR_REG) == 0 || exp1.reg1 == 0 || exp1.etype & (XPR_OP|XPR_OPTION|XPR_MEM|XPR_SYM1|XPR_MASK|XPR_UNRESOLV)) {
|
| 1595 |
|
|
errors.report(tokens[tok1].pos, tokens[tok1].stringLength, ERR_MASK_NOT_REGISTER);
|
| 1596 |
|
|
}
|
| 1597 |
|
|
uint8_t maskreg = exp1.reg1; // save mask register
|
| 1598 |
|
|
|
| 1599 |
|
|
// evaluate the middle expression
|
| 1600 |
|
|
exp1 = expression(toklow + 1, tokcolon - (toklow + 1), options);
|
| 1601 |
|
|
if (exp1.tokens != tokcolon - (toklow + 1)) errors.report(tokens[toklow + 1 + exp1.tokens]);
|
| 1602 |
|
|
|
| 1603 |
|
|
// third expression must be fallback
|
| 1604 |
|
|
exp2 = expression(tokcolon + 1, tok1 + maxtok - (tokcolon + 1), options);
|
| 1605 |
|
|
uint8_t fallbackreg = 0; // fallback register
|
| 1606 |
|
|
if (exp2.etype & XPR_REG) {
|
| 1607 |
|
|
fallbackreg = exp2.reg1;
|
| 1608 |
|
|
exp1.etype |= XPR_FALLBACK;
|
| 1609 |
|
|
}
|
| 1610 |
|
|
else if ((exp2.etype & (XPR_INT | XPR_FLT)) && exp2.value.i == 0) {
|
| 1611 |
|
|
fallbackreg = maskreg | 0x1F; // register 31 with same type as mask register
|
| 1612 |
|
|
exp1.etype |= XPR_FALLBACK;
|
| 1613 |
|
|
}
|
| 1614 |
|
|
if (exp2.etype & (XPR_STRING | XPR_OP | XPR_OPTION | XPR_MEM | XPR_SYM1 | XPR_MASK) || exp2.value.i) {
|
| 1615 |
|
|
errors.report(tokens[tokcolon+1].pos, tokens[tokcolon+exp2.tokens+1].pos - tokens[tokcolon+1].pos, ERR_FALLBACK_WRONG);
|
| 1616 |
|
|
}
|
| 1617 |
|
|
// insert mask and fallback in exp1
|
| 1618 |
|
|
exp1.etype |= XPR_MASK;
|
| 1619 |
|
|
exp1.mask = maskreg;
|
| 1620 |
|
|
exp1.fallback = fallbackreg;
|
| 1621 |
|
|
exp1.tokens = tokcolon - tok1 + 1 + exp2.tokens;
|
| 1622 |
|
|
return exp1;
|
| 1623 |
|
|
}
|
| 1624 |
|
|
|
| 1625 |
|
|
|
| 1626 |
|
|
// Convert -(expression), e.g. -(A-B)
|
| 1627 |
|
|
SExpression CAssembler::op1minus(SExpression & exp1) {
|
| 1628 |
|
|
exp1.tokens++;
|
| 1629 |
|
|
if ((exp1.etype & (XPR_REG | XPR_MEM)) && !(exp1.etype & XPR_OP) && exp1.value.i == 0) { // -reg or -mem
|
| 1630 |
|
|
exp1.etype |= XPR_OP | XPR_INT;
|
| 1631 |
|
|
exp1.instruction = II_SUB_REV; // 0 - expression
|
| 1632 |
|
|
}
|
| 1633 |
|
|
else if (exp1.instruction == II_SUB) exp1.instruction = II_SUB_REV;
|
| 1634 |
|
|
else if (exp1.instruction == II_SUB_REV) exp1.instruction = II_SUB;
|
| 1635 |
|
|
else if (exp1.instruction == II_ADD_ADD) exp1.optionbits ^= 3;
|
| 1636 |
|
|
else if (exp1.instruction == II_MUL_ADD || exp1.instruction == II_MUL_ADD2) exp1.optionbits ^= 0xF;
|
| 1637 |
|
|
else if (exp1.instruction == II_ADD && !(exp1.etype & (XPR_IMMEDIATE | XPR_MEM | XPR_SYM1))) {
|
| 1638 |
|
|
// -(R1+R2) = -R1 -R2 + 0
|
| 1639 |
|
|
exp1.instruction = II_ADD_ADD;
|
| 1640 |
|
|
exp1.value.i = 0;
|
| 1641 |
|
|
exp1.optionbits = 3;
|
| 1642 |
|
|
exp1.etype |= XPR_INT;
|
| 1643 |
|
|
}
|
| 1644 |
|
|
else if (exp1.instruction == II_ADD && (exp1.etype & XPR_IMMEDIATE)) {
|
| 1645 |
|
|
// -(R1+I) = -R1 + (-I)
|
| 1646 |
|
|
exp1.instruction = II_SUB_REV;
|
| 1647 |
|
|
if ((exp1.etype & XPR_IMMEDIATE) == XPR_FLT) exp1.value.d = -exp1.value.d;
|
| 1648 |
|
|
else exp1.value.i = -exp1.value.i;
|
| 1649 |
|
|
}
|
| 1650 |
|
|
else if ((exp1.instruction == 0 || exp1.instruction == II_MUL || exp1.instruction == II_DIV || exp1.instruction == II_DIV_REV)
|
| 1651 |
|
|
&& (exp1.etype & XPR_IMMEDIATE)) {
|
| 1652 |
|
|
// -I or -(A*I)
|
| 1653 |
|
|
if (exp1.etype & XPR_FLT) exp1.value.d = -exp1.value.d;
|
| 1654 |
|
|
else exp1.value.i = -exp1.value.i;
|
| 1655 |
|
|
}
|
| 1656 |
|
|
else if (exp1.instruction == II_MUL && !(exp1.etype & XPR_IMMEDIATE)) {
|
| 1657 |
|
|
exp1.instruction = II_MUL_ADD;
|
| 1658 |
|
|
exp1.optionbits ^= 3;
|
| 1659 |
|
|
exp1.etype |= XPR_INT;
|
| 1660 |
|
|
}
|
| 1661 |
|
|
else {
|
| 1662 |
|
|
exp1.etype = XPR_ERROR;
|
| 1663 |
|
|
exp1.value.u = ERR_TOO_COMPLEX; // cannot apply '-' to other expressions
|
| 1664 |
|
|
}
|
| 1665 |
|
|
return exp1;
|
| 1666 |
|
|
}
|
| 1667 |
|
|
|
| 1668 |
|
|
// Interpret dyadic expression with string operands
|
| 1669 |
|
|
SExpression CAssembler::op2String(uint32_t op, SExpression const & exp1, SExpression const & exp2) {
|
| 1670 |
|
|
if (op != '+') {
|
| 1671 |
|
|
SExpression exp3;
|
| 1672 |
|
|
exp3.etype = XPR_ERROR;
|
| 1673 |
|
|
exp3.value.u = ERR_WRONG_TYPE;
|
| 1674 |
|
|
return exp3;
|
| 1675 |
|
|
}
|
| 1676 |
|
|
// operation is +. concatenate strings, convert numeric to string
|
| 1677 |
|
|
|
| 1678 |
|
|
uint32_t stringpos1 = stringBuffer.dataSize(); // current position in string buffer
|
| 1679 |
|
|
uint32_t stringpos2; // position of second part of concatenated string
|
| 1680 |
|
|
const int maxIntLength = 32; // maximum length of integer as string
|
| 1681 |
|
|
const int maxFloatLength = 48;
|
| 1682 |
|
|
const char * wrongType = "-wrong type!-";
|
| 1683 |
|
|
uint32_t len = 0; // length of string
|
| 1684 |
|
|
|
| 1685 |
|
|
// first operand
|
| 1686 |
|
|
if (exp1.etype == XPR_STRING) {
|
| 1687 |
|
|
stringBuffer.push(stringBuffer.buf() + exp1.value.u, exp1.sym2); // copy to string buffer without terminating zero
|
| 1688 |
|
|
stringBuffer.put((char)0);
|
| 1689 |
|
|
//stringpos2 = stringBuffer.dataSize();
|
| 1690 |
|
|
}
|
| 1691 |
|
|
else if (exp1.etype == XPR_INT) { // convert integer to string
|
| 1692 |
|
|
stringBuffer.push(&exp1, maxIntLength); // put in anyting here to make space for writing string
|
| 1693 |
|
|
if (sizeof(long int) >= 8) {
|
| 1694 |
|
|
#ifndef _WIN32 // suppress warning
|
| 1695 |
|
|
sprintf((char*)stringBuffer.buf()+stringpos1, "%li", exp1.value.i);
|
| 1696 |
|
|
#endif
|
| 1697 |
|
|
}
|
| 1698 |
|
|
else {
|
| 1699 |
|
|
sprintf((char*)stringBuffer.buf()+stringpos1, "%lli", (long long)exp1.value.i);
|
| 1700 |
|
|
}
|
| 1701 |
|
|
}
|
| 1702 |
|
|
else if (exp1.etype == XPR_FLT) { // convert float to string
|
| 1703 |
|
|
stringBuffer.push(&exp1, maxFloatLength); // put in anyting here to make space for writing string
|
| 1704 |
|
|
sprintf((char*)stringBuffer.buf()+stringpos1, "%g", exp1.value.d);
|
| 1705 |
|
|
}
|
| 1706 |
|
|
else {
|
| 1707 |
|
|
stringBuffer.put(wrongType);
|
| 1708 |
|
|
}
|
| 1709 |
|
|
len = (uint32_t)strlen((char*)stringBuffer.buf()+stringpos1);
|
| 1710 |
|
|
stringpos2 = stringpos1 + len;
|
| 1711 |
|
|
stringBuffer.setSize(stringpos2); // remove extra space
|
| 1712 |
|
|
|
| 1713 |
|
|
// second operand
|
| 1714 |
|
|
if (exp2.etype == XPR_STRING) {
|
| 1715 |
|
|
stringBuffer.push(stringBuffer.buf() + exp2.value.u, exp2.sym2); // copy to string buffer without terminating zero
|
| 1716 |
|
|
stringBuffer.put((char)0);
|
| 1717 |
|
|
}
|
| 1718 |
|
|
else if (exp2.etype == XPR_INT) { // convert integer to string
|
| 1719 |
|
|
stringBuffer.push(&exp2, maxIntLength); // put in anyting here to make space for writing string
|
| 1720 |
|
|
if (sizeof(long int) >= 8) {
|
| 1721 |
|
|
#ifndef _WIN32 // suppress warning
|
| 1722 |
|
|
sprintf((char*)stringBuffer.buf()+stringpos2, "%li", exp2.value.i);
|
| 1723 |
|
|
#endif
|
| 1724 |
|
|
}
|
| 1725 |
|
|
else {
|
| 1726 |
|
|
sprintf((char*)stringBuffer.buf()+stringpos2, "%lli", (long long)exp2.value.i);
|
| 1727 |
|
|
}
|
| 1728 |
|
|
len = (uint32_t)strlen((char*)stringBuffer.buf()+stringpos2);
|
| 1729 |
|
|
stringBuffer.setSize(stringpos2 + len + 1);
|
| 1730 |
|
|
}
|
| 1731 |
|
|
else if (exp2.etype == XPR_FLT) { // convert float to string
|
| 1732 |
|
|
stringBuffer.push(&exp2, maxFloatLength); // put in anyting here to make space for writing string
|
| 1733 |
|
|
sprintf((char*)stringBuffer.buf()+stringpos2, "%g", exp2.value.d);
|
| 1734 |
|
|
len = (uint32_t)strlen((char*)stringBuffer.buf()+stringpos2);
|
| 1735 |
|
|
stringBuffer.setSize(stringpos2 + len + 1);
|
| 1736 |
|
|
}
|
| 1737 |
|
|
else {
|
| 1738 |
|
|
stringBuffer.put(wrongType);
|
| 1739 |
|
|
}
|
| 1740 |
|
|
SExpression exp3;
|
| 1741 |
|
|
exp3.etype = XPR_STRING;
|
| 1742 |
|
|
exp3.value.u = stringpos1;
|
| 1743 |
|
|
exp3.sym2 = (uint32_t)strlen((char*)stringBuffer.buf() + stringpos1);
|
| 1744 |
|
|
exp3.tokens = exp1.tokens + exp2.tokens + 1;
|
| 1745 |
|
|
return exp3;
|
| 1746 |
|
|
}
|
| 1747 |
|
|
|
| 1748 |
|
|
|
| 1749 |
|
|
double interpretFloat(const char * s, uint32_t length) {
|
| 1750 |
|
|
// interpret floating point number from string with indicated length
|
| 1751 |
|
|
char buffer[64];
|
| 1752 |
|
|
if (length >= sizeof(buffer)) {
|
| 1753 |
|
|
union {
|
| 1754 |
|
|
uint64_t i;
|
| 1755 |
|
|
double d;
|
| 1756 |
|
|
} nan = {0xFFFFC00000000000};
|
| 1757 |
|
|
return nan.d; // return NAN
|
| 1758 |
|
|
}
|
| 1759 |
|
|
memcpy(buffer, s, length);
|
| 1760 |
|
|
buffer[length] = 0; // terminate string
|
| 1761 |
|
|
double r;
|
| 1762 |
|
|
sscanf(buffer, "%lf", &r); // convert string to double
|
| 1763 |
|
|
return r;
|
| 1764 |
|
|
}
|
| 1765 |
|
|
|
| 1766 |
|
|
// make expression out of symbol
|
| 1767 |
|
|
SExpression CAssembler::symbol2expression(uint32_t symi) {
|
| 1768 |
|
|
SExpression expr;
|
| 1769 |
|
|
zeroAllMembers(expr);
|
| 1770 |
|
|
|
| 1771 |
|
|
switch (symbols[symi].st_type) {
|
| 1772 |
|
|
case STT_CONSTANT: case STT_VARIABLE:
|
| 1773 |
|
|
expr.etype = XPR_INT; // default type
|
| 1774 |
|
|
expr.sym1 = symi;
|
| 1775 |
|
|
if (symbols[symi].st_other & STV_FLOAT) expr.etype = XPR_FLT;
|
| 1776 |
|
|
if (symbols[symi].st_other & STV_STRING) {
|
| 1777 |
|
|
expr.etype = XPR_STRING;
|
| 1778 |
|
|
expr.sym2 = (uint32_t)symbols[symi].st_unitnum;
|
| 1779 |
|
|
}
|
| 1780 |
|
|
expr.value.u = symbols[symi].st_value;
|
| 1781 |
|
|
break;
|
| 1782 |
|
|
case STT_EXPRESSION:
|
| 1783 |
|
|
if (symbols[symi].st_value < expressions.numEntries()) {
|
| 1784 |
|
|
expr = expressions[uint32_t(symbols[symi].st_value)];
|
| 1785 |
|
|
}
|
| 1786 |
|
|
else {
|
| 1787 |
|
|
expr.etype = XPR_ERROR;
|
| 1788 |
|
|
expr.value.u = TOK_XPR;
|
| 1789 |
|
|
}
|
| 1790 |
|
|
break;
|
| 1791 |
|
|
default:
|
| 1792 |
|
|
expr.etype = XPR_ERROR;
|
| 1793 |
|
|
expr.value.u = ERR_CONFLICT_TYPE;
|
| 1794 |
|
|
}
|
| 1795 |
|
|
expr.tokens = 0;
|
| 1796 |
|
|
return expr;
|
| 1797 |
|
|
}
|