Make ewram memory lineal
This saves a few cycles in MIPS and simplifies a bit the core. Removed the write map, only affects interpreter performance very minimally. Rewired ARM and x86 handlers to support direct access to I/EWRAM (and VRAM on ARM) to compensate. Overall performance is slightly better but code is cleaner and allows for further improvements in the dynarecs.
This commit is contained in:
		
							parent
							
								
									7e27010a3c
								
							
						
					
					
						commit
						11ec213c99
					
				
					 11 changed files with 271 additions and 368 deletions
				
			
		
							
								
								
									
										178
									
								
								arm/arm_stub.S
									
										
									
									
									
								
							
							
						
						
									
										178
									
								
								arm/arm_stub.S
									
										
									
									
									
								
							|  | @ -4,7 +4,6 @@ | |||
| .globl invalidate_cache_region
 | ||||
| 
 | ||||
| .globl memory_map_read
 | ||||
| .globl memory_map_write
 | ||||
| .globl reg
 | ||||
| .globl palette_ram
 | ||||
| .globl palette_ram_converted
 | ||||
|  | @ -533,31 +532,6 @@ return_to_main: | |||
|   bx lr | ||||
| 
 | ||||
| 
 | ||||
| @ Write out to memory.
 | ||||
| 
 | ||||
| @ Input:
 | ||||
| @ r0: address
 | ||||
| @ r1: value
 | ||||
| @ r2: current pc
 | ||||
| 
 | ||||
| #define execute_store_body(store_type, store_op)                             ;\
 | ||||
|   save_flags()                                                               ;\
 | ||||
