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 }