Update FSF address in GPL/LGPL boilerplate
[sdk/emulator/qemu.git] / target-cris / helper.c
1 /*
2  *  CRIS helper routines.
3  *
4  *  Copyright (c) 2007 AXIS Communications AB
5  *  Written by Edgar E. Iglesias.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "config.h"
26 #include "cpu.h"
27 #include "mmu.h"
28 #include "exec-all.h"
29 #include "host-utils.h"
30
31 #define D(x)
32
33 #if defined(CONFIG_USER_ONLY)
34
35 void do_interrupt (CPUState *env)
36 {
37         env->exception_index = -1;
38         env->pregs[PR_ERP] = env->pc;
39 }
40
41 int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
42                              int mmu_idx, int is_softmmu)
43 {
44         env->exception_index = 0xaa;
45         env->pregs[PR_EDA] = address;
46         cpu_dump_state(env, stderr, fprintf, 0);
47         return 1;
48 }
49
50 target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
51 {
52         return addr;
53 }
54
55 #else /* !CONFIG_USER_ONLY */
56
57
58 static void cris_shift_ccs(CPUState *env)
59 {
60         uint32_t ccs;
61         /* Apply the ccs shift.  */
62         ccs = env->pregs[PR_CCS];
63         ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
64         env->pregs[PR_CCS] = ccs;
65 }
66
67 int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
68                                int mmu_idx, int is_softmmu)
69 {
70         struct cris_mmu_result_t res;
71         int prot, miss;
72         int r = -1;
73         target_ulong phy;
74
75         D(printf ("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
76         address &= TARGET_PAGE_MASK;
77         miss = cris_mmu_translate(&res, env, address, rw, mmu_idx);
78         if (miss)
79         {
80                 if (env->exception_index == EXCP_BUSFAULT)
81                         cpu_abort(env, 
82                                   "CRIS: Illegal recursive bus fault."
83                                   "addr=%x rw=%d\n",
84                                   address, rw);
85
86                 env->exception_index = EXCP_BUSFAULT;
87                 env->fault_vector = res.bf_vec;
88                 r = 1;
89         }
90         else
91         {
92                 /*
93                  * Mask off the cache selection bit. The ETRAX busses do not
94                  * see the top bit.
95                  */
96                 phy = res.phy & ~0x80000000;
97                 prot = res.prot;
98                 r = tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu);
99         }
100         if (r > 0)
101                 D(fprintf(logfile, "%s returns %d irqreq=%x addr=%x"
102                           " phy=%x ismmu=%d vec=%x pc=%x\n", 
103                           __func__, r, env->interrupt_request, 
104                           address, res.phy, is_softmmu, res.bf_vec, env->pc));
105         return r;
106 }
107
108 void do_interrupt(CPUState *env)
109 {
110         int ex_vec = -1;
111
112         D(fprintf (logfile, "exception index=%d interrupt_req=%d\n",
113                    env->exception_index,
114                    env->interrupt_request));
115
116         switch (env->exception_index)
117         {
118                 case EXCP_BREAK:
119                         /* These exceptions are genereated by the core itself.
120                            ERP should point to the insn following the brk.  */
121                         ex_vec = env->trap_vector;
122                         env->pregs[PR_ERP] = env->pc;
123                         break;
124
125                 case EXCP_NMI:
126                         /* NMI is hardwired to vector zero.  */
127                         ex_vec = 0;
128                         env->pregs[PR_CCS] &= ~M_FLAG;
129                         env->pregs[PR_NRP] = env->pc;
130                         break;
131
132                 case EXCP_BUSFAULT:
133                         ex_vec = env->fault_vector;
134                         env->pregs[PR_ERP] = env->pc;
135                         break;
136
137                 default:
138                         /* The interrupt controller gives us the vector.  */
139                         ex_vec = env->interrupt_vector;
140                         /* Normal interrupts are taken between
141                            TB's.  env->pc is valid here.  */
142                         env->pregs[PR_ERP] = env->pc;
143                         break;
144         }
145
146         /* Fill in the IDX field.  */
147         env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
148
149         if (env->dslot) {
150                 D(fprintf(logfile, "excp isr=%x PC=%x ds=%d SP=%x"
151                           " ERP=%x pid=%x ccs=%x cc=%d %x\n",
152                           ex_vec, env->pc, env->dslot,
153                           env->regs[R_SP],
154                           env->pregs[PR_ERP], env->pregs[PR_PID],
155                           env->pregs[PR_CCS],
156                           env->cc_op, env->cc_mask));
157                 /* We loose the btarget, btaken state here so rexec the
158                    branch.  */
159                 env->pregs[PR_ERP] -= env->dslot;
160                 /* Exception starts with dslot cleared.  */
161                 env->dslot = 0;
162         }
163         
164         env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
165
166         if (env->pregs[PR_CCS] & U_FLAG) {
167                 /* Swap stack pointers.  */
168                 env->pregs[PR_USP] = env->regs[R_SP];
169                 env->regs[R_SP] = env->ksp;
170         }
171
172         /* Apply the CRIS CCS shift. Clears U if set.  */
173         cris_shift_ccs(env);
174         D(fprintf (logfile, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
175                    __func__, env->pc, ex_vec, 
176                    env->pregs[PR_CCS],
177                    env->pregs[PR_PID], 
178                    env->pregs[PR_ERP]));
179 }
180
181 target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
182 {
183         uint32_t phy = addr;
184         struct cris_mmu_result_t res;
185         int miss;
186         miss = cris_mmu_translate(&res, env, addr, 0, 0);
187         if (!miss)
188                 phy = res.phy;
189         D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
190         return phy;
191 }
192 #endif