|   str lr, [reg_base, #REG_SAVE3]          /* save lr                       */;\
 | ||||
|   tst r0, #0xF0000000                     /* make sure address is in range */;\
 | ||||
|   bne ext_store_u##store_type             /* if not do ext store           */;\ | ||||
|                                                                              ;\
 | ||||
|   ldr r2, =memory_map_write               /* r2 = memory_map_write         */;\
 | ||||
|   mov lr, r0, lsr #15                     /* lr = page index of address    */;\
 | ||||
|   ldr r2, [r2, lr, lsl #2]                /* r2 = memory page              */;\
 | ||||
|                                                                              ;\
 | ||||
|   cmp r2, #0                              /* see if map is ext             */;\
 | ||||
|   beq ext_store_u##store_type             /* if so do ext store            */;\ | ||||
|                                                                              ;\
 | ||||
|   mov r0, r0, lsl #17                     /* isolate bottom 15 bits in top */;\
 | ||||
|   mov r0, r0, lsr #17                     /* like performing and 0x7FFF    */;\
 | ||||
|   store_op r1, [r2, r0]                   /* store result                  */;\
 | ||||
| 
 | ||||
| 
 | ||||
| #define store_align_8()                                                      ;\
 | ||||
|   and r1, r1, #0xff                                                          ;\
 | ||||
| 
 | ||||
|  | @ -568,6 +542,75 @@ return_to_main: | |||
| #define store_align_32()                                                     ;\
 | ||||
|   bic r0, r0, #0x03                                                          ;\
 | ||||
| 
 | ||||
| #define mask_addr_8(nbits)                                                   ;\
 | ||||
|   mov r0, r0, lsl #(32 - nbits)            /* isolate bottom n bits in top */;\
 | ||||
|   mov r0, r0, lsr #(32 - nbits)            /* high bits are now clear      */;\
 | ||||
| 
 | ||||
| #define mask_addr_16(nbits)                                                  ;\
 | ||||
|   mov r0, r0, lsl #(32 - nbits)            /* isolate bottom n bits in top */;\
 | ||||
|   mov r0, r0, lsr #(32 - nbits + 1)        /* high bits are now clear      */;\
 | ||||
|   mov r0, r0, lsl #1                       /* LSB is also zero             */;\
 | ||||
| 
 | ||||
| #define mask_addr_32(nbits)                                                  ;\
 | ||||
|   mov r0, r0, lsl #(32 - nbits)            /* isolate bottom n bits in top */;\
 | ||||
|   mov r0, r0, lsr #(32 - nbits + 2)        /* high bits are now clear      */;\
 | ||||
|   mov r0, r0, lsl #2                       /* 2 LSB are also zero          */;\
 | ||||
| 
 | ||||
| @ Vram, OAM and palette memories can only be accessed at a 16 bit boundary
 | ||||
| #define mask_addr_bus16_32(nbits) mask_addr_32(nbits) | ||||
| #define mask_addr_bus16_16(nbits) mask_addr_16(nbits) | ||||
| #define mask_addr_bus16_8(nbits) \ | ||||
|   mask_addr_16(nbits)            \ | ||||
|   extract_u16(r1, r1) | ||||
| 
 | ||||
| 
 | ||||
| @ Write out to memory.
 | ||||
| 
 | ||||
| @ Input:
 | ||||
| @ r0: address
 | ||||
| @ r1: value
 | ||||
| @ r2: current pc
 | ||||
| @
 | ||||
| @ The instruction at LR is not an inst but a u32 data that contains the PC
 | ||||
| @ Used for SMC. That's why return is essentially `pc = lr + 4`
 | ||||
| 
 | ||||
| #define execute_store_body(store_type, store_op)                             ;\
 | ||||
|   save_flags()                                                               ;\
 | ||||
|   str lr, [reg_base, #REG_SAVE3]          /* save lr                       */;\
 | ||||
|   str r4, [reg_base, #REG_SAVE2]          /* save r4                       */;\
 | ||||
|   tst r0, #0xF0000000                     /* make sure address is in range */;\
 | ||||
|   bne ext_store_u##store_type             /* if not do ext store           */;\ | ||||
|                                                                              ;\
 | ||||
|   ldr lr, =ptr_tbl_##store_type           /* lr = ptr table                */;\ | ||||
|   mov r4, r0, lsr #24                     /* r4 = region number            */;\
 | ||||
|   ldr lr, [lr, r4, lsl #2]                /* lr = function pointer         */;\
 | ||||
|   ldr r4, [reg_base, #REG_SAVE2]          /* restore r4                    */;\
 | ||||
|   bx lr                                   /* jump to handler               */;\
 | ||||
|                                                                              ;\
 | ||||
| ptr_tbl_##store_type:                                                        ;\ | ||||
|   .word ext_store_ignore                  /* 0x00: BIOS, ignore            */;\
 | ||||
|   .word ext_store_ignore                  /* 0x01: ignore                  */;\
 | ||||
|   .word ext_store_ewram_u##store_type     /* 0x02: ewram                   */;\
 | ||||
|   .word ext_store_iwram_u##store_type     /* 0x03: iwram                   */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x04: I/O regs                */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x05: palette RAM             */;\
 | ||||
|   .word ext_store_vram_u##store_type      /* 0x06: vram                    */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x07: oam ram                 */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x08: gamepak: ignore         */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x09: gamepak: ignore         */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x0A: gamepak: ignore         */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x0B: gamepak: ignore         */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x0C: gamepak: ignore         */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x0D: EEPROM                  */;\
 | ||||
|   .word ext_store_u##store_type           /* 0x0E: backup                  */;\
 | ||||
|   .word ext_store_ignore                  /* 0x0F: ignore                  */;\
 | ||||
| 
 | ||||
| @ for ignored areas, just return
 | ||||
| ext_store_ignore: | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          @ pop lr off of stack
 | ||||
|   restore_flags() | ||||
|   add pc, lr, #4                          @ return
 | ||||
| 
 | ||||
| 
 | ||||
| #define execute_store_builder(store_type, store_op, load_op)                 ;\
 | ||||
|                                                                              ;\
 | ||||
|  | @ -577,20 +620,6 @@ return_to_main: | |||
| execute_store_u##store_type:                                                 ;\ | ||||
| _execute_store_u##store_type:                                                ;\ | ||||
|   execute_store_body(store_type, store_op)                                   ;\
 | ||||
|   sub r2, r2, #0x8000                     /* Pointer to code status data   */;\
 | ||||
|   load_op r0, [r2, r0]                    /* check code flag               */;\
 | ||||
|                                                                              ;\
 | ||||
|   cmp r0, #0                              /* see if it's not 0             */;\
 | ||||
|   bne 2f                                  /* if so perform smc write       */;\
 | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* restore lr                    */;\
 | ||||
|   restore_flags()                                                            ;\
 | ||||
|   add pc, lr, #4                          /* return                        */;\
 | ||||
|                                                                              ;\
 | ||||
| 2:                                                                           ;\
 | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* restore lr                    */;\
 | ||||
|   ldr r0, [lr]                            /* load PC                       */;\
 | ||||
|   str r0, [reg_base, #REG_PC]             /* write out PC                  */;\ | ||||
|   b smc_write                             /* perform smc write             */;\
 | ||||
|                                                                              ;\
 | ||||
| ext_store_u##store_type:                                                     ;\ | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* pop lr off of stack           */;\
 | ||||
|  | @ -599,11 +628,53 @@ ext_store_u##store_type:                                                     ;\ | |||
|   store_align_##store_type()                                                 ;\ | ||||
|   call_c_function(write_memory##store_type)                                  ;\ | ||||
|   b write_epilogue                        /* handle additional write stuff */;\
 | ||||
|                                                                              ;\
 | ||||
| ext_store_iwram_u##store_type:                                               ;\ | ||||
|   mask_addr_##store_type(15)              /* Mask to mirror memory (+align)*/;\
 | ||||
|   ldr r2, =(iwram+0x8000)                 /* r2 = iwram base               */;\
 | ||||
|   store_op r1, [r0, r2]                   /* store data                    */;\
 | ||||
|   sub r2, r2, #0x8000                     /* r2 = iwram smc base           */;\
 | ||||
|   load_op r1, [r0, r2]                    /* r1 = SMC sentinel             */;\
 | ||||
|   cmp r1, #0                              /* see if it's not 0             */;\
 | ||||
|   bne 3f                                  /* if so perform smc write       */;\
 | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* pop lr off of stack           */;\
 | ||||
|   restore_flags()                                                            ;\
 | ||||
|   add pc, lr, #4                          /* return                        */;\
 | ||||
|                                                                              ;\
 | ||||
| ext_store_ewram_u##store_type:                                               ;\ | ||||
|   mask_addr_##store_type(18)              /* Mask to mirror memory (+align)*/;\
 | ||||
|   ldr r2, =(ewram)                        /* r2 = ewram base               */;\
 | ||||
|   store_op r1, [r0, r2]                   /* store data                    */;\
 | ||||
|   add r2, r2, #0x40000                    /* r2 = ewram smc base           */;\
 | ||||
|   load_op r1, [r0, r2]                    /* r1 = SMC sentinel             */;\
 | ||||
|   cmp r1, #0                              /* see if it's not 0             */;\
 | ||||
|   bne 3f                                  /* if so perform smc write       */;\
 | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* pop lr off of stack           */;\
 | ||||
|   restore_flags()                                                            ;\
 | ||||
|   add pc, lr, #4                          /* return                        */;\
 | ||||
|                                                                              ;\
 | ||||
| ext_store_vram_u##store_type:                                                ;\ | ||||
|   mask_addr_bus16_##store_type(17)        /* Mask to mirror memory (+align)*/;\
 | ||||
|   cmp r0, #0x18000                        /* Check if exceeds 96KB         */;\
 | ||||
|   subcs r0, r0, #0x8000                   /* Mirror to the last bank       */;\
 | ||||
|   ldr r2, =(vram)                         /* r2 = vram base                */;\
 | ||||
|   store_op r1, [r0, r2]                   /* store data                    */;\
 | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* pop lr off of stack           */;\
 | ||||
|   restore_flags()                                                            ;\
 | ||||
|   add pc, lr, #4                          /* return                        */;\
 | ||||
|                                                                              ;\
 | ||||
| 3:                                                                           ;\
 | ||||
|   ldr lr, [reg_base, #REG_SAVE3]          /* restore lr                    */;\
 | ||||
|   ldr r0, [lr]                            /* load PC                       */;\
 | ||||
|   str r0, [reg_base, #REG_PC]             /* write out PC                  */;\ | ||||
|   b smc_write                             /* perform smc write             */;\
 | ||||
| 
 | ||||
| 
 | ||||
| execute_store_builder(8, strb, ldrb) | ||||
| execute_store_builder(16, strh, ldrh) | ||||
| execute_store_builder(32, str, ldr) | ||||
| 
 | ||||
| @ This is a store that is executed in a strm case (so no SMC checks in-between)
 | ||||
| 
 | ||||
| .globl execute_store_u32_safe
 | ||||
| .globl _execute_store_u32_safe
 | ||||
|  | @ -619,6 +690,28 @@ ext_store_u32_safe: | |||
|   restore_flags() | ||||
|   bx lr                                   @ Return
 | ||||
| 
 | ||||
| ext_store_iwram_u32_safe: | ||||
|   mask_addr_8(15)                         @ Mask to mirror memory (no need to align!)
 | ||||
|   ldr r2, =(iwram+0x8000)                 @ r2 = iwram base
 | ||||
|   str r1, [r0, r2]                        @ store data
 | ||||
|   restore_flags() | ||||
|   ldr pc, [reg_base, #REG_SAVE3]          @ return
 | ||||
| 
 | ||||
| ext_store_ewram_u32_safe: | ||||
|   mask_addr_8(18)                         @ Mask to mirror memory (no need to align!)
 | ||||
|   ldr r2, =(ewram)                        @ r2 = ewram base
 | ||||
|   str r1, [r0, r2]                        @ store data
 | ||||
|   restore_flags() | ||||
|   ldr pc, [reg_base, #REG_SAVE3]          @ return
 | ||||
| 
 | ||||
| ext_store_vram_u32_safe: | ||||
|   mask_addr_8(17)                         @ Mask to mirror memory (no need to align!)
 | ||||
|   ldr r2, =(vram)                         @ r2 = vram base
 | ||||
|   cmp r0, #0x18000                        @ Check if exceeds 96KB
 | ||||
|   subcs r0, r0, #0x8000                   @ Mirror to the last bank
 | ||||
|   str r1, [r0, r2]                        @ store data
 | ||||
|   restore_flags() | ||||
|   ldr pc, [reg_base, #REG_SAVE3]          @ return
 | ||||
| 
 | ||||
| write_epilogue: | ||||
|   cmp r0, #0                              @ check if the write rose an alert
 | ||||
|  | @ -756,6 +849,7 @@ ext_load_##load_type:                                                        ;\ | |||
|   restore_flags()                                                            ;\
 | ||||
|   add pc, lr, #4                          /* return                        */;\
 | ||||
| 
 | ||||
| .pool | ||||
| 
 | ||||
| execute_load_builder(u8, 8, ldrneb, #0xF0000000) | ||||
| execute_load_builder(s8, 8, ldrnesb, #0xF0000000) | ||||
|  | @ -763,14 +857,10 @@ execute_load_builder(u16, 16, ldrneh, #0xF0000001) | |||
| execute_load_builder(s16, 16_signed, ldrnesh, #0xF0000001) | ||||
| execute_load_builder(u32, 32, ldrne, #0xF0000000) | ||||
| 
 | ||||
| .pool | ||||
| 
 | ||||
| .data | ||||
| 
 | ||||
| memory_map_read: | ||||
|   .space 0x8000
 | ||||
| memory_map_write: | ||||
|   .space 0x8000
 | ||||
| palette_ram: | ||||
|   .space 0x400
 | ||||
| palette_ram_converted: | ||||
|  |  | |||
							
								
								
									
										30
									
								
								cpu.c
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								cpu.c
									
										
									
									
									
								
							|  | @ -1003,7 +1003,6 @@ const u32 psr_masks[16] = | |||
| 
 | ||||
| #define fast_write_memory(size, type, address, value)                         \ | ||||
| {                                                                             \ | ||||
|   u8 *map;                                                                    \ | ||||
|   u32 _address = (address) & ~(aligned_address_mask##size & 0x03);            \ | ||||
|   if(_address < 0x10000000)                                                   \ | ||||
|   {                                                                           \ | ||||
|  | @ -1011,17 +1010,9 @@ const u32 psr_masks[16] = | |||
|     memory_writes_##type++;                                                   \ | ||||
|   }                                                                           \ | ||||
|                                                                               \ | ||||
|   if(((_address & aligned_address_mask##size) == 0) &&                        \ | ||||
|    (map = memory_map_write[_address >> 15]))                                  \ | ||||
|   {                                                                           \ | ||||
|     *((type *)((u8 *)map + (_address & 0x7FFF))) = value;                     \ | ||||
|   }                                                                           \ | ||||
|   else                                                                        \ | ||||
|   {                                                                           \ | ||||
|     cpu_alert = write_memory##size(_address, value);                          \ | ||||
|     if(cpu_alert)                                                             \ | ||||
|       goto alert;                                                             \ | ||||
|   }                                                                           \ | ||||
|   cpu_alert = write_memory##size(_address, value);                            \ | ||||
|   if(cpu_alert)                                                               \ | ||||
|     goto alert;                                                               \ | ||||
| }                                                                             \ | ||||
| 
 | ||||
| #define load_aligned32(address, dest)                                         \ | ||||
|  | @ -1046,22 +1037,14 @@ const u32 psr_masks[16] = | |||
| #define store_aligned32(address, value)                                       \ | ||||
| {                                                                             \ | ||||
|   u32 _address = address;                                                     \ | ||||
|   u8 *map = memory_map_write[_address >> 15];                                 \ | ||||
|   if(_address < 0x10000000)                                                   \ | ||||
|   {                                                                           \ | ||||
|     memory_region_access_write_u32[_address >> 24]++;                         \ | ||||
|     memory_writes_u32++;                                                      \ | ||||
|   }                                                                           \ | ||||
|   if(map)                                                                     \ | ||||
|   {                                                                           \ | ||||
|     address32(map, _address & 0x7FFF) = value;                                \ | ||||
|   }                                                                           \ | ||||
|   else                                                                        \ | ||||
|   {                                                                           \ | ||||
|     cpu_alert = write_memory32(_address, value);                              \ | ||||
|     if(cpu_alert)                                                             \ | ||||
|       goto alert;                                                             \ | ||||
|   }                                                                           \ | ||||
|   cpu_alert = write_memory32(_address, value);                                \ | ||||
|   if(cpu_alert)                                                               \ | ||||
|     goto alert;                                                               \ | ||||
| }                                                                             \ | ||||
| 
 | ||||
| #define load_memory_u8(address, dest)                                         \ | ||||
|  | @ -1647,7 +1630,6 @@ void raise_interrupt(irq_type irq_raised) | |||
| 
 | ||||
| #ifndef HAVE_DYNAREC | ||||
| u8 *memory_map_read [8 * 1024]; | ||||
| u8 *memory_map_write[8 * 1024]; | ||||
| u16 palette_ram[512]; | ||||
| u16 palette_ram_converted[512]; | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										4
									
								
								cpu.h
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								cpu.h
									
										
									
									
									
								
							|  | @ -155,11 +155,7 @@ extern u8 *ram_translation_ptr; | |||
| #define MAX_TRANSLATION_GATES 8 | ||||
| 
 | ||||
| extern u32 idle_loop_target_pc; | ||||
| extern u32 force_pc_update_target; | ||||
| extern u32 iwram_stack_optimize; | ||||
| extern u32 allow_smc_ram_u8; | ||||
| extern u32 allow_smc_ram_u16; | ||||
| extern u32 allow_smc_ram_u32; | ||||
| extern u32 direct_map_vram; | ||||
| extern u32 translation_gate_targets; | ||||
| extern u32 translation_gate_target_pc[MAX_TRANSLATION_GATES]; | ||||
|  |  | |||
|  | @ -76,12 +76,6 @@ u32 ewram_code_max = 0xFFFFFFFF; | |||
| 
 | ||||
| u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE]; | ||||
| 
 | ||||
| // Default
 | ||||
| u32 force_pc_update_target = 0xFFFFFFFF; | ||||
| u32 allow_smc_ram_u8 = 1; | ||||
| u32 allow_smc_ram_u16 = 1; | ||||
| u32 allow_smc_ram_u32 = 1; | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
|   u8 *block_offset; | ||||
|  | @ -2813,7 +2807,7 @@ u8 function_cc *block_lookup_address_##type(u32 pc)                           \ | |||
|   switch(pc >> 24)                                                            \ | ||||
|   {                                                                           \ | ||||
|     case 0x2:                                                                 \ | ||||
|       location = (u16 *)(ewram + (pc & 0x7FFF) + ((pc & 0x38000) * 2));       \ | ||||
|       location = (u16 *)(ewram + (pc & 0x3FFFF) + 0x40000);                   \ | ||||
|       block_lookup_translate(type, ram, 1);                                   \ | ||||
|       break;                                                                  \ | ||||
|                                                                               \ | ||||
|  | @ -3119,18 +3113,22 @@ block_lookup_address_builder(dual); | |||
| block_data_type block_data[MAX_BLOCK_SIZE]; | ||||
| block_exit_type block_exits[MAX_EXITS]; | ||||
| 
 | ||||
| #define smc_write_arm_yes()                                                   \ | ||||
|   if(address32(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) == 0x0000) \ | ||||
| #define smc_write_arm_yes() {                                                 \ | ||||
|   int offset = (pc < 0x03000000) ? 0x40000 : -0x8000;                         \ | ||||
|   if(address32(pc_address_block, (block_end_pc & 0x7FFF) + offset) == 0)      \ | ||||
|   {                                                                           \ | ||||
|     address32(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) =           \ | ||||
|     address32(pc_address_block, (block_end_pc & 0x7FFF) + offset) =           \ | ||||
|      0xFFFFFFFF;                                                              \ | ||||
|   }                                                                           \ | ||||
| } | ||||
| 
 | ||||
| #define smc_write_thumb_yes()                                                 \ | ||||
|   if(address16(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) == 0x0000) \ | ||||
| #define smc_write_thumb_yes() {                                               \ | ||||
|   int offset = (pc < 0x03000000) ? 0x40000 : -0x8000;                         \ | ||||
|   if(address16(pc_address_block, (block_end_pc & 0x7FFF) + offset) == 0)      \ | ||||
|   {                                                                           \ | ||||
|     address16(pc_address_block, (block_end_pc & 0x7FFF) - 0x8000) = 0xFFFF;   \ | ||||
|     address16(pc_address_block, (block_end_pc & 0x7FFF) + offset) = 0xFFFF;   \ | ||||
|   }                                                                           \ | ||||
| } | ||||
| 
 | ||||
| #define smc_write_arm_no()                                                    \ | ||||
| 
 | ||||
|  | @ -3428,7 +3426,6 @@ s32 translate_block_thumb(u32 pc, translation_region_type | |||
|   u32 opcode = 0; | ||||
|   u32 last_opcode; | ||||
|   u32 condition; | ||||
|   u32 last_condition; | ||||
|   u32 pc_region = (pc >> 15); | ||||
|   u32 new_pc_region; | ||||
|   u8 *pc_address_block = memory_map_read[pc_region]; | ||||
|  | @ -3514,8 +3511,6 @@ s32 translate_block_thumb(u32 pc, translation_region_type | |||
|   block_exit_position = 0; | ||||
|   block_data_position = 0; | ||||
| 
 | ||||
|   last_condition = 0x0E; | ||||
| 
 | ||||
|   while(pc != block_end_pc) | ||||
|   { | ||||
|     block_data[block_data_position].block_offset = translation_ptr; | ||||
|  | @ -3627,13 +3622,16 @@ s32 translate_block_thumb(u32 pc, translation_region_type | |||
| void flush_translation_cache_ram(void) | ||||
| { | ||||
|   flush_ram_count++; | ||||
| /*  printf("ram flush %d (pc %x), %x to %x, %x to %x\n",
 | ||||
|   /*printf("ram flush %d (pc %x), %x to %x, %x to %x\n",
 | ||||
|    flush_ram_count, reg[REG_PC], iwram_code_min, iwram_code_max, | ||||
|    ewram_code_min, ewram_code_max); */ | ||||
|    ewram_code_min, ewram_code_max);*/ | ||||
| 
 | ||||
|   last_ram_translation_ptr = ram_translation_cache; | ||||
|   ram_translation_ptr = ram_translation_cache; | ||||
|   ram_block_tag_top = 0x0101; | ||||
| 
 | ||||
|   // Proceed to clean the SMC area if needed
 | ||||
|   // (also try to memset as little as possible for performance)
 | ||||
|   if(iwram_code_min != 0xFFFFFFFF) | ||||
|   { | ||||
|     iwram_code_min &= 0x7FFF; | ||||
|  | @ -3643,33 +3641,9 @@ void flush_translation_cache_ram(void) | |||
| 
 | ||||
|   if(ewram_code_min != 0xFFFFFFFF) | ||||
|   { | ||||
|     u32 ewram_code_min_page; | ||||
|     u32 ewram_code_max_page; | ||||
|     u32 ewram_code_min_offset; | ||||
|     u32 ewram_code_max_offset; | ||||
|     u32 i; | ||||
| 
 | ||||
|     ewram_code_min &= 0x3FFFF; | ||||
|     ewram_code_max &= 0x3FFFF; | ||||
| 
 | ||||
|     ewram_code_min_page = ewram_code_min >> 15; | ||||
|     ewram_code_max_page = ewram_code_max >> 15; | ||||
|     ewram_code_min_offset = ewram_code_min & 0x7FFF; | ||||
|     ewram_code_max_offset = ewram_code_max & 0x7FFF; | ||||
| 
 | ||||
|     if(ewram_code_min_page == ewram_code_max_page) | ||||
|     { | ||||
|       memset(ewram + (ewram_code_min_page * 0x10000) + | ||||
|        ewram_code_min_offset, 0, | ||||
|        ewram_code_max_offset - ewram_code_min_offset); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       for(i = ewram_code_min_page + 1; i < ewram_code_max_page; i++) | ||||
|         memset(ewram + (i * 0x10000), 0, 0x8000); | ||||
| 
 | ||||
|       memset(ewram, 0, ewram_code_max_offset); | ||||
|     } | ||||
|     memset(&ewram[0x40000 + ewram_code_min], 0, ewram_code_max - ewram_code_min); | ||||
|   } | ||||
| 
 | ||||
|   iwram_code_min = 0xFFFFFFFF; | ||||
|  |  | |||
							
								
								
									
										121
									
								
								gba_memory.c
									
										
									
									
									
								
							
							
						
						
									
										121
									
								
								gba_memory.c
									
										
									
									
									
								
							|  | @ -596,8 +596,7 @@ u32 function_cc read_eeprom(void) | |||
|                                                                               \ | ||||
|     case 0x02:                                                                \ | ||||
|       /* external work RAM */                                                 \ | ||||
|       address = (address & 0x7FFF) + ((address & 0x38000) * 2) + 0x8000;      \ | ||||
|       value = address##type(ewram, address);                                  \ | ||||
|       value = address##type(ewram, (address & 0x3FFFF));                      \ | ||||
|       break;                                                                  \ | ||||
|                                                                               \ | ||||
|     case 0x03:                                                                \ | ||||
|  | @ -1907,8 +1906,7 @@ void function_cc write_rtc(u32 address, u32 value) | |||
|   {                                                                           \ | ||||
|     case 0x02:                                                                \ | ||||
|       /* external work RAM */                                                 \ | ||||
|       address = (address & 0x7FFF) + ((address & 0x38000) * 2) + 0x8000;      \ | ||||
|       address##type(ewram, address) = value;                                  \ | ||||
|       address##type(ewram, (address & 0x3FFFF)) = value;                      \ | ||||
|       break;                                                                  \ | ||||
|                                                                               \ | ||||
|     case 0x03:                                                                \ | ||||
|  | @ -2454,7 +2452,7 @@ s32 load_bios(char *name) | |||
| 
 | ||||
| // DMA memory regions can be one of the following:
 | ||||
| // IWRAM - 32kb offset from the contiguous iwram region.
 | ||||
| // EWRAM - like segmented but with self modifying code check.
 | ||||
| // EWRAM - also contiguous but with self modifying code check mirror.
 | ||||
| // VRAM - 96kb offset from the contiguous vram region, should take care
 | ||||
| // Palette RAM - Converts palette entries when written to.
 | ||||
| // OAM RAM - Sets OAM modified flag to true.
 | ||||
|  | @ -2527,11 +2525,8 @@ dma_region_type dma_region_map[16] = | |||
| #define dma_vars_iwram(type)                                                  \ | ||||
|   dma_smc_vars_##type()                                                       \ | ||||
| 
 | ||||
| #define dma_vars_vram(type)                                                   \ | ||||
| 
 | ||||
| #define dma_vars_palette_ram(type)                                            \ | ||||
| 
 | ||||
| #define dma_oam_ram_src()                                                     \ | ||||
| #define dma_vars_ewram(type)                                                  \ | ||||
|   dma_smc_vars_##type() | ||||
| 
 | ||||
| #define dma_oam_ram_dest()                                                    \ | ||||
|   oam_update = 1                                                              \ | ||||
|  | @ -2539,14 +2534,17 @@ dma_region_type dma_region_map[16] = | |||
| #define dma_vars_oam_ram(type)                                                \ | ||||
|   dma_oam_ram_##type()                                                        \ | ||||
| 
 | ||||
| #define dma_vars_io(type)                                                     \ | ||||
| #define dma_vars_io(type) | ||||
| #define dma_vars_vram(type) | ||||
| #define dma_vars_palette_ram(type) | ||||
| #define dma_vars_bios(type) | ||||
| #define dma_vars_ext(type) | ||||
| 
 | ||||
| #define dma_oam_ram_src() | ||||
| 
 | ||||
| #define dma_segmented_load_src()                                              \ | ||||
|   memory_map_read[src_current_region]                                         \ | ||||
| 
 | ||||
| #define dma_segmented_load_dest()                                             \ | ||||
|   memory_map_write[dest_current_region]                                       \ | ||||
| 
 | ||||
| #define dma_vars_gamepak(type)                                                \ | ||||
|   u32 type##_new_region;                                                      \ | ||||
|   u32 type##_current_region = type##_ptr >> 15;                               \ | ||||
|  | @ -2558,24 +2556,6 @@ dma_region_type dma_region_map[16] = | |||
|     type##_address_block = load_gamepak_page(type##_current_region & 0x3FF);  \ | ||||
|   }                                                                           \ | ||||
| 
 | ||||
| #define dma_vars_ewram(type)                                                  \ | ||||
|   dma_smc_vars_##type();                                                      \ | ||||
|   u32 type##_new_region;                                                      \ | ||||
|   u32 type##_current_region = type##_ptr >> 15;                               \ | ||||
|   u8 *type##_address_block = dma_segmented_load_##type()                      \ | ||||
| 
 | ||||
| #define dma_vars_bios(type)                                                   \ | ||||
| 
 | ||||
| #define dma_vars_ext(type)                                                    \ | ||||
| 
 | ||||
| #define dma_ewram_check_region(type)                                          \ | ||||
|   type##_new_region = (type##_ptr >> 15);                                     \ | ||||
|   if(type##_new_region != type##_current_region)                              \ | ||||
|   {                                                                           \ | ||||
|     type##_current_region = type##_new_region;                                \ | ||||
|     type##_address_block = dma_segmented_load_##type();                       \ | ||||
|   }                                                                           \ | ||||
| 
 | ||||
| #define dma_gamepak_check_region(type)                                        \ | ||||
|   type##_new_region = (type##_ptr >> 15);                                     \ | ||||
|   if(type##_new_region != type##_current_region)                              \ | ||||
|  | @ -2605,9 +2585,7 @@ dma_region_type dma_region_map[16] = | |||
|   read_value = address##transfer_size(palette_ram, type##_ptr & 0x3FF)        \ | ||||
| 
 | ||||
| #define dma_read_ewram(type, transfer_size)                                   \ | ||||
|   dma_ewram_check_region(type);                                               \ | ||||
|   read_value = address##transfer_size(type##_address_block,                   \ | ||||
|    type##_ptr & 0x7FFF)                                                       \ | ||||
|   read_value = address##transfer_size(ewram, type##_ptr & 0x3FFFF)            \ | ||||
| 
 | ||||
| #define dma_read_gamepak(type, transfer_size)                                 \ | ||||
|   dma_gamepak_check_region(type);                                             \ | ||||
|  | @ -2642,12 +2620,9 @@ dma_region_type dma_region_map[16] = | |||
|   write_memory##transfer_size(type##_ptr, read_value)                         \ | ||||
| 
 | ||||
| #define dma_write_ewram(type, transfer_size)                                  \ | ||||
|   dma_ewram_check_region(type);                                               \ | ||||
|                                                                               \ | ||||
|   address##transfer_size(type##_address_block, type##_ptr & 0x7FFF) =         \ | ||||
|     read_value;                                                               \ | ||||
|   smc_trigger |= address##transfer_size(type##_address_block,                 \ | ||||
|    (type##_ptr & 0x7FFF) - 0x8000)                                            \ | ||||
|   address##transfer_size(ewram, type##_ptr & 0x3FFFF) = read_value;           \ | ||||
|   smc_trigger |= address##transfer_size(ewram,                                \ | ||||
|    (type##_ptr & 0x3FFFF) + 0x40000)                                          \ | ||||
| 
 | ||||
| #define dma_epilogue_iwram()                                                  \ | ||||
|   if(smc_trigger)                                                             \ | ||||
|  | @ -3105,14 +3080,6 @@ cpu_alert_type dma_transfer(dma_transfer_type *dma) | |||
|    map_offset++)                                                              \ | ||||
|     memory_map_##type[map_offset] = NULL;                                     \ | ||||
| 
 | ||||
| #define map_ram_region(type, start, end, mirror_blocks, region)               \ | ||||
|   for(map_offset = (start) / 0x8000; map_offset <                             \ | ||||
|    ((end) / 0x8000); map_offset++)                                            \ | ||||
|   {                                                                           \ | ||||
|     memory_map_##type[map_offset] =                                           \ | ||||
|      ((u8 *)region) + ((map_offset % mirror_blocks) * 0x10000) + 0x8000;      \ | ||||
|   }                                                                           \ | ||||
| 
 | ||||
| #define map_vram(type)                                                        \ | ||||
|   for(map_offset = 0x6000000 / 0x8000; map_offset < (0x7000000 / 0x8000);     \ | ||||
|    map_offset += 4)                                                           \ | ||||
|  | @ -3274,8 +3241,8 @@ void init_memory(void) | |||
|   // Fill memory map regions, areas marked as NULL must be checked directly
 | ||||
|   map_region(read, 0x0000000, 0x1000000, 1, bios_rom); | ||||
|   map_null(read, 0x1000000, 0x2000000); | ||||
|   map_ram_region(read, 0x2000000, 0x3000000, 8, ewram); | ||||
|   map_ram_region(read, 0x3000000, 0x4000000, 1, iwram); | ||||
|   map_region(read, 0x2000000, 0x3000000, 8, ewram); | ||||
|   map_region(read, 0x3000000, 0x4000000, 1, &iwram[0x8000]); | ||||
|   map_region(read, 0x4000000, 0x5000000, 1, io_registers); | ||||
|   map_null(read, 0x5000000, 0x6000000); | ||||
|   map_null(read, 0x6000000, 0x7000000); | ||||
|  | @ -3284,45 +3251,12 @@ void init_memory(void) | |||
|   init_memory_gamepak(); | ||||
|   map_null(read, 0xE000000, 0x10000000); | ||||
| 
 | ||||
|   // Fill memory map regions, areas marked as NULL must be checked directly
 | ||||
|   map_null(write, 0x0000000, 0x2000000); | ||||
|   map_ram_region(write, 0x2000000, 0x3000000, 8, ewram); | ||||
|   map_ram_region(write, 0x3000000, 0x4000000, 1, iwram); | ||||
|   map_null(write, 0x4000000, 0x5000000); | ||||
|   map_null(write, 0x5000000, 0x6000000); | ||||
| 
 | ||||
|   // The problem here is that the current method of handling self-modifying code
 | ||||
|   // requires writeable memory to be proceeded by 32KB SMC data areas or be
 | ||||
|   // indirectly writeable. It's possible to get around this if you turn off the SMC
 | ||||
|   // check altogether, but this will make a good number of ROMs crash (perhaps most
 | ||||
|   // of the ones that actually need it? This has yet to be determined).
 | ||||
| 
 | ||||
|   // This is because VRAM cannot be efficiently made incontiguous, and still allow
 | ||||
|   // the renderer to work as efficiently. It would, at the very least, require a
 | ||||
|   // lot of hacking of the renderer which I'm not prepared to do.
 | ||||
|   // TODO(davidgfnet): add SMC VRAM detection
 | ||||
| 
 | ||||
|   // However, it IS possible to directly map the first page no matter what because
 | ||||
|   // there's 32kb of blank stuff sitting beneath it.
 | ||||
|   if(direct_map_vram) | ||||
|   { | ||||
|     map_vram(write); | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     map_null(write, 0x6000000, 0x7000000); | ||||
|   } | ||||
| 
 | ||||
|   map_null(write, 0x7000000, 0x8000000); | ||||
|   map_null(write, 0x8000000, 0xE000000); | ||||
|   map_null(write, 0xE000000, 0x10000000); | ||||
| 
 | ||||
|   memset(io_registers, 0, 0x8000); | ||||
|   memset(oam_ram, 0, 0x400); | ||||
|   memset(palette_ram, 0, 0x400); | ||||
|   memset(iwram, 0, 0x10000); | ||||
|   memset(ewram, 0, 0x80000); | ||||
|   memset(vram, 0, 0x18000); | ||||
|   memset(io_registers, 0, sizeof(io_registers)); | ||||
|   memset(oam_ram, 0, sizeof(oam_ram)); | ||||
|   memset(palette_ram, 0, sizeof(palette_ram)); | ||||
|   memset(iwram, 0, sizeof(iwram)); | ||||
|   memset(ewram, 0, sizeof(ewram)); | ||||
|   memset(vram, 0, sizeof(vram)); | ||||
| 
 | ||||
|   io_registers[REG_DISPCNT] = 0x80; | ||||
|   io_registers[REG_P1] = 0x3FF; | ||||
|  | @ -3426,8 +3360,6 @@ void gba_save_state(void* dst) | |||
| #define memory_savestate_builder(type)                         \ | ||||
| void memory_##type##_savestate(void)                           \ | ||||
| {                                                              \ | ||||
|   u32 i;                                                       \ | ||||
|                                                                \ | ||||
|   state_mem_##type##_variable(backup_type);                    \ | ||||
|   state_mem_##type##_variable(sram_size);                      \ | ||||
|   state_mem_##type##_variable(flash_mode);                     \ | ||||
|  | @ -3453,10 +3385,7 @@ void memory_##type##_savestate(void)                           \ | |||
|   state_mem_##type##_array(dma);                               \ | ||||
|                                                                \ | ||||
|   state_mem_##type(iwram + 0x8000, 0x8000);                    \ | ||||
|   for(i = 0; i < 8; i++)                                       \ | ||||
|   {                                                            \ | ||||
|     state_mem_##type(ewram + (i * 0x10000) + 0x8000, 0x8000);  \ | ||||
|   }                                                            \ | ||||
|   state_mem_##type(ewram, 0x40000);                            \ | ||||
|   state_mem_##type(vram, 0x18000);                             \ | ||||
|   state_mem_##type(oam_ram, 0x400);                            \ | ||||
|   state_mem_##type(palette_ram, 0x400);                        \ | ||||
|  |  | |||
|  | @ -214,7 +214,6 @@ extern u8 ewram[1024 * 256 * 2]; | |||
| extern u8 iwram[1024 * 32 * 2]; | ||||
| 
 | ||||
| extern u8 *memory_map_read[8 * 1024]; | ||||
| extern u8 *memory_map_write[8 * 1024]; | ||||
| 
 | ||||
| extern u32 reg[64]; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										11
									
								
								libretro.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								libretro.c
									
										
									
									
									
								
							|  | @ -809,15 +809,8 @@ static void set_memory_descriptors(void) | |||
| { | ||||
|    const uint64_t mem = RETRO_MEMORY_SYSTEM_RAM; | ||||
|    struct retro_memory_descriptor desc[9] = { | ||||
|       { mem, iwram, 0x00000 + 0x8000, 0x3000000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x00000 + 0x8000, 0x2000000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x10000 + 0x8000, 0x2008000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x20000 + 0x8000, 0x2010000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x30000 + 0x8000, 0x2018000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x40000 + 0x8000, 0x2020000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x50000 + 0x8000, 0x2028000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x60000 + 0x8000, 0x2030000, 0, 0, 0x8000, NULL }, | ||||
|       { mem, ewram, 0x70000 + 0x8000, 0x2038000, 0, 0, 0x8000, NULL } | ||||
|       { mem, iwram, 0x00000 + 0x8000, 0x3000000, 0, 0,  0x8000, NULL }, | ||||
|       { mem, ewram, 0x00000,          0x2000000, 0, 0, 0x40000, NULL }, | ||||
|    }; | ||||
|    struct retro_memory_map retromap = { | ||||
|       desc, | ||||
|  |  | |||
|  | @ -1010,47 +1010,10 @@ u32 generate_load_rm_sh_##flags_op(u32 rm)                                    \ | |||
| {                                                                             \ | ||||
|   u32 _address = (u32)(address);                                              \ | ||||
|   u32 _address_hi = (_address + 0x8000) >> 16;                                \ | ||||
|   generate_load_imm(ireg, address);                                           \ | ||||
|   mips_emit_lui(ireg, _address_hi >> 16)                                      \ | ||||
|   generate_load_memory_##type(ireg, _address - (_address_hi << 16));          \ | ||||
| }                                                                             \ | ||||
| 
 | ||||
| #define generate_known_address_load_builder(type)                             \ | ||||
|   u32 generate_known_address_load_##type(u32 rd, u32 address)                 \ | ||||
|   {                                                                           \ | ||||
|     switch(address >> 24)                                                     \ | ||||
|     {                                                                         \ | ||||
|       /* Read from the BIOS ROM, can be converted to an immediate load.       \
 | ||||
|          Only really possible to do this from the BIOS but should be okay     \ | ||||
|          to allow it everywhere */                                            \ | ||||
|       case 0x00:                                                              \ | ||||
|         u32 imm = read_memory_constant_##type(address);                       \ | ||||
|         generate_load_imm(arm_to_mips_reg[rd], imm);                          \ | ||||
|         return 1;                                                             \ | ||||
|                                                                               \ | ||||
|       /* Read from RAM, can be converted to a load */                         \ | ||||
|       case 0x02:                                                              \ | ||||
|         generate_load_memory(type, arm_to_mips_reg[rd], (u8 *)ewram +         \ | ||||
|          (address & 0x7FFF) + ((address & 0x38000) * 2) + 0x8000);            \ | ||||
|         return 1;                                                             \ | ||||
|                                                                               \ | ||||
|       case 0x03:                                                              \ | ||||
|         generate_load_memory(type, arm_to_mips_reg[rd], (u8 *)iwram +         \ | ||||
|          (address & 0x7FFF) + 0x8000);                                        \ | ||||
|         return 1;                                                             \ | ||||
|                                                                               \ | ||||
|       /* Read from gamepak ROM, this has to be an immediate load because      \
 | ||||
|          it might not actually be in memory anymore when we get to it. */     \ | ||||
|       case 0x08:                                                              \ | ||||
|         u32 imm = read_memory_constant_##type(address);                       \ | ||||
|         generate_load_imm(arm_to_mips_reg[rd], imm);                          \ | ||||
|         return 1;                                                             \ | ||||
|                                                                               \ | ||||
|       default:                                                                \ | ||||
|         return 0;                                                             \ | ||||
|     }                                                                         \ | ||||
|   }                                                                           \ | ||||
| 
 | ||||
| #define generate_block_extra_vars()                                           \ | ||||
|   u32 stored_pc = pc;                                                         \ | ||||
|   u8 *update_trampoline                                                       \ | ||||
|  | @ -1060,12 +1023,6 @@ u32 generate_load_rm_sh_##flags_op(u32 rm)                                    \ | |||
|   generate_load_rm_sh_builder(flags);                                         \ | ||||
|   generate_load_rm_sh_builder(no_flags);                                      \ | ||||
|                                                                               \ | ||||
| /*  generate_known_address_load_builder(u8);                                  \
 | ||||
|   generate_known_address_load_builder(u16);                                   \ | ||||
|   generate_known_address_load_builder(u32);                                   \ | ||||
|   generate_known_address_load_builder(s8);                                    \ | ||||
|   generate_known_address_load_builder(s16); */                                \ | ||||
|                                                                               \ | ||||
|   u32 generate_load_offset_sh(u32 rm)                                         \ | ||||
|   {                                                                           \ | ||||
|     switch((opcode >> 5) & 0x03)                                              \ | ||||
|  | @ -2787,12 +2744,13 @@ static void emit_pmemld_stub( | |||
|     mips_emit_lui(reg_rv, ((base_addr + 0x8000) >> 16)); | ||||
| 
 | ||||
|     if (region == 2) { | ||||
|       // EWRAM is a bit special
 | ||||
|       // Can't do EWRAM with an `andi` instruction (18 bits mask)
 | ||||
|       mips_emit_ext(reg_a0, reg_a0, 0, 18);      // &= 0x3ffff
 | ||||
|       if (!aligned && alignment != 0) { | ||||
|         mips_emit_ins(reg_a0, reg_zero, 0, size);// addr & ~1/2 (align to size)
 | ||||
|       } | ||||
|       // Need to insert a zero in the addr (due to how it's mapped)
 | ||||
|       mips_emit_andi(reg_temp, reg_a0, memmask); // Clears all but 15 bits (LSB)
 | ||||
|       mips_emit_ext(reg_a0,   reg_a0, 15, 3);    // Gets the 3 higher bits (from the 18)
 | ||||
|       mips_emit_ins(reg_temp, reg_a0, 16, 3);    // Puts the 3 bits into bits 18..16
 | ||||
|       mips_emit_addu(reg_rv, reg_rv, reg_temp);  // Adds to the base addr
 | ||||
|       mips_emit_addu(reg_rv, reg_rv, reg_a0);    // Adds to the base addr
 | ||||
|     } else if (region == 6) { | ||||
|       // VRAM is mirrored every 128KB but the last 32KB is mapped to the previous
 | ||||
|       mips_emit_ext(reg_temp, reg_a0, 15, 2);    // Extract bits 15 and 16
 | ||||
|  | @ -2862,12 +2820,13 @@ static void emit_pmemst_stub( | |||
|   } | ||||
| 
 | ||||
|   if (region == 2) { | ||||
|     // EWRAM is a bit special
 | ||||
|     // Can't do EWRAM with an `andi` instruction (18 bits mask)
 | ||||
|     mips_emit_ext(reg_a0, reg_a0, 0, 18);      // &= 0x3ffff
 | ||||
|     if (!aligned && realsize != 0) { | ||||
|       mips_emit_ins(reg_a0, reg_zero, 0, size);// addr & ~1/2 (align to size)
 | ||||
|     } | ||||
|     // Need to insert a zero in the addr (due to how it's mapped)
 | ||||
|     mips_emit_andi(reg_temp, reg_a0, memmask); // Clears all but 15 bits (LSB)
 | ||||
|     mips_emit_ext(reg_a0,   reg_a0, 15, 3);    // Gets the 3 higher bits (from the 18)
 | ||||
|     mips_emit_ins(reg_temp, reg_a0, 16, 3);    // Puts the 3 bits into bits 18..16
 | ||||
|     mips_emit_addu(reg_rv, reg_rv, reg_temp);  // Adds to the base addr
 | ||||
|     mips_emit_addu(reg_rv, reg_rv, reg_a0);    // Adds to the base addr
 | ||||
|   } else if (region == 6) { | ||||
|     // VRAM is mirrored every 128KB but the last 32KB is mapped to the previous
 | ||||
|     mips_emit_ext(reg_temp, reg_a0, 15, 2);    // Extract bits 15 and 16
 | ||||
|  | @ -2888,7 +2847,12 @@ static void emit_pmemst_stub( | |||
|   // Generate SMC write and tracking
 | ||||
|   // TODO: Should we have SMC checks here also for aligned?
 | ||||
|   if (meminfo->check_smc && !aligned) { | ||||
|     mips_emit_addiu(reg_temp, reg_rv, 0x8000); // -32KB is the addr of the SMC buffer
 | ||||
|     if (region == 2) { | ||||
|       mips_emit_lui(reg_temp, 0x40000 >> 16); | ||||
|       mips_emit_addu(reg_temp, reg_rv, reg_temp); // SMC lives after the ewram
 | ||||
|     } else { | ||||
|       mips_emit_addiu(reg_temp, reg_rv, 0x8000); // -32KB is the addr of the SMC buffer
 | ||||
|     } | ||||
|     if (realsize == 2) { | ||||
|       mips_emit_lw(reg_temp, reg_temp, base_addr); | ||||
|     } else if (realsize == 1) { | ||||
|  | @ -3272,8 +3236,8 @@ void init_emitter() { | |||
|   const t_stub_meminfo ldinfo [] = { | ||||
|     { emit_pmemld_stub,  0, 0x4000, false, false, (u32)bios_rom }, | ||||
|     // 1 Open load / Ignore store
 | ||||
|     { emit_pmemld_stub,  2, 0x8000, true,  false, (u32)&ewram[0x8000] }, | ||||
|     { emit_pmemld_stub,  3, 0x8000, true,  false, (u32)&iwram[0x8000] },   // memsize wrong on purpose, see above
 | ||||
|     { emit_pmemld_stub,  2, 0x8000, true,  false, (u32)ewram },      // memsize wrong on purpose
 | ||||
|     { emit_pmemld_stub,  3, 0x8000, true,  false, (u32)&iwram[0x8000] }, | ||||
|     { emit_pmemld_stub,  4,  0x400, false, false, (u32)io_registers }, | ||||
|     { emit_pmemld_stub,  5,  0x400, false, true,  (u32)palette_ram }, | ||||
|     { emit_pmemld_stub,  6,    0x0, false, true,  (u32)vram },             // same, vram is a special case
 | ||||
|  | @ -3308,8 +3272,8 @@ void init_emitter() { | |||
|   } | ||||
| 
 | ||||
|   const t_stub_meminfo stinfo [] = { | ||||
|     { emit_pmemst_stub, 2, 0x8000, true,  false, (u32)&ewram[0x8000] }, | ||||
|     { emit_pmemst_stub, 3, 0x8000, true,  false, (u32)&iwram[0x8000] },   // memsize wrong on purpose, see above
 | ||||
|     { emit_pmemst_stub, 2, 0x8000, true,  false, (u32)ewram }, | ||||
|     { emit_pmemst_stub, 3, 0x8000, true,  false, (u32)&iwram[0x8000] }, | ||||
|     // I/O is special and mapped with a function call
 | ||||
|     { emit_palette_hdl, 5,  0x400, false, true,  (u32)palette_ram }, | ||||
|     { emit_pmemst_stub, 6,    0x0, false, true,  (u32)vram },             // same, vram is a special case
 | ||||
|  |  | |||
|  | @ -44,7 +44,6 @@ | |||
| 
 | ||||
| .global write_io_epilogue
 | ||||
| .global memory_map_read
 | ||||
| .global memory_map_write
 | ||||
| .global tmemld
 | ||||
| .global tmemst
 | ||||
| .global tmemst
 | ||||
|  | @ -609,9 +608,6 @@ execute_arm_translate_internal: | |||
| .data | ||||
| .align 6
 | ||||
| 
 | ||||
| memory_map_write: | ||||
|   .space 0x8000
 | ||||
| 
 | ||||
| memory_map_read: | ||||
|   .space 0x8000
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1485,23 +1485,13 @@ u32 function_cc execute_aligned_load32(u32 address) | |||
|     return read_memory32(address); | ||||
| } | ||||
| 
 | ||||
| void function_cc execute_aligned_store32(u32 address, u32 source) | ||||
| { | ||||
|   u8 *map; | ||||
| 
 | ||||
|   if(!(address & 0xF0000000) && (map = memory_map_write[address >> 15])) | ||||
|     address32(map, address & 0x7FFF) = source; | ||||
|   else | ||||
|     write_memory32(address, source); | ||||
| } | ||||
| 
 | ||||
| #define arm_block_memory_load()                                               \ | ||||
|   generate_function_call(execute_aligned_load32);                             \ | ||||
|   generate_store_reg(rv, i)                                                   \ | ||||
| 
 | ||||
| #define arm_block_memory_store()                                              \ | ||||
|   generate_load_reg_pc(a1, i, 8);                                             \ | ||||
|   generate_function_call(execute_aligned_store32)                             \ | ||||
|   generate_function_call(write_memory32)                                      \ | ||||
| 
 | ||||
| #define arm_block_memory_final_load()                                         \ | ||||
|   arm_block_memory_load()                                                     \ | ||||
|  | @ -1956,7 +1946,7 @@ u32 function_cc execute_ror_imm_op(u32 value, u32 shift) | |||
| #define thumb_block_memory_extra_push_lr(base_reg)                            \ | ||||
|   generate_add_reg_reg_imm(a0, s0, (bit_count[reg_list] * 4));                \ | ||||
|   generate_load_reg(a1, REG_LR);                                              \ | ||||
|   generate_function_call(execute_aligned_store32)                             \ | ||||
|   generate_function_call(write_memory32)                                      \ | ||||
| 
 | ||||
| #define thumb_block_memory_load()                                             \ | ||||
|   generate_function_call(execute_aligned_load32);                             \ | ||||
|  | @ -1964,7 +1954,7 @@ u32 function_cc execute_ror_imm_op(u32 value, u32 shift) | |||
| 
 | ||||
| #define thumb_block_memory_store()                                            \ | ||||
|   generate_load_reg(a1, i);                                                   \ | ||||
|   generate_function_call(execute_aligned_store32)                             \ | ||||
|   generate_function_call(write_memory32)                                      \ | ||||
| 
 | ||||
| #define thumb_block_memory_final_load()                                       \ | ||||
|   thumb_block_memory_load()                                                   \ | ||||
|  |  | |||
							
								
								
									
										134
									
								
								x86/x86_stub.S
									
										
									
									
									
								
							
							
						
						
									
										134
									
								
								x86/x86_stub.S
									
										
									
									
									
								
							|  | @ -29,7 +29,6 @@ | |||
| #define _execute_store_cpsr execute_store_cpsr | ||||
| #define _execute_arm_translate execute_arm_translate | ||||
| #define _memory_map_read memory_map_read | ||||
| #define _memory_map_write memory_map_write | ||||
| #define _reg reg | ||||
| #define _reg_mode reg_mode | ||||
| #define _oam_update oam_update | ||||
|  | @ -68,7 +67,6 @@ | |||
| .global _execute_arm_translate
 | ||||
| 
 | ||||
| .global _memory_map_read
 | ||||
| .global _memory_map_write
 | ||||
| .global _reg
 | ||||
| .global _reg_mode
 | ||||
| .global _spsr
 | ||||
|  | @ -231,6 +229,20 @@ ext_store_eeprom: | |||
| 
 | ||||
| # 8bit ext memory routines | ||||
| 
 | ||||
| ext_store_iwram8: | ||||
|   and $0x7FFF, %eax                 # wrap around address | ||||
|   mov %dl, (_iwram+0x8000)(%eax)    # perform store | ||||
|   cmpb $0, _iwram(%eax)             # Check SMC mirror | ||||
|   jne smc_write | ||||
|   ret | ||||
| 
 | ||||
| ext_store_ewram8: | ||||
|   and $0x3FFFF, %eax                # wrap around address | ||||
|   mov %dl, _ewram(%eax)             # perform store | ||||
|   cmpb $0, (_ewram+0x40000)(%eax)   # Check SMC mirror | ||||
|   jne smc_write | ||||
|   ret | ||||
| 
 | ||||
| ext_store_io8: | ||||
|   and $0x3FF, %eax            # wrap around address | ||||
|   and $0xFF, %edx | ||||
|  | @ -267,8 +279,8 @@ ext_store_backup: | |||
| ext_store_u8_jtable: | ||||
|   .long ext_store_ignore      # 0x00 BIOS, ignore | ||||
|   .long ext_store_ignore      # 0x01 invalid, ignore | ||||
|   .long ext_store_ignore      # 0x02 EWRAM, should have been hit already | ||||
|   .long ext_store_ignore      # 0x03 IWRAM, should have been hit already | ||||
|   .long ext_store_ewram8      # 0x02 EWRAM | ||||
|   .long ext_store_iwram8      # 0x03 IWRAM | ||||
|   .long ext_store_io8         # 0x04 I/O registers | ||||
|   .long ext_store_palette8    # 0x05 Palette RAM | ||||
|   .long ext_store_vram8       # 0x06 VRAM | ||||
|  | @ -281,7 +293,12 @@ ext_store_u8_jtable: | |||
|   .long ext_store_eeprom      # 0x0D EEPROM (possibly) | ||||
|   .long ext_store_backup      # 0x0E Flash ROM/SRAM | ||||
| 
 | ||||
| ext_store_u8: | ||||
| # eax: address to write to | ||||
| # edx: value to write | ||||
| # ecx: current pc | ||||
| 
 | ||||
| _execute_store_u8: | ||||
|   mov %ecx, REG_PC(%ebx)      # write out the PC | ||||
|   mov %eax, %ecx              # ecx = address | ||||
|   shr $24, %ecx               # ecx = address >> 24 | ||||
|   cmp $15, %ecx | ||||
|  | @ -290,47 +307,22 @@ ext_store_u8: | |||
|   mov ext_store_u8_jtable(, %ecx, 4), %ecx | ||||
|   jmp *%ecx                   # jump to table index | ||||
| 
 | ||||
| # eax: address to write to | ||||
| # edx: value to write | ||||
| # ecx: current pc | ||||
| 
 | ||||
| _execute_store_u8: | ||||
|   mov %ecx, REG_PC(%ebx)      # write out the PC | ||||
|   mov %eax, %ecx              # ecx = address | ||||
|   test $0xF0000000, %ecx      # check address range | ||||
|   jnz ext_store_u8            # if above perform an extended write | ||||
|   shr $15, %ecx               # ecx = page number of address | ||||
|   # load the corresponding memory map offset | ||||
|   mov _memory_map_write(, %ecx, 4), %ecx | ||||
|   test %ecx, %ecx             # see if it's NULL | ||||
|   jz ext_store_u8             # if so perform an extended write | ||||
|   and $0x7FFF, %eax           # isolate the lower 15bits of the address | ||||
|   mov %dl, (%eax, %ecx)       # store the value | ||||
|   # check for self-modifying code | ||||
|   testb $0xFF, -32768(%eax, %ecx) | ||||
|   jne smc_write | ||||
|   ret                         # return | ||||
| 
 | ||||
| _execute_store_u16: | ||||
|   mov %ecx, REG_PC(%ebx)      # write out the PC | ||||
|   and $~0x01, %eax            # fix alignment | ||||
|   mov %eax, %ecx              # ecx = address | ||||
|   test $0xF0000000, %ecx      # check address range | ||||
|   jnz ext_store_u16           # if above perform an extended write | ||||
|   shr $15, %ecx               # ecx = page number of address | ||||
|   # load the corresponding memory map offset | ||||
|   mov _memory_map_write(, %ecx, 4), %ecx | ||||
|   test %ecx, %ecx             # see if it's NULL | ||||
|   jz ext_store_u16            # if so perform an extended write | ||||
|   and $0x7FFF, %eax           # isolate the lower 15bits of the address | ||||
|   mov %dx, (%eax, %ecx)       # store the value | ||||
|   # check for self-modifying code | ||||
|   testw $0xFFFF, -32768(%eax, %ecx) | ||||
|   jne smc_write | ||||
|   ret                         # return | ||||
| 
 | ||||
| # 16bit ext memory routines | ||||
| 
 | ||||
| ext_store_iwram16: | ||||
|   and $0x7FFF, %eax                 # wrap around address | ||||
|   mov %dx, (_iwram+0x8000)(%eax)    # perform store | ||||
|   cmpw $0, _iwram(%eax)             # Check SMC mirror | ||||
|   jne smc_write | ||||
|   ret | ||||
| 
 | ||||
| ext_store_ewram16: | ||||
|   and $0x3FFFF, %eax                # wrap around address | ||||
|   mov %dx, _ewram(%eax)             # perform store | ||||
|   cmpw $0, (_ewram+0x40000)(%eax)   # Check SMC mirror | ||||
|   jne smc_write | ||||
|   ret | ||||
| 
 | ||||
| ext_store_io16: | ||||
|   and $0x3FF, %eax            # wrap around address | ||||
|   and $0xFFFF, %edx | ||||
|  | @ -377,8 +369,8 @@ ext_store_rtc: | |||
| ext_store_u16_jtable: | ||||
|   .long ext_store_ignore      # 0x00 BIOS, ignore | ||||
|   .long ext_store_ignore      # 0x01 invalid, ignore | ||||
|   .long ext_store_ignore      # 0x02 EWRAM, should have been hit already | ||||
|   .long ext_store_ignore      # 0x03 IWRAM, should have been hit already | ||||
|   .long ext_store_ewram16     # 0x02 EWRAM | ||||
|   .long ext_store_iwram16     # 0x03 IWRAM | ||||
|   .long ext_store_io16        # 0x04 I/O registers | ||||
|   .long ext_store_palette16   # 0x05 Palette RAM | ||||
|   .long ext_store_vram16      # 0x06 VRAM | ||||
|  | @ -391,7 +383,9 @@ ext_store_u16_jtable: | |||
|   .long ext_store_eeprom      # 0x0D EEPROM (possibly) | ||||
|   .long ext_store_ignore      # 0x0E Flash ROM/SRAM must be 8bit | ||||
| 
 | ||||
| ext_store_u16: | ||||
| _execute_store_u16: | ||||
|   mov %ecx, REG_PC(%ebx)      # write out the PC | ||||
|   and $~0x01, %eax            # fix alignment | ||||
|   mov %eax, %ecx              # ecx = address | ||||
|   shr $24, %ecx               # ecx = address >> 24 | ||||
|   cmp $15, %ecx | ||||
|  | @ -400,26 +394,22 @@ ext_store_u16: | |||
|   mov ext_store_u16_jtable(, %ecx, 4), %ecx | ||||
|   jmp *%ecx                   # jump to table index | ||||
| 
 | ||||
| _execute_store_u32: | ||||
|   mov %ecx, REG_PC(%ebx)      # write out the PC | ||||
|   and $~0x03, %eax            # fix alignment | ||||
|   mov %eax, %ecx              # ecx = address | ||||
|   test $0xF0000000, %ecx      # check address range | ||||
|   jnz ext_store_u32           # if above perform an extended write | ||||
|   shr $15, %ecx               # ecx = page number of address | ||||
|   # load the corresponding memory map offset | ||||
|   mov _memory_map_write(, %ecx, 4), %ecx | ||||
|   test %ecx, %ecx             # see if it's NULL | ||||
|   jz ext_store_u32            # if so perform an extended write | ||||
|   and $0x7FFF, %eax           # isolate the lower 15bits of the address | ||||
|   mov %edx, (%eax, %ecx)      # store the value | ||||
|   # check for self-modifying code | ||||
|   testl $0xFFFFFFFF, -32768(%eax, %ecx) | ||||
|   jne smc_write | ||||
|   ret                         # return it | ||||
| 
 | ||||
| # 32bit ext memory routines | ||||
| 
 | ||||
| ext_store_iwram32: | ||||
|   and $0x7FFF, %eax                 # wrap around address | ||||
|   mov %edx, (_iwram+0x8000)(%eax)   # perform store | ||||
|   cmpl $0, _iwram(%eax)             # Check SMC mirror | ||||
|   jne smc_write | ||||
|   ret | ||||
| 
 | ||||
| ext_store_ewram32: | ||||
|   and $0x3FFFF, %eax                # wrap around address | ||||
|   mov %edx, _ewram(%eax)            # perform store | ||||
|   cmpl $0, (_ewram+0x40000)(%eax)   # Check SMC mirror | ||||
|   jne smc_write | ||||
|   ret | ||||
| 
 | ||||
| ext_store_io32: | ||||
|   and $0x3FF, %eax            # wrap around address | ||||
|   call _write_io_register32   # perform 32bit I/O register write | ||||
|  | @ -451,8 +441,8 @@ ext_store_oam32: | |||
| ext_store_u32_jtable: | ||||
|   .long ext_store_ignore      # 0x00 BIOS, ignore | ||||
|   .long ext_store_ignore      # 0x01 invalid, ignore | ||||
|   .long ext_store_ignore      # 0x02 EWRAM, should have been hit already | ||||
|   .long ext_store_ignore      # 0x03 IWRAM, should have been hit already | ||||
|   .long ext_store_ewram32     # 0x02 EWRAM | ||||
|   .long ext_store_iwram32     # 0x03 IWRAM | ||||
|   .long ext_store_io32        # 0x04 I/O registers | ||||
|   .long ext_store_palette32   # 0x05 Palette RAM | ||||
|   .long ext_store_vram32      # 0x06 VRAM | ||||
|  | @ -466,7 +456,9 @@ ext_store_u32_jtable: | |||
|   .long ext_store_ignore      # 0x0E Flash ROM/SRAM must be 8bit | ||||
| 
 | ||||
| 
 | ||||
| ext_store_u32: | ||||
| _execute_store_u32: | ||||
|   mov %ecx, REG_PC(%ebx)      # write out the PC | ||||
|   and $~0x03, %eax            # fix alignment | ||||
|   mov %eax, %ecx              # ecx = address | ||||
|   shr $24, %ecx               # ecx = address >> 24 | ||||
|   cmp $15, %ecx | ||||
|  | @ -507,8 +499,8 @@ smc_write: | |||
|   call _flush_translation_cache_ram | ||||
| 
 | ||||
| lookup_pc: | ||||
|   add $4, %esp | ||||
|   movl $0, CHANGED_PC_STATUS(%ebx) | ||||
|   add $4, %esp                       # Can't return, discard addr | ||||
|   movl $0, CHANGED_PC_STATUS(%ebx)   # Lookup new block and jump to it | ||||
|   mov REG_PC(%ebx), %eax | ||||
|   testl $0x20, REG_CPSR(%ebx) | ||||
|   jz lookup_pc_arm | ||||
|  | @ -577,7 +569,5 @@ _reg_mode: | |||
| 
 | ||||
| _memory_map_read: | ||||
|   .space 0x8000
 | ||||
| _memory_map_write: | ||||
|   .space 0x8000
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue