memref.c (17764B)
1 #include "rc_internal.h" 2 3 #include <stdlib.h> /* malloc/realloc */ 4 #include <string.h> /* memcpy */ 5 #include <math.h> /* INFINITY/NAN */ 6 7 #define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF 8 9 rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size, uint8_t is_indirect) { 10 rc_memref_t** next_memref; 11 rc_memref_t* memref; 12 13 if (!is_indirect) { 14 /* attempt to find an existing memref that can be shared */ 15 next_memref = parse->first_memref; 16 while (*next_memref) { 17 memref = *next_memref; 18 if (!memref->value.is_indirect && memref->address == address && memref->value.size == size) 19 return memref; 20 21 next_memref = &memref->next; 22 } 23 24 /* no match found, create a new entry */ 25 memref = RC_ALLOC_SCRATCH(rc_memref_t, parse); 26 *next_memref = memref; 27 } 28 else { 29 /* indirect references always create a new entry because we can't guarantee that the 30 * indirection amount will be the same between references. because they aren't shared, 31 * don't bother putting them in the chain. 32 */ 33 memref = RC_ALLOC(rc_memref_t, parse); 34 } 35 36 memset(memref, 0, sizeof(*memref)); 37 memref->address = address; 38 memref->value.size = size; 39 memref->value.is_indirect = is_indirect; 40 41 return memref; 42 } 43 44 int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) { 45 const char* aux = *memaddr; 46 char* end; 47 unsigned long value; 48 49 if (aux[0] == '0') { 50 if (aux[1] != 'x' && aux[1] != 'X') 51 return RC_INVALID_MEMORY_OPERAND; 52 53 aux += 2; 54 switch (*aux++) { 55 /* ordered by estimated frequency in case compiler doesn't build a jump table */ 56 case 'h': case 'H': *size = RC_MEMSIZE_8_BITS; break; 57 case ' ': *size = RC_MEMSIZE_16_BITS; break; 58 case 'x': case 'X': *size = RC_MEMSIZE_32_BITS; break; 59 60 case 'm': case 'M': *size = RC_MEMSIZE_BIT_0; break; 61 case 'n': case 'N': *size = RC_MEMSIZE_BIT_1; break; 62 case 'o': case 'O': *size = RC_MEMSIZE_BIT_2; break; 63 case 'p': case 'P': *size = RC_MEMSIZE_BIT_3; break; 64 case 'q': case 'Q': *size = RC_MEMSIZE_BIT_4; break; 65 case 'r': case 'R': *size = RC_MEMSIZE_BIT_5; break; 66 case 's': case 'S': *size = RC_MEMSIZE_BIT_6; break; 67 case 't': case 'T': *size = RC_MEMSIZE_BIT_7; break; 68 case 'l': case 'L': *size = RC_MEMSIZE_LOW; break; 69 case 'u': case 'U': *size = RC_MEMSIZE_HIGH; break; 70 case 'k': case 'K': *size = RC_MEMSIZE_BITCOUNT; break; 71 case 'w': case 'W': *size = RC_MEMSIZE_24_BITS; break; 72 case 'g': case 'G': *size = RC_MEMSIZE_32_BITS_BE; break; 73 case 'i': case 'I': *size = RC_MEMSIZE_16_BITS_BE; break; 74 case 'j': case 'J': *size = RC_MEMSIZE_24_BITS_BE; break; 75 76 /* case 'v': case 'V': */ 77 /* case 'y': case 'Y': 64 bit? */ 78 /* case 'z': case 'Z': 128 bit? */ 79 80 case '0': case '1': case '2': case '3': case '4': 81 case '5': case '6': case '7': case '8': case '9': 82 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 83 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 84 /* legacy support - addresses without a size prefix are assumed to be 16-bit */ 85 aux--; 86 *size = RC_MEMSIZE_16_BITS; 87 break; 88 89 default: 90 return RC_INVALID_MEMORY_OPERAND; 91 } 92 } 93 else if (aux[0] == 'f' || aux[0] == 'F') { 94 ++aux; 95 switch (*aux++) { 96 case 'f': case 'F': *size = RC_MEMSIZE_FLOAT; break; 97 case 'b': case 'B': *size = RC_MEMSIZE_FLOAT_BE; break; 98 case 'h': case 'H': *size = RC_MEMSIZE_DOUBLE32; break; 99 case 'i': case 'I': *size = RC_MEMSIZE_DOUBLE32_BE; break; 100 case 'm': case 'M': *size = RC_MEMSIZE_MBF32; break; 101 case 'l': case 'L': *size = RC_MEMSIZE_MBF32_LE; break; 102 103 default: 104 return RC_INVALID_FP_OPERAND; 105 } 106 } 107 else { 108 return RC_INVALID_MEMORY_OPERAND; 109 } 110 111 value = strtoul(aux, &end, 16); 112 113 if (end == aux) 114 return RC_INVALID_MEMORY_OPERAND; 115 116 if (value > 0xffffffffU) 117 value = 0xffffffffU; 118 119 *address = (uint32_t)value; 120 *memaddr = end; 121 return RC_OK; 122 } 123 124 static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign) { 125 /* 32-bit float has a 23-bit mantissa and 8-bit exponent */ 126 const uint32_t implied_bit = 1 << 23; 127 const uint32_t mantissa = mantissa_bits | implied_bit; 128 double dbl = ((double)mantissa) / ((double)implied_bit); 129 130 if (exponent > 127) { 131 /* exponent above 127 is a special number */ 132 if (mantissa_bits == 0) { 133 /* infinity */ 134 #ifdef INFINITY /* INFINITY and NAN #defines require C99 */ 135 dbl = INFINITY; 136 #else 137 dbl = -log(0.0); 138 #endif 139 } 140 else { 141 /* NaN */ 142 #ifdef NAN 143 dbl = NAN; 144 #else 145 dbl = -sqrt(-1); 146 #endif 147 } 148 } 149 else if (exponent > 0) { 150 /* exponent from 1 to 127 is a number greater than 1 */ 151 while (exponent > 30) { 152 dbl *= (double)(1 << 30); 153 exponent -= 30; 154 } 155 dbl *= (double)((long long)1 << exponent); 156 } 157 else if (exponent < 0) { 158 /* exponent from -1 to -127 is a number less than 1 */ 159 160 if (exponent == -127) { 161 /* exponent -127 (all exponent bits were zero) is a denormalized value 162 * (no implied leading bit) with exponent -126 */ 163 dbl = ((double)mantissa_bits) / ((double)implied_bit); 164 exponent = 126; 165 } else { 166 exponent = -exponent; 167 } 168 169 while (exponent > 30) { 170 dbl /= (double)(1 << 30); 171 exponent -= 30; 172 } 173 dbl /= (double)((long long)1 << exponent); 174 } 175 else { 176 /* exponent of 0 requires no adjustment */ 177 } 178 179 return (sign) ? (float)-dbl : (float)dbl; 180 } 181 182 static void rc_transform_memref_float(rc_typed_value_t* value) { 183 /* decodes an IEEE 754 float */ 184 const uint32_t mantissa = (value->value.u32 & 0x7FFFFF); 185 const int32_t exponent = (int32_t)((value->value.u32 >> 23) & 0xFF) - 127; 186 const int sign = (value->value.u32 & 0x80000000); 187 value->value.f32 = rc_build_float(mantissa, exponent, sign); 188 value->type = RC_VALUE_TYPE_FLOAT; 189 } 190 191 static void rc_transform_memref_float_be(rc_typed_value_t* value) { 192 /* decodes an IEEE 754 float in big endian format */ 193 const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) | 194 ((value->value.u32 & 0x00FF0000) >> 8) | 195 ((value->value.u32 & 0x00007F00) << 8); 196 const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 1) | 197 ((value->value.u32 & 0x00008000) >> 15)) - 127; 198 const int sign = (value->value.u32 & 0x00000080); 199 value->value.f32 = rc_build_float(mantissa, exponent, sign); 200 value->type = RC_VALUE_TYPE_FLOAT; 201 } 202 203 static void rc_transform_memref_double32(rc_typed_value_t* value) 204 { 205 /* decodes the four most significant bytes of an IEEE 754 double into a float */ 206 const uint32_t mantissa = (value->value.u32 & 0x000FFFFF) << 3; 207 const int32_t exponent = (int32_t)((value->value.u32 >> 20) & 0x7FF) - 1023; 208 const int sign = (value->value.u32 & 0x80000000); 209 value->value.f32 = rc_build_float(mantissa, exponent, sign); 210 value->type = RC_VALUE_TYPE_FLOAT; 211 } 212 213 static void rc_transform_memref_double32_be(rc_typed_value_t* value) 214 { 215 /* decodes the four most significant bytes of an IEEE 754 double in big endian format into a float */ 216 const uint32_t mantissa = (((value->value.u32 & 0xFF000000) >> 24) | 217 ((value->value.u32 & 0x00FF0000) >> 8) | 218 ((value->value.u32 & 0x00000F00) << 8)) << 3; 219 const int32_t exponent = (int32_t)(((value->value.u32 & 0x0000007F) << 4) | 220 ((value->value.u32 & 0x0000F000) >> 12)) - 1023; 221 const int sign = (value->value.u32 & 0x00000080); 222 value->value.f32 = rc_build_float(mantissa, exponent, sign); 223 value->type = RC_VALUE_TYPE_FLOAT; 224 } 225 226 static void rc_transform_memref_mbf32(rc_typed_value_t* value) { 227 /* decodes a Microsoft Binary Format float */ 228 /* NOTE: 32-bit MBF is stored in memory as big endian (at least for Apple II) */ 229 const uint32_t mantissa = ((value->value.u32 & 0xFF000000) >> 24) | 230 ((value->value.u32 & 0x00FF0000) >> 8) | 231 ((value->value.u32 & 0x00007F00) << 8); 232 const int32_t exponent = (int32_t)(value->value.u32 & 0xFF) - 129; 233 const int sign = (value->value.u32 & 0x00008000); 234 235 if (mantissa == 0 && exponent == -129) 236 value->value.f32 = (sign) ? -0.0f : 0.0f; 237 else 238 value->value.f32 = rc_build_float(mantissa, exponent, sign); 239 240 value->type = RC_VALUE_TYPE_FLOAT; 241 } 242 243 static void rc_transform_memref_mbf32_le(rc_typed_value_t* value) { 244 /* decodes a Microsoft Binary Format float */ 245 /* Locomotive BASIC (CPC) uses MBF40, but in little endian format */ 246 const uint32_t mantissa = value->value.u32 & 0x007FFFFF; 247 const int32_t exponent = (int32_t)(value->value.u32 >> 24) - 129; 248 const int sign = (value->value.u32 & 0x00800000); 249 250 if (mantissa == 0 && exponent == -129) 251 value->value.f32 = (sign) ? -0.0f : 0.0f; 252 else 253 value->value.f32 = rc_build_float(mantissa, exponent, sign); 254 255 value->type = RC_VALUE_TYPE_FLOAT; 256 } 257 258 static const uint8_t rc_bits_set[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; 259 260 void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size) { 261 /* ASSERT: value->type == RC_VALUE_TYPE_UNSIGNED */ 262 switch (size) 263 { 264 case RC_MEMSIZE_8_BITS: 265 value->value.u32 = (value->value.u32 & 0x000000ff); 266 break; 267 268 case RC_MEMSIZE_16_BITS: 269 value->value.u32 = (value->value.u32 & 0x0000ffff); 270 break; 271 272 case RC_MEMSIZE_24_BITS: 273 value->value.u32 = (value->value.u32 & 0x00ffffff); 274 break; 275 276 case RC_MEMSIZE_32_BITS: 277 break; 278 279 case RC_MEMSIZE_BIT_0: 280 value->value.u32 = (value->value.u32 >> 0) & 1; 281 break; 282 283 case RC_MEMSIZE_BIT_1: 284 value->value.u32 = (value->value.u32 >> 1) & 1; 285 break; 286 287 case RC_MEMSIZE_BIT_2: 288 value->value.u32 = (value->value.u32 >> 2) & 1; 289 break; 290 291 case RC_MEMSIZE_BIT_3: 292 value->value.u32 = (value->value.u32 >> 3) & 1; 293 break; 294 295 case RC_MEMSIZE_BIT_4: 296 value->value.u32 = (value->value.u32 >> 4) & 1; 297 break; 298 299 case RC_MEMSIZE_BIT_5: 300 value->value.u32 = (value->value.u32 >> 5) & 1; 301 break; 302 303 case RC_MEMSIZE_BIT_6: 304 value->value.u32 = (value->value.u32 >> 6) & 1; 305 break; 306 307 case RC_MEMSIZE_BIT_7: 308 value->value.u32 = (value->value.u32 >> 7) & 1; 309 break; 310 311 case RC_MEMSIZE_LOW: 312 value->value.u32 = value->value.u32 & 0x0f; 313 break; 314 315 case RC_MEMSIZE_HIGH: 316 value->value.u32 = (value->value.u32 >> 4) & 0x0f; 317 break; 318 319 case RC_MEMSIZE_BITCOUNT: 320 value->value.u32 = rc_bits_set[(value->value.u32 & 0x0F)] 321 + rc_bits_set[((value->value.u32 >> 4) & 0x0F)]; 322 break; 323 324 case RC_MEMSIZE_16_BITS_BE: 325 value->value.u32 = ((value->value.u32 & 0xFF00) >> 8) | 326 ((value->value.u32 & 0x00FF) << 8); 327 break; 328 329 case RC_MEMSIZE_24_BITS_BE: 330 value->value.u32 = ((value->value.u32 & 0xFF0000) >> 16) | 331 (value->value.u32 & 0x00FF00) | 332 ((value->value.u32 & 0x0000FF) << 16); 333 break; 334 335 case RC_MEMSIZE_32_BITS_BE: 336 value->value.u32 = ((value->value.u32 & 0xFF000000) >> 24) | 337 ((value->value.u32 & 0x00FF0000) >> 8) | 338 ((value->value.u32 & 0x0000FF00) << 8) | 339 ((value->value.u32 & 0x000000FF) << 24); 340 break; 341 342 case RC_MEMSIZE_FLOAT: 343 rc_transform_memref_float(value); 344 break; 345 346 case RC_MEMSIZE_FLOAT_BE: 347 rc_transform_memref_float_be(value); 348 break; 349 350 case RC_MEMSIZE_DOUBLE32: 351 rc_transform_memref_double32(value); 352 break; 353 354 case RC_MEMSIZE_DOUBLE32_BE: 355 rc_transform_memref_double32_be(value); 356 break; 357 358 case RC_MEMSIZE_MBF32: 359 rc_transform_memref_mbf32(value); 360 break; 361 362 case RC_MEMSIZE_MBF32_LE: 363 rc_transform_memref_mbf32_le(value); 364 break; 365 366 default: 367 break; 368 } 369 } 370 371 static const uint32_t rc_memref_masks[] = { 372 0x000000ff, /* RC_MEMSIZE_8_BITS */ 373 0x0000ffff, /* RC_MEMSIZE_16_BITS */ 374 0x00ffffff, /* RC_MEMSIZE_24_BITS */ 375 0xffffffff, /* RC_MEMSIZE_32_BITS */ 376 0x0000000f, /* RC_MEMSIZE_LOW */ 377 0x000000f0, /* RC_MEMSIZE_HIGH */ 378 0x00000001, /* RC_MEMSIZE_BIT_0 */ 379 0x00000002, /* RC_MEMSIZE_BIT_1 */ 380 0x00000004, /* RC_MEMSIZE_BIT_2 */ 381 0x00000008, /* RC_MEMSIZE_BIT_3 */ 382 0x00000010, /* RC_MEMSIZE_BIT_4 */ 383 0x00000020, /* RC_MEMSIZE_BIT_5 */ 384 0x00000040, /* RC_MEMSIZE_BIT_6 */ 385 0x00000080, /* RC_MEMSIZE_BIT_7 */ 386 0x000000ff, /* RC_MEMSIZE_BITCOUNT */ 387 0x0000ffff, /* RC_MEMSIZE_16_BITS_BE */ 388 0x00ffffff, /* RC_MEMSIZE_24_BITS_BE */ 389 0xffffffff, /* RC_MEMSIZE_32_BITS_BE */ 390 0xffffffff, /* RC_MEMSIZE_FLOAT */ 391 0xffffffff, /* RC_MEMSIZE_MBF32 */ 392 0xffffffff, /* RC_MEMSIZE_MBF32_LE */ 393 0xffffffff, /* RC_MEMSIZE_FLOAT_BE */ 394 0xffffffff, /* RC_MEMSIZE_DOUBLE32 */ 395 0xffffffff, /* RC_MEMSIZE_DOUBLE32_BE*/ 396 0xffffffff /* RC_MEMSIZE_VARIABLE */ 397 }; 398 399 uint32_t rc_memref_mask(uint8_t size) { 400 const size_t index = (size_t)size; 401 if (index >= sizeof(rc_memref_masks) / sizeof(rc_memref_masks[0])) 402 return 0xffffffff; 403 404 return rc_memref_masks[index]; 405 } 406 407 /* all sizes less than 8-bits (1 byte) are mapped to 8-bits. 24-bit is mapped to 32-bit 408 * as we don't expect the client to understand a request for 3 bytes. all other reads are 409 * mapped to the little-endian read of the same size. */ 410 static const uint8_t rc_memref_shared_sizes[] = { 411 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_8_BITS */ 412 RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS */ 413 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS */ 414 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS */ 415 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_LOW */ 416 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_HIGH */ 417 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_0 */ 418 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_1 */ 419 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_2 */ 420 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_3 */ 421 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_4 */ 422 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_5 */ 423 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_6 */ 424 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BIT_7 */ 425 RC_MEMSIZE_8_BITS, /* RC_MEMSIZE_BITCOUNT */ 426 RC_MEMSIZE_16_BITS, /* RC_MEMSIZE_16_BITS_BE */ 427 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_24_BITS_BE */ 428 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_32_BITS_BE */ 429 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_FLOAT */ 430 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_MBF32 */ 431 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_MBF32_LE */ 432 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_FLOAT_BE */ 433 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_DOUBLE32 */ 434 RC_MEMSIZE_32_BITS, /* RC_MEMSIZE_DOUBLE32_BE*/ 435 RC_MEMSIZE_32_BITS /* RC_MEMSIZE_VARIABLE */ 436 }; 437 438 uint8_t rc_memref_shared_size(uint8_t size) { 439 const size_t index = (size_t)size; 440 if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0])) 441 return size; 442 443 return rc_memref_shared_sizes[index]; 444 } 445 446 uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud) { 447 if (!peek) 448 return 0; 449 450 switch (size) 451 { 452 case RC_MEMSIZE_8_BITS: 453 return peek(address, 1, ud); 454 455 case RC_MEMSIZE_16_BITS: 456 return peek(address, 2, ud); 457 458 case RC_MEMSIZE_32_BITS: 459 return peek(address, 4, ud); 460 461 default: 462 { 463 uint32_t value; 464 const size_t index = (size_t)size; 465 if (index >= sizeof(rc_memref_shared_sizes) / sizeof(rc_memref_shared_sizes[0])) 466 return 0; 467 468 /* fetch the larger value and mask off the bits associated to the specified size 469 * for correct deduction of prior value. non-prior memrefs should already be using 470 * shared size memrefs to minimize the total number of memory reads required. */ 471 value = rc_peek_value(address, rc_memref_shared_sizes[index], peek, ud); 472 return value & rc_memref_masks[index]; 473 } 474 } 475 } 476 477 void rc_update_memref_value(rc_memref_value_t* memref, uint32_t new_value) { 478 if (memref->value == new_value) { 479 memref->changed = 0; 480 } 481 else { 482 memref->prior = memref->value; 483 memref->value = new_value; 484 memref->changed = 1; 485 } 486 } 487 488 void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud) { 489 while (memref) { 490 /* indirect memory references are not shared and will be updated in rc_get_memref_value */ 491 if (!memref->value.is_indirect) 492 rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud)); 493 494 memref = memref->next; 495 } 496 } 497 498 void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs) { 499 parse->first_memref = memrefs; 500 *memrefs = 0; 501 } 502 503 static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) { 504 switch (operand_type) 505 { 506 /* most common case explicitly first, even though it could be handled by default case. 507 * this helps the compiler to optimize if it turns the switch into a series of if/elses */ 508 case RC_OPERAND_ADDRESS: 509 return memref->value; 510 511 case RC_OPERAND_DELTA: 512 if (!memref->changed) { 513 /* fallthrough */ 514 default: 515 return memref->value; 516 } 517 /* fallthrough */ 518 case RC_OPERAND_PRIOR: 519 return memref->prior; 520 } 521 } 522 523 uint32_t rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state) { 524 /* if this is an indirect reference, handle the indirection. */ 525 if (memref->value.is_indirect) { 526 const uint32_t new_address = memref->address + eval_state->add_address; 527 rc_update_memref_value(&memref->value, rc_peek_value(new_address, memref->value.size, eval_state->peek, eval_state->peek_userdata)); 528 } 529 530 return rc_get_memref_value_value(&memref->value, operand_type); 531 }