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