Statistics
| Branch: | Revision:

root / target-m68k / op_helper.c @ 0633879f

History | View | Annotate | Download (3.5 kB)

1
/*
2
 *  M68K helper routines
3
 * 
4
 *  Copyright (c) 2007 CodeSourcery
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include "exec.h"
21

    
22
#if defined(CONFIG_USER_ONLY)
23

    
24
void do_interrupt(int is_hw)
25
{
26
    env->exception_index = -1;
27
}
28

    
29
#else
30

    
31
#define MMUSUFFIX _mmu
32
#define GETPC() (__builtin_return_address(0))
33

    
34
#define SHIFT 0
35
#include "softmmu_template.h"
36

    
37
#define SHIFT 1
38
#include "softmmu_template.h"
39

    
40
#define SHIFT 2
41
#include "softmmu_template.h"
42

    
43
#define SHIFT 3
44
#include "softmmu_template.h"
45

    
46
/* Try to fill the TLB and return an exception if error. If retaddr is
47
   NULL, it means that the function was called in C code (i.e. not
48
   from generated code or from helper.c) */
49
/* XXX: fix it to restore all registers */
50
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
51
{
52
    TranslationBlock *tb;
53
    CPUState *saved_env;
54
    target_phys_addr_t pc;
55
    int ret;
56

    
57
    /* XXX: hack to restore env in all cases, even if not called from
58
       generated code */
59
    saved_env = env;
60
    env = cpu_single_env;
61
    ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, is_user, 1);
62
    if (__builtin_expect(ret, 0)) {
63
        if (retaddr) {
64
            /* now we have a real cpu fault */
65
            pc = (target_phys_addr_t)retaddr;
66
            tb = tb_find_pc(pc);
67
            if (tb) {
68
                /* the PC is inside the translated code. It means that we have
69
                   a virtual CPU fault */
70
                cpu_restore_state(tb, env, pc, NULL);
71
            }
72
        }
73
        cpu_loop_exit();
74
    }
75
    env = saved_env;
76
}
77

    
78
static void do_rte(void)
79
{
80
    uint32_t sp;
81
    uint32_t fmt;
82

    
83
    sp = env->aregs[7];
84
    fmt = ldl_kernel(sp);
85
    env->pc = ldl_kernel(sp + 4);
86
    sp |= (fmt >> 28) & 3;
87
    env->sr = fmt & 0xffff;
88
    env->aregs[7] = sp + 8;
89
}
90

    
91
void do_interrupt(int is_hw)
92
{
93
    uint32_t sp;
94
    uint32_t fmt;
95
    uint32_t retaddr;
96
    uint32_t vector;
97

    
98
    fmt = 0;
99
    retaddr = env->pc;
100

    
101
    if (!is_hw) {
102
        switch (env->exception_index) {
103
        case EXCP_RTE:
104
            /* Return from an exception.  */
105
            do_rte();
106
            return;
107
        }
108
        if (env->exception_index >= EXCP_TRAP0
109
            && env->exception_index <= EXCP_TRAP15) {
110
            /* Move the PC after the trap instruction.  */
111
            retaddr += 2;
112
        }
113
    }
114

    
115
    /* TODO: Implement USP.  */
116
    sp = env->aregs[7];
117

    
118
    vector = env->exception_index << 2;
119

    
120
    fmt |= 0x40000000;
121
    fmt |= (sp & 3) << 28;
122
    fmt |= vector << 16;
123
    fmt |= env->sr;
124

    
125
    /* ??? This could cause MMU faults.  */
126
    sp &= ~3;
127
    sp -= 4;
128
    stl_kernel(sp, retaddr);
129
    sp -= 4;
130
    stl_kernel(sp, fmt);
131
    env->aregs[7] = sp;
132
    env->sr |= SR_S;
133
    if (is_hw) {
134
        env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
135
    }
136
    /* Jump to vector.  */
137
    env->pc = ldl_kernel(env->vbr + vector);
138
}
139

    
140
#endif