/*
* Software MMU support
*
+ * Generate helpers used by TCG for qemu_ld/st ops and code load
+ * functions.
+ *
+ * Included from target op helpers and exec.c.
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu-timer.h"
+#include "memory.h"
+
#define DATA_SIZE (1 << SHIFT)
#if DATA_SIZE == 8
{
DATA_TYPE res;
int index;
- index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+ index = physaddr & (IO_MEM_NB_ENTRIES - 1);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
env->mem_io_pc = (unsigned long)retaddr;
- if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
+ if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr
+ && index != io_mem_unassigned.ram_addr
+ && index != io_mem_notdirty.ram_addr
&& !can_do_io(env)) {
cpu_io_recompile(env, retaddr);
}
+ env->mem_io_vaddr = addr;
#if SHIFT <= 2
- res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
+ res = io_mem_read(index, physaddr, 1 << SHIFT);
#else
#ifdef TARGET_WORDS_BIGENDIAN
- res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr) << 32;
- res |= io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
+ res = io_mem_read(index, physaddr, 4) << 32;
+ res |= io_mem_read(index, physaddr + 4, 4);
#else
- res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
- res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index], physaddr + 4) << 32;
+ res = io_mem_read(index, physaddr, 4);
+ res |= io_mem_read(index, physaddr + 4, 4) << 32;
#endif
#endif /* SHIFT > 2 */
-#ifdef USE_KQEMU
- env->last_io_time = cpu_get_time_fast();
-#endif
return res;
}
DATA_TYPE res;
int index;
target_ulong tlb_addr;
- target_phys_addr_t addend;
+ target_phys_addr_t ioaddr;
+ unsigned long addend;
void *retaddr;
/* test if there is match for unaligned or IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
goto do_unaligned_access;
retaddr = GETPC();
- addend = env->iotlb[mmu_idx][index];
- res = glue(io_read, SUFFIX)(addend, addr, retaddr);
+ ioaddr = env->iotlb[mmu_idx][index];
+ res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
/* slow unaligned access (it spans two pages or IO) */
do_unaligned_access:
if ((addr & (DATA_SIZE - 1)) != 0)
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
#endif
- tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+ tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
goto redo;
}
return res;
{
DATA_TYPE res, res1, res2;
int index, shift;
- target_phys_addr_t addend;
+ target_phys_addr_t ioaddr;
+ unsigned long addend;
target_ulong tlb_addr, addr1, addr2;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
/* IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
goto do_unaligned_access;
- retaddr = GETPC();
- addend = env->iotlb[mmu_idx][index];
- res = glue(io_read, SUFFIX)(addend, addr, retaddr);
+ ioaddr = env->iotlb[mmu_idx][index];
+ res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
do_unaligned_access:
/* slow unaligned access (it spans two pages) */
}
} else {
/* the page is not in the TLB : fill it */
- tlb_fill(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+ tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
goto redo;
}
return res;
void *retaddr)
{
int index;
- index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+ index = physaddr & (IO_MEM_NB_ENTRIES - 1);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
- if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
+ if (index != io_mem_ram.ram_addr && index != io_mem_rom.ram_addr
+ && index != io_mem_unassigned.ram_addr
+ && index != io_mem_notdirty.ram_addr
&& !can_do_io(env)) {
cpu_io_recompile(env, retaddr);
}
env->mem_io_vaddr = addr;
env->mem_io_pc = (unsigned long)retaddr;
#if SHIFT <= 2
- io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val);
+ io_mem_write(index, physaddr, val, 1 << SHIFT);
#else
#ifdef TARGET_WORDS_BIGENDIAN
- io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32);
- io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val);
+ io_mem_write(index, physaddr, (val >> 32), 4);
+ io_mem_write(index, physaddr + 4, (uint32_t)val, 4);
#else
- io_mem_write[index][2](io_mem_opaque[index], physaddr, val);
- io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32);
+ io_mem_write(index, physaddr, (uint32_t)val, 4);
+ io_mem_write(index, physaddr + 4, val >> 32, 4);
#endif
#endif /* SHIFT > 2 */
-#ifdef USE_KQEMU
- env->last_io_time = cpu_get_time_fast();
-#endif
}
void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
DATA_TYPE val,
int mmu_idx)
{
- target_phys_addr_t addend;
+ target_phys_addr_t ioaddr;
+ unsigned long addend;
target_ulong tlb_addr;
void *retaddr;
int index;
if ((addr & (DATA_SIZE - 1)) != 0)
goto do_unaligned_access;
retaddr = GETPC();
- addend = env->iotlb[mmu_idx][index];
- glue(io_write, SUFFIX)(addend, val, addr, retaddr);
+ ioaddr = env->iotlb[mmu_idx][index];
+ glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
do_unaligned_access:
retaddr = GETPC();
if ((addr & (DATA_SIZE - 1)) != 0)
do_unaligned_access(addr, 1, mmu_idx, retaddr);
#endif
- tlb_fill(addr, 1, mmu_idx, retaddr);
+ tlb_fill(env, addr, 1, mmu_idx, retaddr);
goto redo;
}
}
int mmu_idx,
void *retaddr)
{
- target_phys_addr_t addend;
+ target_phys_addr_t ioaddr;
+ unsigned long addend;
target_ulong tlb_addr;
int index, i;
/* IO access */
if ((addr & (DATA_SIZE - 1)) != 0)
goto do_unaligned_access;
- addend = env->iotlb[mmu_idx][index];
- glue(io_write, SUFFIX)(addend, val, addr, retaddr);
+ ioaddr = env->iotlb[mmu_idx][index];
+ glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
do_unaligned_access:
/* XXX: not efficient, but simple */
}
} else {
/* the page is not in the TLB : fill it */
- tlb_fill(addr, 1, mmu_idx, retaddr);
+ tlb_fill(env, addr, 1, mmu_idx, retaddr);
goto redo;
}
}