28 |
/* Memory access with special access mask */ |
/* Memory access with special access mask */ |
29 |
void ppc32_access_special(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid, |
void ppc32_access_special(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid, |
30 |
m_uint32_t mask,u_int op_code,u_int op_type, |
m_uint32_t mask,u_int op_code,u_int op_type, |
31 |
u_int op_size,m_uint64_t *data,u_int *exc) |
u_int op_size,m_uint64_t *data) |
32 |
{ |
{ |
33 |
switch(mask) { |
switch(mask) { |
34 |
case MTS_ACC_T: |
case MTS_ACC_T: |
44 |
memlog_dump(cpu->gen); |
memlog_dump(cpu->gen); |
45 |
#endif |
#endif |
46 |
#endif |
#endif |
|
|
|
47 |
if (cid == PPC32_MTS_DCACHE) { |
if (cid == PPC32_MTS_DCACHE) { |
48 |
cpu->dsisr = PPC32_DSISR_NOTRANS; |
cpu->dsisr = PPC32_DSISR_NOTRANS; |
49 |
|
|
52 |
|
|
53 |
cpu->dar = vaddr; |
cpu->dar = vaddr; |
54 |
ppc32_trigger_exception(cpu,PPC32_EXC_DSI); |
ppc32_trigger_exception(cpu,PPC32_EXC_DSI); |
55 |
|
cpu_exec_loop_enter(cpu->gen); |
56 |
} |
} |
57 |
} |
} |
|
|
|
|
*exc = 1; |
|
58 |
break; |
break; |
59 |
|
|
60 |
case MTS_ACC_U: |
case MTS_ACC_U: |
61 |
|
if (op_type == MTS_READ) |
62 |
|
*data = 0; |
63 |
|
|
64 |
|
if (cpu->gen->undef_mem_handler != NULL) { |
65 |
|
if (cpu->gen->undef_mem_handler(cpu->gen,(m_uint64_t)vaddr, |
66 |
|
op_size,op_type,data)) |
67 |
|
return; |
68 |
|
} |
69 |
|
|
70 |
#if DEBUG_MTS_ACC_U |
#if DEBUG_MTS_ACC_U |
71 |
if (op_type == MTS_READ) |
if (op_type == MTS_READ) |
72 |
cpu_log(cpu->gen, |
cpu_log(cpu->gen, |
78 |
"ia=0x%8.8x, value=0x%8.8llx (size=%u)\n", |
"ia=0x%8.8x, value=0x%8.8llx (size=%u)\n", |
79 |
vaddr,cpu->ia,*data,op_size); |
vaddr,cpu->ia,*data,op_size); |
80 |
#endif |
#endif |
|
if (op_type == MTS_READ) |
|
|
*data = 0; |
|
81 |
break; |
break; |
82 |
} |
} |
83 |
} |
} |
185 |
ppc32_mem_map(cpu_ppc_t *cpu,u_int op_type,mts_map_t *map, |
ppc32_mem_map(cpu_ppc_t *cpu,u_int op_type,mts_map_t *map, |
186 |
mts32_entry_t *entry,mts32_entry_t *alt_entry) |
mts32_entry_t *entry,mts32_entry_t *alt_entry) |
187 |
{ |
{ |
188 |
|
ppc32_jit_tcb_t *block; |
189 |
struct vdevice *dev; |
struct vdevice *dev; |
190 |
m_uint32_t offset; |
m_uint32_t offset; |
191 |
m_iptr_t host_ptr; |
m_iptr_t host_ptr; |
192 |
|
m_uint32_t exec_flag = 0; |
193 |
int cow; |
int cow; |
194 |
|
|
195 |
if (!(dev = dev_lookup(cpu->vm,map->paddr,map->cached))) |
if (!(dev = dev_lookup(cpu->vm,map->paddr+map->offset,map->cached))) |
196 |
return NULL; |
return NULL; |
197 |
|
|
198 |
|
if (cpu->exec_phys_map) { |
199 |
|
block = ppc32_jit_find_by_phys_page(cpu,map->paddr >> VM_PAGE_SHIFT); |
200 |
|
|
201 |
|
if (block) |
202 |
|
exec_flag = MTS_FLAG_EXEC; |
203 |
|
} |
204 |
|
|
205 |
if (dev->flags & VDEVICE_FLAG_SPARSE) { |
if (dev->flags & VDEVICE_FLAG_SPARSE) { |
206 |
host_ptr = dev_sparse_get_host_addr(cpu->vm,dev,map->paddr,op_type,&cow); |
host_ptr = dev_sparse_get_host_addr(cpu->vm,dev,map->paddr,op_type,&cow); |
207 |
|
|
209 |
entry->gppa = map->paddr; |
entry->gppa = map->paddr; |
210 |
entry->hpa = host_ptr; |
entry->hpa = host_ptr; |
211 |
entry->flags = (cow) ? MTS_FLAG_COW : 0; |
entry->flags = (cow) ? MTS_FLAG_COW : 0; |
212 |
|
entry->flags |= exec_flag; |
213 |
return entry; |
return entry; |
214 |
} |
} |
215 |
|
|
216 |
if (!dev->host_addr || (dev->flags & VDEVICE_FLAG_NO_MTS_MMAP)) { |
if (!dev->host_addr || (dev->flags & VDEVICE_FLAG_NO_MTS_MMAP)) { |
217 |
offset = map->paddr - dev->phys_addr; |
offset = (map->paddr + map->offset) - dev->phys_addr; |
218 |
|
|
219 |
alt_entry->gvpa = map->vaddr; |
/* device entries are never stored in virtual TLB */ |
|
alt_entry->gppa = map->paddr; |
|
220 |
alt_entry->hpa = (dev->id << MTS_DEVID_SHIFT) + offset; |
alt_entry->hpa = (dev->id << MTS_DEVID_SHIFT) + offset; |
221 |
alt_entry->flags = MTS_FLAG_DEV; |
alt_entry->flags = MTS_FLAG_DEV; |
222 |
return alt_entry; |
return alt_entry; |
225 |
entry->gvpa = map->vaddr; |
entry->gvpa = map->vaddr; |
226 |
entry->gppa = map->paddr; |
entry->gppa = map->paddr; |
227 |
entry->hpa = dev->host_addr + (map->paddr - dev->phys_addr); |
entry->hpa = dev->host_addr + (map->paddr - dev->phys_addr); |
228 |
entry->flags = 0; |
entry->flags = exec_flag; |
229 |
return entry; |
return entry; |
230 |
} |
} |
231 |
|
|
255 |
map->vaddr = vaddr & PPC32_MIN_PAGE_MASK; |
map->vaddr = vaddr & PPC32_MIN_PAGE_MASK; |
256 |
map->paddr = cpu->bat[cid][i].reg[1] & PPC32_LBAT_BRPN_MASK; |
map->paddr = cpu->bat[cid][i].reg[1] & PPC32_LBAT_BRPN_MASK; |
257 |
map->paddr += map->vaddr - bepi; |
map->paddr += map->vaddr - bepi; |
258 |
|
map->offset = vaddr & PPC32_MIN_PAGE_IMASK; |
259 |
map->cached = FALSE; |
map->cached = FALSE; |
260 |
return(TRUE); |
return(TRUE); |
261 |
} |
} |
268 |
static mts32_entry_t *ppc32_slow_lookup(cpu_ppc_t *cpu,m_uint32_t vaddr, |
static mts32_entry_t *ppc32_slow_lookup(cpu_ppc_t *cpu,m_uint32_t vaddr, |
269 |
u_int cid,u_int op_code,u_int op_size, |
u_int cid,u_int op_code,u_int op_size, |
270 |
u_int op_type,m_uint64_t *data, |
u_int op_type,m_uint64_t *data, |
271 |
u_int *exc,mts32_entry_t *alt_entry) |
mts32_entry_t *alt_entry) |
272 |
{ |
{ |
273 |
m_uint32_t hash_bucket,segment,vsid; |
m_uint32_t hash_bucket,segment,vsid; |
274 |
m_uint32_t hash,tmp,pteg_offset,pte_key,key,pte2; |
m_uint32_t hash,tmp,pteg_offset,pte_key,key,pte2; |
291 |
{ |
{ |
292 |
map.vaddr = vaddr & PPC32_MIN_PAGE_MASK; |
map.vaddr = vaddr & PPC32_MIN_PAGE_MASK; |
293 |
map.paddr = vaddr & PPC32_MIN_PAGE_MASK; |
map.paddr = vaddr & PPC32_MIN_PAGE_MASK; |
294 |
|
map.offset = vaddr & PPC32_MIN_PAGE_IMASK; |
295 |
map.cached = FALSE; |
map.cached = FALSE; |
296 |
|
|
297 |
if (!(entry = ppc32_mem_map(cpu,op_type,&map,entry,alt_entry))) |
if (!(entry = ppc32_mem_map(cpu,op_type,&map,entry,alt_entry))) |
355 |
|
|
356 |
no_pte: |
no_pte: |
357 |
/* No matching PTE for this virtual address */ |
/* No matching PTE for this virtual address */ |
358 |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_T,op_code,op_type,op_size, |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_T,op_code,op_type,op_size,data); |
|
data,exc); |
|
359 |
return NULL; |
return NULL; |
360 |
|
|
361 |
pte_lookup_done: |
pte_lookup_done: |
366 |
|
|
367 |
map.vaddr = vaddr & ~PPC32_MIN_PAGE_IMASK; |
map.vaddr = vaddr & ~PPC32_MIN_PAGE_IMASK; |
368 |
map.paddr = paddr; |
map.paddr = paddr; |
369 |
|
map.offset = vaddr & PPC32_MIN_PAGE_IMASK; |
370 |
map.cached = FALSE; |
map.cached = FALSE; |
371 |
|
|
372 |
if ((entry = ppc32_mem_map(cpu,op_type,&map,entry,alt_entry))) |
if ((entry = ppc32_mem_map(cpu,op_type,&map,entry,alt_entry))) |
373 |
return entry; |
return entry; |
374 |
|
|
375 |
err_undef: |
err_undef: |
376 |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_U,op_code,op_type,op_size, |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_U,op_code,op_type,op_size,data); |
|
data,exc); |
|
377 |
return NULL; |
return NULL; |
378 |
} |
} |
379 |
|
|
380 |
/* Memory access */ |
/* Memory access */ |
381 |
static inline void *ppc32_mem_access(cpu_ppc_t *cpu,m_uint32_t vaddr, |
static inline void *ppc32_mem_access(cpu_ppc_t *cpu,m_uint32_t vaddr, |
382 |
u_int cid,u_int op_code,u_int op_size, |
u_int cid,u_int op_code,u_int op_size, |
383 |
u_int op_type,m_uint64_t *data, |
u_int op_type,m_uint64_t *data) |
|
u_int *exc) |
|
384 |
{ |
{ |
385 |
mts32_entry_t *entry,alt_entry; |
mts32_entry_t *entry,alt_entry; |
386 |
|
ppc32_jit_tcb_t *block; |
387 |
m_uint32_t hash_bucket; |
m_uint32_t hash_bucket; |
388 |
|
m_uint32_t phys_page; |
389 |
|
m_uint32_t ia_hash; |
390 |
m_iptr_t haddr; |
m_iptr_t haddr; |
391 |
u_int dev_id; |
u_int dev_id; |
392 |
int cow; |
int cow; |
396 |
memlog_rec_access(cpu->gen,vaddr,*data,op_size,op_type); |
memlog_rec_access(cpu->gen,vaddr,*data,op_size,op_type); |
397 |
#endif |
#endif |
398 |
|
|
|
*exc = 0; |
|
399 |
hash_bucket = MTS32_HASH(vaddr); |
hash_bucket = MTS32_HASH(vaddr); |
400 |
entry = &cpu->mts_cache[cid][hash_bucket]; |
entry = &cpu->mts_cache[cid][hash_bucket]; |
401 |
|
|
409 |
/* Slow lookup if nothing found in cache */ |
/* Slow lookup if nothing found in cache */ |
410 |
if (unlikely(((vaddr & PPC32_MIN_PAGE_MASK) != entry->gvpa) || cow)) { |
if (unlikely(((vaddr & PPC32_MIN_PAGE_MASK) != entry->gvpa) || cow)) { |
411 |
entry = cpu->mts_slow_lookup(cpu,vaddr,cid,op_code,op_size,op_type, |
entry = cpu->mts_slow_lookup(cpu,vaddr,cid,op_code,op_size,op_type, |
412 |
data,exc,&alt_entry); |
data,&alt_entry); |
413 |
if (!entry) |
if (!entry) |
414 |
return NULL; |
return NULL; |
415 |
|
|
416 |
if (entry->flags & MTS_FLAG_DEV) { |
if (entry->flags & MTS_FLAG_DEV) { |
417 |
dev_id = (entry->hpa & MTS_DEVID_MASK) >> MTS_DEVID_SHIFT; |
dev_id = (entry->hpa & MTS_DEVID_MASK) >> MTS_DEVID_SHIFT; |
418 |
haddr = entry->hpa & MTS_DEVOFF_MASK; |
haddr = entry->hpa & MTS_DEVOFF_MASK; |
|
haddr += vaddr - entry->gvpa; |
|
419 |
return(dev_access_fast(cpu->gen,dev_id,haddr,op_size,op_type,data)); |
return(dev_access_fast(cpu->gen,dev_id,haddr,op_size,op_type,data)); |
420 |
} |
} |
421 |
} |
} |
422 |
|
|
423 |
|
/* Invalidate JIT code for written pages */ |
424 |
|
if ((op_type == MTS_WRITE) && (entry->flags & MTS_FLAG_EXEC)) { |
425 |
|
if (cpu->exec_phys_map) { |
426 |
|
phys_page = entry->gppa >> VM_PAGE_SHIFT; |
427 |
|
|
428 |
|
if (vaddr >= PPC32_EXC_SYS_RST) { |
429 |
|
block = ppc32_jit_find_by_phys_page(cpu,phys_page); |
430 |
|
|
431 |
|
if (block != NULL) { |
432 |
|
//printf("Invalidation of block 0x%8.8x\n",block->start_ia); |
433 |
|
ia_hash = ppc32_jit_get_ia_hash(block->start_ia); |
434 |
|
ppc32_jit_tcb_free(cpu,block,TRUE); |
435 |
|
|
436 |
|
if (cpu->exec_blk_map[ia_hash] == block) |
437 |
|
cpu->exec_blk_map[ia_hash] = NULL; |
438 |
|
|
439 |
|
entry->flags &= ~MTS_FLAG_EXEC; |
440 |
|
} |
441 |
|
} |
442 |
|
} |
443 |
|
} |
444 |
|
|
445 |
/* Raw memory access */ |
/* Raw memory access */ |
446 |
haddr = entry->hpa + (vaddr & PPC32_MIN_PAGE_IMASK); |
haddr = entry->hpa + (vaddr & PPC32_MIN_PAGE_IMASK); |
447 |
#if MEMLOG_ENABLE |
#if MEMLOG_ENABLE |
451 |
} |
} |
452 |
|
|
453 |
/* Memory data access */ |
/* Memory data access */ |
454 |
#define PPC32_MEM_DACCESS(cpu,vaddr,op_code,op_size,op_type,data,exc) \ |
#define PPC32_MEM_DACCESS(cpu,vaddr,op_code,op_size,op_type,data) \ |
455 |
ppc32_mem_access((cpu),(vaddr),PPC32_MTS_DCACHE,(op_code),(op_size),\ |
ppc32_mem_access((cpu),(vaddr),PPC32_MTS_DCACHE,(op_code),(op_size),\ |
456 |
(op_type),(data),(exc)) |
(op_type),(data)) |
457 |
|
|
458 |
/* Virtual address to physical page translation */ |
/* Virtual address to physical page translation */ |
459 |
static fastcall int ppc32_translate(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid, |
static fastcall int ppc32_translate(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid, |
462 |
mts32_entry_t *entry,alt_entry; |
mts32_entry_t *entry,alt_entry; |
463 |
m_uint32_t hash_bucket; |
m_uint32_t hash_bucket; |
464 |
m_uint64_t data = 0; |
m_uint64_t data = 0; |
|
u_int exc = 0; |
|
465 |
|
|
466 |
hash_bucket = MTS32_HASH(vaddr); |
hash_bucket = MTS32_HASH(vaddr); |
467 |
entry = &cpu->mts_cache[cid][hash_bucket]; |
entry = &cpu->mts_cache[cid][hash_bucket]; |
469 |
/* Slow lookup if nothing found in cache */ |
/* Slow lookup if nothing found in cache */ |
470 |
if (unlikely(((m_uint32_t)vaddr & PPC32_MIN_PAGE_MASK) != entry->gvpa)) { |
if (unlikely(((m_uint32_t)vaddr & PPC32_MIN_PAGE_MASK) != entry->gvpa)) { |
471 |
entry = cpu->mts_slow_lookup(cpu,vaddr,cid,PPC_MEMOP_LOOKUP,4,MTS_READ, |
entry = cpu->mts_slow_lookup(cpu,vaddr,cid,PPC_MEMOP_LOOKUP,4,MTS_READ, |
472 |
&data,&exc,&alt_entry); |
&data,&alt_entry); |
473 |
if (!entry) |
if (!entry) |
474 |
return(-1); |
return(-1); |
475 |
} |
} |
482 |
static void *ppc32_mem_lookup(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid) |
static void *ppc32_mem_lookup(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid) |
483 |
{ |
{ |
484 |
m_uint64_t data; |
m_uint64_t data; |
485 |
u_int exc; |
return(ppc32_mem_access(cpu,vaddr,cid,PPC_MEMOP_LOOKUP,4,MTS_READ,&data)); |
|
return(ppc32_mem_access(cpu,vaddr,cid,PPC_MEMOP_LOOKUP,4,MTS_READ, |
|
|
&data,&exc)); |
|
486 |
} |
} |
487 |
|
|
488 |
/* Set a BAT register */ |
/* Set a BAT register */ |
631 |
static mts32_entry_t *ppc405_slow_lookup(cpu_ppc_t *cpu,m_uint32_t vaddr, |
static mts32_entry_t *ppc405_slow_lookup(cpu_ppc_t *cpu,m_uint32_t vaddr, |
632 |
u_int cid,u_int op_code,u_int op_size, |
u_int cid,u_int op_code,u_int op_size, |
633 |
u_int op_type,m_uint64_t *data, |
u_int op_type,m_uint64_t *data, |
634 |
u_int *exc,mts32_entry_t *alt_entry) |
mts32_entry_t *alt_entry) |
635 |
{ |
{ |
636 |
struct ppc405_tlb_entry *tlb_entry; |
struct ppc405_tlb_entry *tlb_entry; |
637 |
m_uint32_t hash_bucket,mask; |
m_uint32_t hash_bucket,mask; |
690 |
} |
} |
691 |
|
|
692 |
/* No matching TLB entry for this virtual address */ |
/* No matching TLB entry for this virtual address */ |
693 |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_T,op_code,op_type,op_size, |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_T,op_code,op_type,op_size,data); |
|
data,exc); |
|
694 |
return NULL; |
return NULL; |
695 |
|
|
696 |
err_undef: |
err_undef: |
697 |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_U,op_code,op_type,op_size, |
ppc32_access_special(cpu,vaddr,cid,MTS_ACC_U,op_code,op_type,op_size,data); |
|
data,exc); |
|
698 |
return NULL; |
return NULL; |
699 |
} |
} |
700 |
|
|
722 |
/* === PPC Memory Operations ============================================= */ |
/* === PPC Memory Operations ============================================= */ |
723 |
|
|
724 |
/* LBZ: Load Byte Zero */ |
/* LBZ: Load Byte Zero */ |
725 |
fastcall u_int ppc32_lbz(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lbz(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
726 |
{ |
{ |
727 |
m_uint64_t data; |
m_uint64_t data; |
728 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
729 |
|
|
730 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LBZ,1,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LBZ,1,MTS_READ,&data); |
731 |
if (likely(haddr != NULL)) data = *(m_uint8_t *)haddr; |
if (likely(haddr != NULL)) data = *(m_uint8_t *)haddr; |
732 |
if (likely(!exc)) cpu->gpr[reg] = data & 0xFF; |
cpu->gpr[reg] = data & 0xFF; |
|
return(exc); |
|
733 |
} |
} |
734 |
|
|
735 |
/* LHZ: Load Half-Word Zero */ |
/* LHZ: Load Half-Word Zero */ |
736 |
fastcall u_int ppc32_lhz(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lhz(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
737 |
{ |
{ |
738 |
m_uint64_t data; |
m_uint64_t data; |
739 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
740 |
|
|
741 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LHZ,2,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LHZ,2,MTS_READ,&data); |
742 |
if (likely(haddr != NULL)) data = vmtoh16(*(m_uint16_t *)haddr); |
if (likely(haddr != NULL)) data = vmtoh16(*(m_uint16_t *)haddr); |
743 |
if (likely(!exc)) cpu->gpr[reg] = data & 0xFFFF; |
cpu->gpr[reg] = data & 0xFFFF; |
|
return(exc); |
|
744 |
} |
} |
745 |
|
|
746 |
/* LWZ: Load Word Zero */ |
/* LWZ: Load Word Zero */ |
747 |
fastcall u_int ppc32_lwz(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lwz(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
748 |
{ |
{ |
749 |
m_uint64_t data; |
m_uint64_t data; |
750 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
751 |
|
|
752 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LWZ,4,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LWZ,4,MTS_READ,&data); |
753 |
if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr); |
if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr); |
754 |
if (likely(!exc)) cpu->gpr[reg] = data; |
cpu->gpr[reg] = data; |
|
return(exc); |
|
755 |
} |
} |
756 |
|
|
757 |
/* LWBR: Load Word Byte Reverse */ |
/* LWBR: Load Word Byte Reverse */ |
758 |
fastcall u_int ppc32_lwbr(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lwbr(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
759 |
{ |
{ |
760 |
m_uint64_t data; |
m_uint64_t data; |
761 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
762 |
|
|
763 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LWBR,4,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LWBR,4,MTS_READ,&data); |
764 |
if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr); |
if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr); |
765 |
if (likely(!exc)) cpu->gpr[reg] = swap32(data); |
cpu->gpr[reg] = swap32(data); |
|
return(exc); |
|
766 |
} |
} |
767 |
|
|
768 |
/* LHA: Load Half-Word Algebraic */ |
/* LHA: Load Half-Word Algebraic */ |
769 |
fastcall u_int ppc32_lha(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lha(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
770 |
{ |
{ |
771 |
m_uint64_t data; |
m_uint64_t data; |
772 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
773 |
|
|
774 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LHZ,2,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LHZ,2,MTS_READ,&data); |
775 |
if (likely(haddr != NULL)) data = vmtoh16(*(m_uint16_t *)haddr); |
if (likely(haddr != NULL)) data = vmtoh16(*(m_uint16_t *)haddr); |
776 |
if (likely(!exc)) cpu->gpr[reg] = sign_extend_32(data,16); |
cpu->gpr[reg] = sign_extend_32(data,16); |
|
return(exc); |
|
777 |
} |
} |
778 |
|
|
779 |
/* STB: Store Byte */ |
/* STB: Store Byte */ |
780 |
fastcall u_int ppc32_stb(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_stb(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
781 |
{ |
{ |
782 |
m_uint64_t data; |
m_uint64_t data; |
783 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
784 |
|
|
785 |
data = cpu->gpr[reg] & 0xff; |
data = cpu->gpr[reg] & 0xff; |
786 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STB,1,MTS_WRITE,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STB,1,MTS_WRITE,&data); |
787 |
if (likely(haddr != NULL)) *(m_uint8_t *)haddr = data; |
if (likely(haddr != NULL)) *(m_uint8_t *)haddr = data; |
|
return(exc); |
|
788 |
} |
} |
789 |
|
|
790 |
/* STH: Store Half-Word */ |
/* STH: Store Half-Word */ |
791 |
fastcall u_int ppc32_sth(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_sth(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
792 |
{ |
{ |
793 |
m_uint64_t data; |
m_uint64_t data; |
794 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
795 |
|
|
796 |
data = cpu->gpr[reg] & 0xffff; |
data = cpu->gpr[reg] & 0xffff; |
797 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STH,2,MTS_WRITE,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STH,2,MTS_WRITE,&data); |
798 |
if (likely(haddr != NULL)) *(m_uint16_t *)haddr = htovm16(data); |
if (likely(haddr != NULL)) *(m_uint16_t *)haddr = htovm16(data); |
|
return(exc); |
|
799 |
} |
} |
800 |
|
|
801 |
/* STW: Store Word */ |
/* STW: Store Word */ |
802 |
fastcall u_int ppc32_stw(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_stw(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
803 |
{ |
{ |
804 |
m_uint64_t data; |
m_uint64_t data; |
805 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
806 |
|
|
807 |
data = cpu->gpr[reg]; |
data = cpu->gpr[reg]; |
808 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STW,4,MTS_WRITE,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STW,4,MTS_WRITE,&data); |
809 |
if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data); |
if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data); |
|
return(exc); |
|
810 |
} |
} |
811 |
|
|
812 |
/* STWBR: Store Word Byte Reversed */ |
/* STWBR: Store Word Byte Reversed */ |
813 |
fastcall u_int ppc32_stwbr(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_stwbr(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
814 |
{ |
{ |
815 |
m_uint64_t data; |
m_uint64_t data; |
816 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
817 |
|
|
818 |
data = swap32(cpu->gpr[reg]); |
data = swap32(cpu->gpr[reg]); |
819 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STWBR,4,MTS_WRITE,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STWBR,4,MTS_WRITE,&data); |
820 |
if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data); |
if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data); |
|
return(exc); |
|
821 |
} |
} |
822 |
|
|
823 |
/* LSW: Load String Word */ |
/* LSW: Load String Word */ |
824 |
fastcall u_int ppc32_lsw(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lsw(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
825 |
{ |
{ |
826 |
m_uint64_t data; |
m_uint64_t data; |
827 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
828 |
|
|
829 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LSW,1,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LSW,1,MTS_READ,&data); |
830 |
if (likely(haddr != NULL)) data = *(m_uint8_t *)haddr; |
if (likely(haddr != NULL)) data = *(m_uint8_t *)haddr; |
831 |
if (likely(!exc)) cpu->gpr[reg] |= (data & 0xFF) << (24 - cpu->sw_pos); |
cpu->gpr[reg] |= (data & 0xFF) << (24 - cpu->sw_pos); |
|
return(exc); |
|
832 |
} |
} |
833 |
|
|
834 |
/* STW: Store String Word */ |
/* STW: Store String Word */ |
835 |
fastcall u_int ppc32_stsw(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_stsw(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
836 |
{ |
{ |
837 |
m_uint64_t data; |
m_uint64_t data; |
838 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
839 |
|
|
840 |
data = (cpu->gpr[reg] >> (24 - cpu->sw_pos)) & 0xFF; |
data = (cpu->gpr[reg] >> (24 - cpu->sw_pos)) & 0xFF; |
841 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STSW,1,MTS_WRITE,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STSW,1,MTS_WRITE,&data); |
842 |
if (likely(haddr != NULL)) *(m_uint8_t *)haddr = data; |
if (likely(haddr != NULL)) *(m_uint8_t *)haddr = data; |
|
return(exc); |
|
843 |
} |
} |
844 |
|
|
845 |
/* LFD: Load Floating-Point Double */ |
/* LFD: Load Floating-Point Double */ |
846 |
fastcall u_int ppc32_lfd(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_lfd(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
847 |
{ |
{ |
848 |
m_uint64_t data; |
m_uint64_t data; |
849 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
850 |
|
|
851 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LWZ,8,MTS_READ,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_LWZ,8,MTS_READ,&data); |
852 |
if (likely(haddr != NULL)) data = vmtoh64(*(m_uint64_t *)haddr); |
if (likely(haddr != NULL)) data = vmtoh64(*(m_uint64_t *)haddr); |
853 |
if (likely(!exc)) cpu->fpu.reg[reg] = data; |
cpu->fpu.reg[reg] = data; |
|
return(exc); |
|
854 |
} |
} |
855 |
|
|
856 |
/* STFD: Store Floating-Point Double */ |
/* STFD: Store Floating-Point Double */ |
857 |
fastcall u_int ppc32_stfd(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
fastcall void ppc32_stfd(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int reg) |
858 |
{ |
{ |
859 |
m_uint64_t data; |
m_uint64_t data; |
860 |
void *haddr; |
void *haddr; |
|
u_int exc; |
|
861 |
|
|
862 |
data = cpu->fpu.reg[reg]; |
data = cpu->fpu.reg[reg]; |
863 |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STW,8,MTS_WRITE,&data,&exc); |
haddr = PPC32_MEM_DACCESS(cpu,vaddr,PPC_MEMOP_STW,8,MTS_WRITE,&data); |
864 |
if (likely(haddr != NULL)) *(m_uint64_t *)haddr = htovm64(data); |
if (likely(haddr != NULL)) *(m_uint64_t *)haddr = htovm64(data); |
|
return(exc); |
|
865 |
} |
} |
866 |
|
|
867 |
/* ICBI: Instruction Cache Block Invalidate */ |
/* ICBI: Instruction Cache Block Invalidate */ |
868 |
fastcall u_int ppc32_icbi(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int op) |
fastcall void ppc32_icbi(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int op) |
869 |
{ |
{ |
870 |
ppc32_jit_tcb_t *block; |
ppc32_jit_tcb_t *block; |
871 |
m_uint32_t phys_page; |
m_uint32_t phys_page; |
875 |
#endif |
#endif |
876 |
|
|
877 |
if (!cpu->translate(cpu,vaddr,PPC32_MTS_ICACHE,&phys_page)) { |
if (!cpu->translate(cpu,vaddr,PPC32_MTS_ICACHE,&phys_page)) { |
878 |
if ((phys_page < 1048576) && cpu->exec_phys_map) { |
if (cpu->exec_phys_map) { |
879 |
block = cpu->exec_phys_map[phys_page]; |
block = ppc32_jit_find_by_phys_page(cpu,phys_page); |
880 |
|
|
881 |
if (block) { |
if (block && (block->start_ia == (vaddr & PPC32_MIN_PAGE_MASK))) { |
|
if ((cpu->ia < block->start_ia) || |
|
|
((cpu->ia - block->start_ia) >= PPC32_MIN_PAGE_SIZE)) |
|
|
{ |
|
882 |
#if DEBUG_ICBI |
#if DEBUG_ICBI |
883 |
cpu_log(cpu->gen,"MTS", |
cpu_log(cpu->gen,"MTS", |
884 |
"ICBI: removing compiled page at 0x%8.8x, pc=0x%8.8x\n", |
"ICBI: removing compiled page at 0x%8.8x, pc=0x%8.8x\n", |
885 |
block->start_ia,cpu->ia); |
block->start_ia,cpu->ia); |
886 |
#endif |
#endif |
887 |
cpu->exec_phys_map[phys_page] = NULL; |
ppc32_jit_tcb_free(cpu,block,TRUE); |
888 |
ppc32_jit_tcb_free(cpu,block,TRUE); |
cpu->exec_blk_map[ppc32_jit_get_ia_hash(vaddr)] = NULL; |
889 |
} |
} |
890 |
else |
else |
891 |
{ |
{ |
892 |
#if DEBUG_ICBI |
#if DEBUG_ICBI |
893 |
cpu_log(cpu->gen,"MTS", |
cpu_log(cpu->gen,"MTS", |
894 |
"ICBI: trying to remove page 0x%llx with pc=0x%llx\n", |
"ICBI: trying to remove page 0x%llx with pc=0x%llx\n", |
895 |
block->start_ia,cpu->ia); |
block->start_ia,cpu->ia); |
896 |
#endif |
#endif |
|
} |
|
897 |
} |
} |
898 |
} |
} |
899 |
} |
} |
|
|
|
|
return(0); |
|
900 |
} |
} |
901 |
|
|
902 |
/* ======================================================================== */ |
/* ======================================================================== */ |