75 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			75 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
#include "cpu.h"
 | 
						|
#include "dyngen-exec.h"
 | 
						|
#include "helper.h"
 | 
						|
 | 
						|
#if !defined(CONFIG_USER_ONLY)
 | 
						|
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
 | 
						|
                                void *retaddr);
 | 
						|
 | 
						|
#define MMUSUFFIX _mmu
 | 
						|
#define ALIGNED_ONLY
 | 
						|
 | 
						|
#define SHIFT 0
 | 
						|
#include "softmmu_template.h"
 | 
						|
 | 
						|
#define SHIFT 1
 | 
						|
#include "softmmu_template.h"
 | 
						|
 | 
						|
#define SHIFT 2
 | 
						|
#include "softmmu_template.h"
 | 
						|
 | 
						|
#define SHIFT 3
 | 
						|
#include "softmmu_template.h"
 | 
						|
 | 
						|
/* XXX: make it generic ? */
 | 
						|
static void cpu_restore_state2(void *retaddr)
 | 
						|
{
 | 
						|
    TranslationBlock *tb;
 | 
						|
    unsigned long pc;
 | 
						|
 | 
						|
    if (retaddr) {
 | 
						|
        /* now we have a real cpu fault */
 | 
						|
        pc = (unsigned long)retaddr;
 | 
						|
        tb = tb_find_pc(pc);
 | 
						|
        if (tb) {
 | 
						|
            /* the PC is inside the translated code. It means that we have
 | 
						|
               a virtual CPU fault */
 | 
						|
            cpu_restore_state(tb, env, pc);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
 | 
						|
                                void *retaddr)
 | 
						|
{
 | 
						|
#ifdef DEBUG_UNALIGNED
 | 
						|
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
 | 
						|
           "\n", addr, env->pc);
 | 
						|
#endif
 | 
						|
    cpu_restore_state2(retaddr);
 | 
						|
    helper_raise_exception(env, TT_UNALIGNED);
 | 
						|
}
 | 
						|
 | 
						|
/* try to fill the TLB and return an exception if error. If retaddr is
 | 
						|
   NULL, it means that the function was called in C code (i.e. not
 | 
						|
   from generated code or from helper.c) */
 | 
						|
/* XXX: fix it to restore all registers */
 | 
						|
void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
 | 
						|
              void *retaddr)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    CPUState *saved_env;
 | 
						|
 | 
						|
    saved_env = env;
 | 
						|
    env = env1;
 | 
						|
 | 
						|
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
 | 
						|
    if (ret) {
 | 
						|
        cpu_restore_state2(retaddr);
 | 
						|
        cpu_loop_exit(env);
 | 
						|
    }
 | 
						|
    env = saved_env;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* !CONFIG_USER_ONLY */
 |