comparison m68k_core.c @ 1130:8f14767661fa

Remove memory map assumptions from Z80 core and move a little bit of logic to the generic backend.c so it can be shared between CPU cores
author Michael Pavone <pavone@retrodev.com>
date Wed, 28 Dec 2016 20:39:27 -0800
parents c15896605bf2
children 191ac490fb3d
comparison
equal deleted inserted replaced
1129:6b5c92b6205c 1130:8f14767661fa
558 } 558 }
559 559
560 code_ptr get_native_address(m68k_options *opts, uint32_t address) 560 code_ptr get_native_address(m68k_options *opts, uint32_t address)
561 { 561 {
562 native_map_slot * native_code_map = opts->gen.native_code_map; 562 native_map_slot * native_code_map = opts->gen.native_code_map;
563 address &= opts->gen.address_mask;
564 563
565 //TODO: Refactor part of this loop into some kind of get_ram_chunk function 564 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
566 for (int i = 0; i < opts->gen.memmap_chunks; i++) { 565 if (mem_chunk) {
567 if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) { 566 //calculate the lowest alias for this address
568 //calculate the lowest alias for this address 567 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
569 address = opts->gen.memmap[i].start + ((address - opts->gen.memmap[i].start) & opts->gen.memmap[i].mask); 568 }
570 }
571 }
572
573 uint32_t chunk = address / NATIVE_CHUNK_SIZE; 569 uint32_t chunk = address / NATIVE_CHUNK_SIZE;
574 if (!native_code_map[chunk].base) { 570 if (!native_code_map[chunk].base) {
575 return NULL; 571 return NULL;
576 } 572 }
577 uint32_t offset = address % NATIVE_CHUNK_SIZE; 573 uint32_t offset = address % NATIVE_CHUNK_SIZE;
584 code_ptr get_native_from_context(m68k_context * context, uint32_t address) 580 code_ptr get_native_from_context(m68k_context * context, uint32_t address)
585 { 581 {
586 return get_native_address(context->options, address); 582 return get_native_address(context->options, address);
587 } 583 }
588 584
589 uint32_t get_instruction_start(m68k_options *opts, native_map_slot * native_code_map, uint32_t address) 585 uint32_t get_instruction_start(m68k_options *opts, uint32_t address)
590 { 586 {
591 address &= opts->gen.address_mask; 587 native_map_slot * native_code_map = opts->gen.native_code_map;
592 //TODO: Refactor part of this loop into some kind of get_ram_chunk function 588 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
593 for (int i = 0; i < opts->gen.memmap_chunks; i++) { 589 if (mem_chunk) {
594 if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) { 590 //calculate the lowest alias for this address
595 //calculate the lowest alias for this address 591 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
596 address = opts->gen.memmap[i].start + ((address - opts->gen.memmap[i].start) & opts->gen.memmap[i].mask);
597 break;
598 }
599 } 592 }
600 593
601 uint32_t chunk = address / NATIVE_CHUNK_SIZE; 594 uint32_t chunk = address / NATIVE_CHUNK_SIZE;
602 if (!native_code_map[chunk].base) { 595 if (!native_code_map[chunk].base) {
603 return 0; 596 return 0;
604 } 597 }
605 uint32_t offset = address % NATIVE_CHUNK_SIZE; 598 uint32_t offset = address % NATIVE_CHUNK_SIZE;
606 if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) { 599 if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
607 return 0; 600 return 0;
608 } 601 }
609 while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD) { 602 while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD)
603 {
610 --address; 604 --address;
611 chunk = address / NATIVE_CHUNK_SIZE; 605 chunk = address / NATIVE_CHUNK_SIZE;
612 offset = address % NATIVE_CHUNK_SIZE; 606 offset = address % NATIVE_CHUNK_SIZE;
613 } 607 }
614 return address; 608 return address;
615 } 609 }
616 610
617 static void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size) 611 static void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size)
618 { 612 {
619 native_map_slot * native_code_map = context->native_code_map;
620 m68k_options * opts = context->options; 613 m68k_options * opts = context->options;
621 address &= opts->gen.address_mask; 614 native_map_slot * native_code_map = opts->gen.native_code_map;
622 uint32_t meta_off = 0; 615 uint32_t meta_off;
623 //TODO: Refactor part of this loop into some kind of get_ram_chunk function 616 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
624 for (int i = 0; i < opts->gen.memmap_chunks; i++) { 617 if (mem_chunk) {
625 if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) { 618 if ((mem_chunk->flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
626 if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) { 619 uint32_t masked = (address & mem_chunk->mask);
627 uint32_t masked = (address & opts->gen.memmap[i].mask); 620 uint32_t final_off = masked + meta_off;
628 uint32_t final_off = masked + meta_off; 621 uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
629 uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3); 622 context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
630 context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7); 623
631 624 uint32_t slot = final_off / 1024;
632 uint32_t slot = final_off / 1024; 625 if (!opts->gen.ram_inst_sizes[slot]) {
633 if (!opts->gen.ram_inst_sizes[slot]) { 626 opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512);
634 opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512);
635 }
636 opts->gen.ram_inst_sizes[slot][(final_off/2) & 511] = native_size;
637
638 //TODO: Deal with case in which end of instruction is in a different memory chunk
639 masked = (address + size - 1) & opts->gen.memmap[i].mask;
640 final_off = masked + meta_off;
641 ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
642 context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
643 } 627 }
644 //calculate the lowest alias for this address 628 opts->gen.ram_inst_sizes[slot][(final_off/2) & 511] = native_size;
645 address = opts->gen.memmap[i].start + ((address - opts->gen.memmap[i].start) & opts->gen.memmap[i].mask); 629
646 break; 630 //TODO: Deal with case in which end of instruction is in a different memory chunk
647 } else if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) { 631 masked = (address + size - 1) & mem_chunk->mask;
648 uint32_t size = chunk_size(&opts->gen, opts->gen.memmap + i); 632 final_off = masked + meta_off;
649 meta_off += size; 633 ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
650 } 634 context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
635 }
636 //calculate the lowest alias for this address
637 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
651 } 638 }
652 639
653 uint32_t chunk = address / NATIVE_CHUNK_SIZE; 640 uint32_t chunk = address / NATIVE_CHUNK_SIZE;
654 if (!native_code_map[chunk].base) { 641 if (!native_code_map[chunk].base) {
655 native_code_map[chunk].base = native_addr; 642 native_code_map[chunk].base = native_addr;
674 } 661 }
675 } 662 }
676 663
677 static uint8_t get_native_inst_size(m68k_options * opts, uint32_t address) 664 static uint8_t get_native_inst_size(m68k_options * opts, uint32_t address)
678 { 665 {
679 address &= opts->gen.address_mask; 666 uint32_t meta_off;
680 uint32_t meta_off = 0; 667 memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_WRITE | MMAP_CODE, &meta_off);
681 for (int i = 0; i < opts->gen.memmap_chunks; i++) { 668 if (chunk) {
682 if (address >= opts->gen.memmap[i].start && address < opts->gen.memmap[i].end) { 669 meta_off += (address - chunk->start) & chunk->mask;
683 if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) != (MMAP_WRITE | MMAP_CODE)) {
684 return 0;
685 }
686 meta_off += address & opts->gen.memmap[i].mask;
687 break;
688 } else if ((opts->gen.memmap[i].flags & (MMAP_WRITE | MMAP_CODE)) == (MMAP_WRITE | MMAP_CODE)) {
689 uint32_t size = chunk_size(&opts->gen, opts->gen.memmap + i);
690 meta_off += size;
691 }
692 } 670 }
693 uint32_t slot = meta_off/1024; 671 uint32_t slot = meta_off/1024;
694 return opts->gen.ram_inst_sizes[slot][(meta_off/2)%512]; 672 return opts->gen.ram_inst_sizes[slot][(meta_off/2)%512];
695 } 673 }
696 674
710 } 688 }
711 } 689 }
712 690
713 uint16_t m68k_get_ir(m68k_context *context) 691 uint16_t m68k_get_ir(m68k_context *context)
714 { 692 {
715 uint32_t inst_addr = get_instruction_start(context->options, context->native_code_map, context->last_prefetch_address-2); 693 uint32_t inst_addr = get_instruction_start(context->options, context->last_prefetch_address-2);
716 uint16_t *native_addr = get_native_pointer(inst_addr, (void **)context->mem_pointers, &context->options->gen); 694 uint16_t *native_addr = get_native_pointer(inst_addr, (void **)context->mem_pointers, &context->options->gen);
717 if (native_addr) { 695 if (native_addr) {
718 return *native_addr; 696 return *native_addr;
719 } 697 }
720 fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address); 698 fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address);
1063 m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler) 1041 m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler)
1064 { 1042 {
1065 size_t ctx_size = sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8; 1043 size_t ctx_size = sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8;
1066 m68k_context * context = malloc(ctx_size); 1044 m68k_context * context = malloc(ctx_size);
1067 memset(context, 0, ctx_size); 1045 memset(context, 0, ctx_size);
1068 context->native_code_map = opts->gen.native_code_map;
1069 context->options = opts; 1046 context->options = opts;
1070 context->int_cycle = CYCLE_NEVER; 1047 context->int_cycle = CYCLE_NEVER;
1071 context->status = 0x27; 1048 context->status = 0x27;
1072 context->reset_handler = (code_ptr)reset_handler; 1049 context->reset_handler = (code_ptr)reset_handler;
1073 return context; 1050 return context;