]> Git Repo - qemu.git/blob - target-microblaze/op_helper.c
microblaze: Update debug logs.
[qemu.git] / target-microblaze / op_helper.c
1 /*
2  *  Microblaze helper routines.
3  *
4  *  Copyright (c) 2009 Edgar E. Iglesias <[email protected]>.
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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <assert.h>
21 #include "exec.h"
22 #include "helper.h"
23 #include "host-utils.h"
24
25 #define D(x)
26
27 #if !defined(CONFIG_USER_ONLY)
28 #define MMUSUFFIX _mmu
29 #define SHIFT 0
30 #include "softmmu_template.h"
31 #define SHIFT 1
32 #include "softmmu_template.h"
33 #define SHIFT 2
34 #include "softmmu_template.h"
35 #define SHIFT 3
36 #include "softmmu_template.h"
37
38 /* Try to fill the TLB and return an exception if error. If retaddr is
39    NULL, it means that the function was called in C code (i.e. not
40    from generated code or from helper.c) */
41 /* XXX: fix it to restore all registers */
42 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
43 {
44     TranslationBlock *tb;
45     CPUState *saved_env;
46     unsigned long pc;
47     int ret;
48
49     /* XXX: hack to restore env in all cases, even if not called from
50        generated code */
51     saved_env = env;
52     env = cpu_single_env;
53
54     ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
55     if (unlikely(ret)) {
56         if (retaddr) {
57             /* now we have a real cpu fault */
58             pc = (unsigned long)retaddr;
59             tb = tb_find_pc(pc);
60             if (tb) {
61                 /* the PC is inside the translated code. It means that we have
62                    a virtual CPU fault */
63                 cpu_restore_state(tb, env, pc, NULL);
64             }
65         }
66         cpu_loop_exit();
67     }
68     env = saved_env;
69 }
70 #endif
71
72 void helper_raise_exception(uint32_t index)
73 {
74     env->exception_index = index;
75     cpu_loop_exit();
76 }
77
78 void helper_debug(void)
79 {
80     int i;
81
82     qemu_log("PC=%8.8x\n", env->sregs[SR_PC]);
83     qemu_log("rmsr=%x resr=%x debug[%x] imm=%x iflags=%x\n",
84              env->sregs[SR_MSR], env->sregs[SR_ESR],
85              env->debug, env->imm, env->iflags);
86     qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
87              env->btaken, env->btarget,
88              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
89              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
90              (env->sregs[SR_MSR] & MSR_EIP),
91              (env->sregs[SR_MSR] & MSR_IE));
92     for (i = 0; i < 32; i++) {
93         qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
94         if ((i + 1) % 4 == 0)
95             qemu_log("\n");
96     }
97     qemu_log("\n\n");
98 }
99
100 static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
101 {
102     uint32_t cout = 0;
103
104     if ((b == ~0) && cin)
105         cout = 1;
106     else if ((~0 - a) < (b + cin))
107         cout = 1;
108     return cout;
109 }
110
111 uint32_t helper_cmp(uint32_t a, uint32_t b)
112 {
113     uint32_t t;
114
115     t = b + ~a + 1;
116     if ((b & 0x80000000) ^ (a & 0x80000000))
117         t = (t & 0x7fffffff) | (b & 0x80000000);
118     return t;
119 }
120
121 uint32_t helper_cmpu(uint32_t a, uint32_t b)
122 {
123     uint32_t t;
124
125     t = b + ~a + 1;
126     if ((b & 0x80000000) ^ (a & 0x80000000))
127         t = (t & 0x7fffffff) | (a & 0x80000000);
128     return t;
129 }
130
131 uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
132 {
133     uint32_t d, cf = 0, ncf;
134
135     if (c)
136         cf = env->sregs[SR_MSR] >> 31;
137     assert(cf == 0 || cf == 1);
138     d = a + b + cf;
139
140     if (!k) {
141         ncf = compute_carry(a, b, cf);
142         assert(ncf == 0 || ncf == 1);
143         if (ncf)
144             env->sregs[SR_MSR] |= MSR_C | MSR_CC;
145         else
146             env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
147     }
148     D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
149                d, a, b, cf, ncf, k, c));
150     return d;
151 }
152
153 uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
154 {
155     uint32_t d, cf = 1, ncf;
156
157     if (c)
158         cf = env->sregs[SR_MSR] >> 31; 
159     assert(cf == 0 || cf == 1);
160     d = b + ~a + cf;
161
162     if (!k) {
163         ncf = compute_carry(b, ~a, cf);
164         assert(ncf == 0 || ncf == 1);
165         if (ncf)
166             env->sregs[SR_MSR] |= MSR_C | MSR_CC;
167         else
168             env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
169     }
170     D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
171                d, a, b, cf, ncf, k, c));
172     return d;
173 }
174
175 static inline int div_prepare(uint32_t a, uint32_t b)
176 {
177     if (b == 0) {
178         env->sregs[SR_MSR] |= MSR_DZ;
179
180         if ((env->sregs[SR_MSR] & MSR_EE)
181             && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) {
182             env->sregs[SR_ESR] = ESR_EC_DIVZERO;
183             helper_raise_exception(EXCP_HW_EXCP);
184         }
185         return 0;
186     }
187     env->sregs[SR_MSR] &= ~MSR_DZ;
188     return 1;
189 }
190
191 uint32_t helper_divs(uint32_t a, uint32_t b)
192 {
193     if (!div_prepare(a, b))
194         return 0;
195     return (int32_t)a / (int32_t)b;
196 }
197
198 uint32_t helper_divu(uint32_t a, uint32_t b)
199 {
200     if (!div_prepare(a, b))
201         return 0;
202     return a / b;
203 }
204
205 uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
206 {
207     unsigned int i;
208     uint32_t mask = 0xff000000;
209
210     for (i = 0; i < 4; i++) {
211         if ((a & mask) == (b & mask))
212             return i + 1;
213         mask >>= 8;
214     }
215     return 0;
216 }
217
218 void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
219 {
220     if (addr & mask) {
221             qemu_log_mask(CPU_LOG_INT,
222                           "unaligned access addr=%x mask=%x, wr=%d dr=r%d\n",
223                           addr, mask, wr, dr);
224             env->sregs[SR_EAR] = addr;
225             env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
226                                  | (dr & 31) << 5;
227             if (mask == 3) {
228                 env->sregs[SR_ESR] |= 1 << 11;
229             }
230             if (!(env->sregs[SR_MSR] & MSR_EE)) {
231                 return;
232             }
233             helper_raise_exception(EXCP_HW_EXCP);
234     }
235 }
236
237 #if !defined(CONFIG_USER_ONLY)
238 /* Writes/reads to the MMU's special regs end up here.  */
239 uint32_t helper_mmu_read(uint32_t rn)
240 {
241     return mmu_read(env, rn);
242 }
243
244 void helper_mmu_write(uint32_t rn, uint32_t v)
245 {
246     mmu_write(env, rn, v);
247 }
248 #endif
249
250 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
251                           int is_asi, int size)
252 {
253     CPUState *saved_env;
254     /* XXX: hack to restore env in all cases, even if not called from
255        generated code */
256     saved_env = env;
257     env = cpu_single_env;
258     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
259              addr, is_write, is_exec);
260     if (!(env->sregs[SR_MSR] & MSR_EE)) {
261         env = saved_env;
262         return;
263     }
264
265     env->sregs[SR_EAR] = addr;
266     if (is_exec) {
267         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
268             env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
269             helper_raise_exception(EXCP_HW_EXCP);
270         }
271     } else {
272         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
273             env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
274             helper_raise_exception(EXCP_HW_EXCP);
275         }
276     }
277     env = saved_env;
278 }
This page took 0.039504 seconds and 4 git commands to generate.