Mercurial > repos > blastem
comparison backend.c @ 2668:b0b6c6042103
Fix some bugs in memory access functions used in interpreter mode
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 08 Mar 2025 11:45:25 -0800 |
parents | 38c281ef57b0 |
children |
comparison
equal
deleted
inserted
replaced
2667:1f6503bcb1d5 | 2668:b0b6c6042103 |
---|---|
160 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); | 160 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); |
161 if (!chunk) { | 161 if (!chunk) { |
162 return 0xFFFF; | 162 return 0xFFFF; |
163 } | 163 } |
164 uint32_t offset = address & chunk->mask; | 164 uint32_t offset = address & chunk->mask; |
165 if (chunk->shift > 0) { | |
166 offset <<= chunk->shift; | |
167 } else if (chunk->shift < 0){ | |
168 offset >>= -chunk->shift; | |
169 } | |
165 if (chunk->flags & MMAP_READ) { | 170 if (chunk->flags & MMAP_READ) { |
166 uint8_t *base; | 171 uint8_t *base; |
167 if (chunk->flags & MMAP_PTR_IDX) { | 172 if (chunk->flags & MMAP_PTR_IDX) { |
168 base = mem_pointers[chunk->ptr_index]; | 173 base = mem_pointers[chunk->ptr_index]; |
169 } else { | 174 } else { |
170 base = chunk->buffer; | 175 base = chunk->buffer; |
171 } | 176 } |
172 if (base) { | 177 if (base) { |
173 uint16_t val; | 178 uint16_t val; |
174 if (chunk->shift > 0) { | |
175 offset <<= chunk->shift; | |
176 } else if (chunk->shift < 0){ | |
177 offset >>= chunk->shift; | |
178 } | |
179 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 179 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
180 offset /= 2; | 180 offset /= 2; |
181 val = base[offset]; | 181 val = base[offset]; |
182 if (chunk->flags & MMAP_ONLY_ODD) { | 182 if (chunk->flags & MMAP_ONLY_ODD) { |
183 val |= 0xFF00; | 183 val |= 0xFF00; |
201 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); | 201 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); |
202 if (!chunk) { | 202 if (!chunk) { |
203 return; | 203 return; |
204 } | 204 } |
205 uint32_t offset = address & chunk->mask; | 205 uint32_t offset = address & chunk->mask; |
206 if (chunk->shift > 0) { | |
207 offset <<= chunk->shift; | |
208 } else if (chunk->shift < 0){ | |
209 offset >>= -chunk->shift; | |
210 } | |
206 if (chunk->flags & MMAP_WRITE) { | 211 if (chunk->flags & MMAP_WRITE) { |
207 uint8_t *base; | 212 uint8_t *base; |
208 if (chunk->flags & MMAP_PTR_IDX) { | 213 if (chunk->flags & MMAP_PTR_IDX) { |
209 base = mem_pointers[chunk->ptr_index]; | 214 base = mem_pointers[chunk->ptr_index]; |
210 } else { | 215 } else { |
211 base = chunk->buffer; | 216 base = chunk->buffer; |
212 } | 217 } |
213 if (base) { | 218 if (base) { |
214 if (chunk->shift > 0) { | |
215 offset <<= chunk->shift; | |
216 } else if (chunk->shift < 0){ | |
217 offset >>= chunk->shift; | |
218 } | |
219 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 219 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
220 offset /= 2; | 220 offset /= 2; |
221 if (chunk->flags & MMAP_ONLY_EVEN) { | 221 if (chunk->flags & MMAP_ONLY_EVEN) { |
222 value >>= 16; | 222 value >>= 16; |
223 } | 223 } |
238 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); | 238 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); |
239 if (!chunk) { | 239 if (!chunk) { |
240 return 0xFF; | 240 return 0xFF; |
241 } | 241 } |
242 uint32_t offset = address & chunk->mask; | 242 uint32_t offset = address & chunk->mask; |
243 if (offset) { | |
244 uint32_t low_bit = offset & 1; | |
245 offset &= ~1; | |
246 if (chunk->shift > 0) { | |
247 offset <<= chunk->shift; | |
248 } else { | |
249 offset >>= -chunk->shift; | |
250 } | |
251 offset |= low_bit; | |
252 } | |
243 if (chunk->flags & MMAP_READ) { | 253 if (chunk->flags & MMAP_READ) { |
244 uint8_t *base; | 254 uint8_t *base; |
245 if (chunk->flags & MMAP_PTR_IDX) { | 255 if (chunk->flags & MMAP_PTR_IDX) { |
246 base = mem_pointers[chunk->ptr_index]; | 256 base = mem_pointers[chunk->ptr_index]; |
247 } else { | 257 } else { |
248 base = chunk->buffer; | 258 base = chunk->buffer; |
249 } | 259 } |
250 if (base) { | 260 if (base) { |
251 if (chunk->shift > 0) { | |
252 offset <<= chunk->shift; | |
253 } else if (chunk->shift < 0){ | |
254 offset >>= chunk->shift; | |
255 } | |
256 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 261 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
257 if (address & 1) { | 262 if (address & 1) { |
258 if (chunk->flags & MMAP_ONLY_EVEN) { | 263 if (chunk->flags & MMAP_ONLY_EVEN) { |
259 return 0xFF; | 264 return 0xFF; |
260 } | 265 } |
279 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); | 284 memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); |
280 if (!chunk) { | 285 if (!chunk) { |
281 return; | 286 return; |
282 } | 287 } |
283 uint32_t offset = address & chunk->mask; | 288 uint32_t offset = address & chunk->mask; |
289 if (chunk->shift) { | |
290 uint32_t low_bit = offset & 1; | |
291 offset &= ~1; | |
292 if (chunk->shift > 0) { | |
293 offset <<= chunk->shift; | |
294 } else { | |
295 offset >>= -chunk->shift; | |
296 } | |
297 offset |= low_bit; | |
298 } | |
284 if (chunk->flags & MMAP_WRITE) { | 299 if (chunk->flags & MMAP_WRITE) { |
285 uint8_t *base; | 300 uint8_t *base; |
286 if (chunk->flags & MMAP_PTR_IDX) { | 301 if (chunk->flags & MMAP_PTR_IDX) { |
287 base = mem_pointers[chunk->ptr_index]; | 302 base = mem_pointers[chunk->ptr_index]; |
288 } else { | 303 } else { |
289 base = chunk->buffer; | 304 base = chunk->buffer; |
290 } | 305 } |
291 if (base) { | 306 if (base) { |
292 if (chunk->shift > 0) { | |
293 offset <<= chunk->shift; | |
294 } else if (chunk->shift < 0){ | |
295 offset >>= chunk->shift; | |
296 } | |
297 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 307 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
298 if (address & 1) { | 308 if (address & 1) { |
299 if (chunk->flags & MMAP_ONLY_EVEN) { | 309 if (chunk->flags & MMAP_ONLY_EVEN) { |
300 return; | 310 return; |
301 } | 311 } |
419 if (chunk == map_end) { | 429 if (chunk == map_end) { |
420 return 0xFFFF; | 430 return 0xFFFF; |
421 } | 431 } |
422 } | 432 } |
423 uint32_t offset = address & chunk->mask; | 433 uint32_t offset = address & chunk->mask; |
434 if (chunk->shift > 0) { | |
435 offset <<= chunk->shift; | |
436 } else if (chunk->shift < 0){ | |
437 offset >>= -chunk->shift; | |
438 } | |
424 if (chunk->flags & MMAP_READ) { | 439 if (chunk->flags & MMAP_READ) { |
425 uint8_t *base; | 440 uint8_t *base; |
426 if (chunk->flags & MMAP_PTR_IDX) { | 441 if (chunk->flags & MMAP_PTR_IDX) { |
427 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); | 442 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); |
428 base = mem_pointers[chunk->ptr_index]; | 443 base = mem_pointers[chunk->ptr_index]; |
429 } else { | 444 } else { |
430 base = chunk->buffer; | 445 base = chunk->buffer; |
431 } | 446 } |
432 if (base) { | 447 if (base) { |
433 uint16_t val; | 448 uint16_t val; |
434 if (chunk->shift > 0) { | |
435 offset <<= chunk->shift; | |
436 } else if (chunk->shift < 0){ | |
437 offset >>= chunk->shift; | |
438 } | |
439 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 449 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
440 offset /= 2; | 450 offset /= 2; |
441 val = base[offset]; | 451 val = base[offset]; |
442 if (chunk->flags & MMAP_ONLY_ODD) { | 452 if (chunk->flags & MMAP_ONLY_ODD) { |
443 val |= 0xFF00; | 453 val |= 0xFF00; |
473 if (chunk == map_end) { | 483 if (chunk == map_end) { |
474 return 0xFF; | 484 return 0xFF; |
475 } | 485 } |
476 } | 486 } |
477 uint32_t offset = address & chunk->mask; | 487 uint32_t offset = address & chunk->mask; |
488 if (chunk->shift) { | |
489 uint32_t low_bit = offset & 1; | |
490 offset &= ~1; | |
491 if (chunk->shift > 0) { | |
492 offset <<= chunk->shift; | |
493 } else { | |
494 offset >>= -chunk->shift; | |
495 } | |
496 offset |= low_bit; | |
497 } | |
478 if (chunk->flags & MMAP_READ) { | 498 if (chunk->flags & MMAP_READ) { |
479 uint8_t *base; | 499 uint8_t *base; |
480 if (chunk->flags & MMAP_PTR_IDX) { | 500 if (chunk->flags & MMAP_PTR_IDX) { |
481 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); | 501 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); |
482 base = mem_pointers[chunk->ptr_index]; | 502 base = mem_pointers[chunk->ptr_index]; |
483 } else { | 503 } else { |
484 base = chunk->buffer; | 504 base = chunk->buffer; |
485 } | 505 } |
486 if (base) { | 506 if (base) { |
487 if (chunk->shift > 0) { | |
488 offset <<= chunk->shift; | |
489 } else if (chunk->shift < 0){ | |
490 offset >>= chunk->shift; | |
491 } | |
492 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 507 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
493 if (address & 1) { | 508 if (address & 1) { |
494 if (chunk->flags & MMAP_ONLY_EVEN) { | 509 if (chunk->flags & MMAP_ONLY_EVEN) { |
495 return 0xFF; | 510 return 0xFF; |
496 } | 511 } |
525 } | 540 } |
526 if (chunk == map_end) { | 541 if (chunk == map_end) { |
527 return; | 542 return; |
528 } | 543 } |
529 } | 544 } |
530 uint32_t offset = address & chunk->mask; | 545 uint32_t offset = address & chunk->mask; |
546 if (chunk->shift > 0) { | |
547 offset <<= chunk->shift; | |
548 } else if (chunk->shift < 0){ | |
549 offset >>= -chunk->shift; | |
550 } | |
531 if (chunk->flags & MMAP_WRITE) { | 551 if (chunk->flags & MMAP_WRITE) { |
532 uint8_t *base; | 552 uint8_t *base; |
533 if (chunk->flags & MMAP_PTR_IDX) { | 553 if (chunk->flags & MMAP_PTR_IDX) { |
534 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); | 554 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); |
535 base = mem_pointers[chunk->ptr_index]; | 555 base = mem_pointers[chunk->ptr_index]; |
536 } else { | 556 } else { |
537 base = chunk->buffer; | 557 base = chunk->buffer; |
538 } | 558 } |
539 if (base) { | 559 if (base) { |
540 if (chunk->shift > 0) { | |
541 offset <<= chunk->shift; | |
542 } else if (chunk->shift < 0){ | |
543 offset >>= chunk->shift; | |
544 } | |
545 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 560 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
546 offset /= 2; | 561 offset /= 2; |
547 if (chunk->flags & MMAP_ONLY_EVEN) { | 562 if (chunk->flags & MMAP_ONLY_EVEN) { |
548 value >>= 16; | 563 value >>= 16; |
549 } | 564 } |
575 if (chunk == map_end) { | 590 if (chunk == map_end) { |
576 return; | 591 return; |
577 } | 592 } |
578 } | 593 } |
579 uint32_t offset = address & chunk->mask; | 594 uint32_t offset = address & chunk->mask; |
595 if (chunk->shift) { | |
596 uint32_t low_bit = offset & 1; | |
597 offset &= ~1; | |
598 if (chunk->shift > 0) { | |
599 offset <<= chunk->shift; | |
600 } else { | |
601 offset >>= -chunk->shift; | |
602 } | |
603 offset |= low_bit; | |
604 } | |
580 if (chunk->flags & MMAP_WRITE) { | 605 if (chunk->flags & MMAP_WRITE) { |
581 uint8_t *base; | 606 uint8_t *base; |
582 if (chunk->flags & MMAP_PTR_IDX) { | 607 if (chunk->flags & MMAP_PTR_IDX) { |
583 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); | 608 uint8_t ** mem_pointers = (uint8_t**)(opts->mem_ptr_off + (uint8_t *)context); |
584 base = mem_pointers[chunk->ptr_index]; | 609 base = mem_pointers[chunk->ptr_index]; |
585 } else { | 610 } else { |
586 base = chunk->buffer; | 611 base = chunk->buffer; |
587 } | 612 } |
588 if (base) { | 613 if (base) { |
589 if (chunk->shift > 0) { | |
590 offset <<= chunk->shift; | |
591 } else if (chunk->shift < 0){ | |
592 offset >>= chunk->shift; | |
593 } | |
594 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { | 614 if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { |
595 if (address & 1) { | 615 if (address & 1) { |
596 if (chunk->flags & MMAP_ONLY_EVEN) { | 616 if (chunk->flags & MMAP_ONLY_EVEN) { |
597 return; | 617 return; |
598 } | 618 } |
622 } | 642 } |
623 if (chunk == opts->memmap + opts->memmap_chunks) { | 643 if (chunk == opts->memmap + opts->memmap_chunks) { |
624 *data_out = (void *)(uintptr_t)0xFFFF; | 644 *data_out = (void *)(uintptr_t)0xFFFF; |
625 return interp_read_fixed_16; | 645 return interp_read_fixed_16; |
626 } | 646 } |
627 if (chunk->end < end || chunk->start > start) { | 647 if (chunk->end < end || chunk->start > start || chunk->shift) { |
628 goto use_map; | 648 goto use_map; |
629 } | 649 } |
630 if (chunk->flags & MMAP_READ) { | 650 if (chunk->flags & MMAP_READ) { |
631 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift) { | 651 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL))) { |
632 goto use_map; | 652 goto use_map; |
633 } | 653 } |
634 if (!chunk->mask && !(chunk->flags & ~MMAP_READ)) { | 654 if (!chunk->mask && !(chunk->flags & ~MMAP_READ)) { |
635 uintptr_t value = *(uint16_t *)chunk->buffer; | 655 uintptr_t value = *(uint16_t *)chunk->buffer; |
636 *data_out = (void *)value; | 656 *data_out = (void *)value; |
672 } | 692 } |
673 if (chunk == opts->memmap + opts->memmap_chunks) { | 693 if (chunk == opts->memmap + opts->memmap_chunks) { |
674 *data_out = (void *)(uintptr_t)0xFFFF; | 694 *data_out = (void *)(uintptr_t)0xFFFF; |
675 return interp_read_fixed_8; | 695 return interp_read_fixed_8; |
676 } | 696 } |
677 if (chunk->end != end || chunk->start != start) { | 697 if (chunk->end != end || chunk->start != start || chunk->shift) { |
678 goto use_map; | 698 goto use_map; |
679 } | 699 } |
680 if (chunk->flags & MMAP_READ) { | 700 if (chunk->flags & MMAP_READ) { |
681 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift) { | 701 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || !opts->byte_swap) { |
682 goto use_map; | 702 goto use_map; |
683 } | 703 } |
684 if (!chunk->mask && !(chunk->flags & ~MMAP_READ)) { | 704 if (!chunk->mask && !(chunk->flags & ~MMAP_READ)) { |
685 uintptr_t value = *(uint8_t *)chunk->buffer; | 705 uintptr_t value = *(uint8_t *)chunk->buffer; |
686 *data_out = (void *)value; | 706 *data_out = (void *)value; |
722 } | 742 } |
723 if (chunk == opts->memmap + opts->memmap_chunks) { | 743 if (chunk == opts->memmap + opts->memmap_chunks) { |
724 *data_out = NULL; | 744 *data_out = NULL; |
725 return interp_write_ignored_16; | 745 return interp_write_ignored_16; |
726 } | 746 } |
727 if (chunk->end != end || chunk->start != start) { | 747 if (chunk->end != end || chunk->start != start || chunk->shift) { |
728 goto use_map; | 748 goto use_map; |
729 } | 749 } |
730 if (chunk->flags & MMAP_READ) { | 750 if (chunk->flags & MMAP_WRITE) { |
731 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift || (chunk->mask & 0xFFFF) != 0xFFFF) { | 751 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || (chunk->mask & 0xFFFF) != 0xFFFF) { |
732 goto use_map; | 752 goto use_map; |
733 } | 753 } |
734 if (chunk->flags & MMAP_PTR_IDX) { | 754 if (chunk->flags & MMAP_PTR_IDX) { |
735 if (chunk->mask != 0xFFFF && start > 0) { | 755 if (chunk->mask != 0xFFFF && start > 0) { |
736 goto use_map; | 756 goto use_map; |
764 } | 784 } |
765 if (chunk == opts->memmap + opts->memmap_chunks) { | 785 if (chunk == opts->memmap + opts->memmap_chunks) { |
766 *data_out = NULL; | 786 *data_out = NULL; |
767 return interp_write_ignored_8; | 787 return interp_write_ignored_8; |
768 } | 788 } |
769 if (chunk->end != end || chunk->start != start) { | 789 if (chunk->end != end || chunk->start != start || chunk->shift) { |
770 goto use_map; | 790 goto use_map; |
771 } | 791 } |
772 if (chunk->flags & MMAP_READ) { | 792 if (chunk->flags & MMAP_WRITE) { |
773 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) || chunk->shift | 793 if ((chunk->flags & (MMAP_ONLY_ODD|MMAP_ONLY_EVEN|MMAP_FUNC_NULL)) |
774 || (chunk->mask & 0xFFFF) != 0xFFFF || !opts->byte_swap | 794 || (chunk->mask & 0xFFFF) != 0xFFFF || !opts->byte_swap |
775 ) { | 795 ) { |
776 goto use_map; | 796 goto use_map; |
777 } | 797 } |
778 if (chunk->flags & MMAP_PTR_IDX) { | 798 if (chunk->flags & MMAP_PTR_IDX) { |
784 } else { | 804 } else { |
785 *data_out = (start & chunk->mask) + (uint8_t *)chunk->buffer; | 805 *data_out = (start & chunk->mask) + (uint8_t *)chunk->buffer; |
786 return interp_write_direct_8; | 806 return interp_write_direct_8; |
787 } | 807 } |
788 } | 808 } |
789 if (chunk->write_16 && chunk->mask == opts->address_mask) { | 809 if (chunk->write_8 && chunk->mask == opts->address_mask) { |
790 *data_out = NULL; | 810 *data_out = NULL; |
791 //This is not safe for all calling conventions due to the extra param | 811 //This is not safe for all calling conventions due to the extra param |
792 //but should work for the ones we actually care about | 812 //but should work for the ones we actually care about |
793 return (interp_write_8)chunk->write_8; | 813 return (interp_write_8)chunk->write_8; |
794 } | 814 } |