operand.c (13124B)
1 #include "rc_internal.h" 2 3 #include <stdlib.h> 4 #include <ctype.h> 5 #include <math.h> 6 #include <string.h> 7 8 #ifndef RC_DISABLE_LUA 9 10 RC_BEGIN_C_DECLS 11 12 #include <lua.h> 13 #include <lauxlib.h> 14 15 RC_END_C_DECLS 16 17 #endif /* RC_DISABLE_LUA */ 18 19 static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) { 20 const char* aux = *memaddr; 21 #ifndef RC_DISABLE_LUA 22 const char* id; 23 #endif 24 25 if (*aux++ != '@') { 26 return RC_INVALID_LUA_OPERAND; 27 } 28 29 if (!isalpha((unsigned char)*aux)) { 30 return RC_INVALID_LUA_OPERAND; 31 } 32 33 #ifndef RC_DISABLE_LUA 34 id = aux; 35 #endif 36 37 while (isalnum((unsigned char)*aux) || *aux == '_') { 38 aux++; 39 } 40 41 #ifndef RC_DISABLE_LUA 42 43 if (parse->L != 0) { 44 if (!lua_istable(parse->L, parse->funcs_ndx)) { 45 return RC_INVALID_LUA_OPERAND; 46 } 47 48 lua_pushlstring(parse->L, id, aux - id); 49 lua_gettable(parse->L, parse->funcs_ndx); 50 51 if (!lua_isfunction(parse->L, -1)) { 52 lua_pop(parse->L, 1); 53 return RC_INVALID_LUA_OPERAND; 54 } 55 56 self->value.luafunc = luaL_ref(parse->L, LUA_REGISTRYINDEX); 57 } 58 59 #else 60 (void)parse; 61 #endif /* RC_DISABLE_LUA */ 62 63 self->type = RC_OPERAND_LUA; 64 *memaddr = aux; 65 return RC_OK; 66 } 67 68 static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr) { 69 const char* aux = *memaddr; 70 size_t i; 71 char varName[RC_VALUE_MAX_NAME_LENGTH + 1] = { 0 }; 72 73 for (i = 0; i < RC_VALUE_MAX_NAME_LENGTH && *aux != '}'; i++) { 74 if (!rc_is_valid_variable_character(*aux, i == 0)) 75 return RC_INVALID_VARIABLE_NAME; 76 77 varName[i] = *aux++; 78 } 79 80 if (i == 0) 81 return RC_INVALID_VARIABLE_NAME; 82 83 if (*aux != '}') 84 return RC_INVALID_VARIABLE_NAME; 85 86 ++aux; 87 88 if (strcmp(varName, "recall") == 0) { 89 self->type = RC_OPERAND_RECALL; 90 } 91 else { /* process named variable when feature is available.*/ 92 return RC_UNKNOWN_VARIABLE_NAME; 93 } 94 95 *memaddr = aux; 96 return RC_OK; 97 } 98 99 static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect) { 100 const char* aux = *memaddr; 101 uint32_t address; 102 uint8_t size; 103 int ret; 104 105 switch (*aux) { 106 case 'd': case 'D': 107 self->type = RC_OPERAND_DELTA; 108 ++aux; 109 break; 110 111 case 'p': case 'P': 112 self->type = RC_OPERAND_PRIOR; 113 ++aux; 114 break; 115 116 case 'b': case 'B': 117 self->type = RC_OPERAND_BCD; 118 ++aux; 119 break; 120 121 case '~': 122 self->type = RC_OPERAND_INVERTED; 123 ++aux; 124 break; 125 126 default: 127 self->type = RC_OPERAND_ADDRESS; 128 break; 129 } 130 131 ret = rc_parse_memref(&aux, &self->size, &address); 132 if (ret != RC_OK) 133 return ret; 134 135 size = rc_memref_shared_size(self->size); 136 if (size != self->size && self->type == RC_OPERAND_PRIOR) { 137 /* if the shared size differs from the requested size and it's a prior operation, we 138 * have to check to make sure both sizes use the same mask, or the prior value may be 139 * updated when bits outside the mask are modified, which would make it look like the 140 * current value once the mask is applied. if the mask differs, create a new 141 * non-shared record for tracking the prior data. */ 142 if (rc_memref_mask(size) != rc_memref_mask(self->size)) 143 size = self->size; 144 } 145 146 self->value.memref = rc_alloc_memref(parse, address, size, is_indirect); 147 if (parse->offset < 0) 148 return parse->offset; 149 150 *memaddr = aux; 151 return RC_OK; 152 } 153 154 int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indirect, rc_parse_state_t* parse) { 155 const char* aux = *memaddr; 156 char* end; 157 int ret; 158 unsigned long value; 159 int negative; 160 int allow_decimal = 0; 161 162 self->size = RC_MEMSIZE_32_BITS; 163 164 switch (*aux) { 165 case 'h': case 'H': /* hex constant */ 166 if (aux[2] == 'x' || aux[2] == 'X') { 167 /* H0x1234 is a typo - either H1234 or 0xH1234 was probably meant */ 168 return RC_INVALID_CONST_OPERAND; 169 } 170 171 value = strtoul(++aux, &end, 16); 172 if (end == aux) 173 return RC_INVALID_CONST_OPERAND; 174 175 if (value > 0xffffffffU) 176 value = 0xffffffffU; 177 178 self->type = RC_OPERAND_CONST; 179 self->value.num = (unsigned)value; 180 181 aux = end; 182 break; 183 184 case 'f': case 'F': /* floating point constant */ 185 if (isalpha((unsigned char)aux[1])) { 186 ret = rc_parse_operand_memory(self, &aux, parse, is_indirect); 187 188 if (ret < 0) 189 return ret; 190 191 break; 192 } 193 allow_decimal = 1; 194 /* fall through */ 195 case 'v': case 'V': /* signed integer constant */ 196 ++aux; 197 /* fall through */ 198 case '+': case '-': /* signed integer constant */ 199 negative = 0; 200 if (*aux == '-') { 201 negative = 1; 202 ++aux; 203 } 204 else if (*aux == '+') { 205 ++aux; 206 } 207 208 value = strtoul(aux, &end, 10); 209 210 if (*end == '.' && allow_decimal) { 211 /* custom parser for decimal values to ignore locale */ 212 unsigned long shift = 1; 213 unsigned long fraction = 0; 214 215 aux = end + 1; 216 if (*aux < '0' || *aux > '9') 217 return RC_INVALID_FP_OPERAND; 218 219 do { 220 /* only keep as many digits as will fit in a 32-bit value to prevent overflow. 221 * float only has around 7 digits of precision anyway. */ 222 if (shift < 1000000000) { 223 fraction *= 10; 224 fraction += (*aux - '0'); 225 shift *= 10; 226 } 227 ++aux; 228 } while (*aux >= '0' && *aux <= '9'); 229 230 if (fraction != 0) { 231 /* non-zero fractional part, convert to double and merge in integer portion */ 232 const double dbl_fraction = ((double)fraction) / ((double)shift); 233 if (negative) 234 self->value.dbl = ((double)(-((long)value))) - dbl_fraction; 235 else 236 self->value.dbl = (double)value + dbl_fraction; 237 } 238 else { 239 /* fractional part is 0, just convert the integer portion */ 240 if (negative) 241 self->value.dbl = (double)(-((long)value)); 242 else 243 self->value.dbl = (double)value; 244 } 245 246 self->type = RC_OPERAND_FP; 247 } 248 else { 249 /* not a floating point value, make sure something was read and advance the read pointer */ 250 if (end == aux) 251 return allow_decimal ? RC_INVALID_FP_OPERAND : RC_INVALID_CONST_OPERAND; 252 253 aux = end; 254 255 if (value > 0x7fffffffU) 256 value = 0x7fffffffU; 257 258 self->type = RC_OPERAND_CONST; 259 260 if (negative) 261 self->value.num = (unsigned)(-((long)value)); 262 else 263 self->value.num = (unsigned)value; 264 } 265 break; 266 case '{': /* variable */ 267 ++aux; 268 ret = rc_parse_operand_variable(self, &aux); 269 if (ret < 0) 270 return ret; 271 272 break; 273 274 case '0': 275 if (aux[1] == 'x' || aux[1] == 'X') { /* hex integer constant */ 276 /* fallthrough */ /* to default */ 277 default: 278 ret = rc_parse_operand_memory(self, &aux, parse, is_indirect); 279 280 if (ret < 0) 281 return ret; 282 283 break; 284 } 285 /* fallthrough */ /* to case '1' for case '0' where not '0x' */ 286 case '1': case '2': case '3': case '4': case '5': /* unsigned integer constant */ 287 case '6': case '7': case '8': case '9': 288 value = strtoul(aux, &end, 10); 289 if (end == aux) 290 return RC_INVALID_CONST_OPERAND; 291 292 if (value > 0xffffffffU) 293 value = 0xffffffffU; 294 295 self->type = RC_OPERAND_CONST; 296 self->value.num = (unsigned)value; 297 298 aux = end; 299 break; 300 301 case '@': 302 ret = rc_parse_operand_lua(self, &aux, parse); 303 304 if (ret < 0) 305 return ret; 306 307 break; 308 } 309 310 *memaddr = aux; 311 return RC_OK; 312 } 313 314 #ifndef RC_DISABLE_LUA 315 316 typedef struct { 317 rc_peek_t peek; 318 void* ud; 319 } 320 rc_luapeek_t; 321 322 static int rc_luapeek(lua_State* L) { 323 uint32_t address = (uint32_t)luaL_checkinteger(L, 1); 324 uint32_t num_bytes = (uint32_t)luaL_checkinteger(L, 2); 325 rc_luapeek_t* luapeek = (rc_luapeek_t*)lua_touserdata(L, 3); 326 327 uint32_t value = luapeek->peek(address, num_bytes, luapeek->ud); 328 329 lua_pushinteger(L, value); 330 return 1; 331 } 332 333 #endif /* RC_DISABLE_LUA */ 334 335 int rc_operand_is_float_memref(const rc_operand_t* self) { 336 switch (self->size) { 337 case RC_MEMSIZE_FLOAT: 338 case RC_MEMSIZE_FLOAT_BE: 339 case RC_MEMSIZE_DOUBLE32: 340 case RC_MEMSIZE_DOUBLE32_BE: 341 case RC_MEMSIZE_MBF32: 342 case RC_MEMSIZE_MBF32_LE: 343 return 1; 344 345 default: 346 return 0; 347 } 348 } 349 350 int rc_operand_is_memref(const rc_operand_t* self) { 351 switch (self->type) { 352 case RC_OPERAND_CONST: 353 case RC_OPERAND_FP: 354 case RC_OPERAND_LUA: 355 case RC_OPERAND_RECALL: 356 return 0; 357 358 default: 359 return 1; 360 } 361 } 362 363 int rc_operand_is_recall(const rc_operand_t* self) { 364 switch (self->type) { 365 case RC_OPERAND_RECALL: 366 return 1; 367 368 default: 369 return 0; 370 } 371 } 372 373 int rc_operand_is_float(const rc_operand_t* self) { 374 if (self->type == RC_OPERAND_FP) 375 return 1; 376 377 return rc_operand_is_float_memref(self); 378 } 379 380 uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) { 381 switch (self->type) 382 { 383 case RC_OPERAND_BCD: 384 switch (self->size) 385 { 386 case RC_MEMSIZE_8_BITS: 387 value = ((value >> 4) & 0x0f) * 10 388 + ((value ) & 0x0f); 389 break; 390 391 case RC_MEMSIZE_16_BITS: 392 case RC_MEMSIZE_16_BITS_BE: 393 value = ((value >> 12) & 0x0f) * 1000 394 + ((value >> 8) & 0x0f) * 100 395 + ((value >> 4) & 0x0f) * 10 396 + ((value ) & 0x0f); 397 break; 398 399 case RC_MEMSIZE_24_BITS: 400 case RC_MEMSIZE_24_BITS_BE: 401 value = ((value >> 20) & 0x0f) * 100000 402 + ((value >> 16) & 0x0f) * 10000 403 + ((value >> 12) & 0x0f) * 1000 404 + ((value >> 8) & 0x0f) * 100 405 + ((value >> 4) & 0x0f) * 10 406 + ((value ) & 0x0f); 407 break; 408 409 case RC_MEMSIZE_32_BITS: 410 case RC_MEMSIZE_32_BITS_BE: 411 case RC_MEMSIZE_VARIABLE: 412 value = ((value >> 28) & 0x0f) * 10000000 413 + ((value >> 24) & 0x0f) * 1000000 414 + ((value >> 20) & 0x0f) * 100000 415 + ((value >> 16) & 0x0f) * 10000 416 + ((value >> 12) & 0x0f) * 1000 417 + ((value >> 8) & 0x0f) * 100 418 + ((value >> 4) & 0x0f) * 10 419 + ((value ) & 0x0f); 420 break; 421 422 default: 423 break; 424 } 425 break; 426 427 case RC_OPERAND_INVERTED: 428 switch (self->size) 429 { 430 case RC_MEMSIZE_LOW: 431 case RC_MEMSIZE_HIGH: 432 value ^= 0x0f; 433 break; 434 435 case RC_MEMSIZE_8_BITS: 436 value ^= 0xff; 437 break; 438 439 case RC_MEMSIZE_16_BITS: 440 case RC_MEMSIZE_16_BITS_BE: 441 value ^= 0xffff; 442 break; 443 444 case RC_MEMSIZE_24_BITS: 445 case RC_MEMSIZE_24_BITS_BE: 446 value ^= 0xffffff; 447 break; 448 449 case RC_MEMSIZE_32_BITS: 450 case RC_MEMSIZE_32_BITS_BE: 451 case RC_MEMSIZE_VARIABLE: 452 value ^= 0xffffffff; 453 break; 454 455 default: 456 value ^= 0x01; 457 break; 458 } 459 break; 460 461 default: 462 break; 463 } 464 465 return value; 466 } 467 468 void rc_evaluate_operand(rc_typed_value_t* result, rc_operand_t* self, rc_eval_state_t* eval_state) { 469 #ifndef RC_DISABLE_LUA 470 rc_luapeek_t luapeek; 471 #endif /* RC_DISABLE_LUA */ 472 473 /* step 1: read memory */ 474 switch (self->type) { 475 case RC_OPERAND_CONST: 476 result->type = RC_VALUE_TYPE_UNSIGNED; 477 result->value.u32 = self->value.num; 478 return; 479 480 case RC_OPERAND_FP: 481 result->type = RC_VALUE_TYPE_FLOAT; 482 result->value.f32 = (float)self->value.dbl; 483 return; 484 485 case RC_OPERAND_LUA: 486 result->type = RC_VALUE_TYPE_UNSIGNED; 487 result->value.u32 = 0; 488 489 #ifndef RC_DISABLE_LUA 490 if (eval_state->L != 0) { 491 lua_rawgeti(eval_state->L, LUA_REGISTRYINDEX, self->value.luafunc); 492 lua_pushcfunction(eval_state->L, rc_luapeek); 493 494 luapeek.peek = eval_state->peek; 495 luapeek.ud = eval_state->peek_userdata; 496 497 lua_pushlightuserdata(eval_state->L, &luapeek); 498 499 if (lua_pcall(eval_state->L, 2, 1, 0) == LUA_OK) { 500 if (lua_isboolean(eval_state->L, -1)) { 501 result->value.u32 = (uint32_t)lua_toboolean(eval_state->L, -1); 502 } 503 else { 504 result->value.u32 = (uint32_t)lua_tonumber(eval_state->L, -1); 505 } 506 } 507 508 lua_pop(eval_state->L, 1); 509 } 510 511 #endif /* RC_DISABLE_LUA */ 512 513 break; 514 515 case RC_OPERAND_RECALL: 516 result->type = eval_state->recall_value.type; 517 result->value = eval_state->recall_value.value; 518 return; 519 520 default: 521 result->type = RC_VALUE_TYPE_UNSIGNED; 522 result->value.u32 = rc_get_memref_value(self->value.memref, self->type, eval_state); 523 break; 524 } 525 526 /* step 2: convert read memory to desired format */ 527 rc_transform_memref_value(result, self->size); 528 529 /* step 3: apply logic (BCD/invert) */ 530 if (result->type == RC_VALUE_TYPE_UNSIGNED) 531 result->value.u32 = rc_transform_operand_value(result->value.u32, self); 532 }