root / target-cris / op_helper.c @ 8686c490
History | View | Annotate | Download (10.7 kB)
1 | 81fdc5f8 | ths | /*
|
---|---|---|---|
2 | 81fdc5f8 | ths | * CRIS helper routines
|
3 | 81fdc5f8 | ths | *
|
4 | 81fdc5f8 | ths | * Copyright (c) 2007 AXIS Communications
|
5 | 81fdc5f8 | ths | * Written by Edgar E. Iglesias
|
6 | 81fdc5f8 | ths | *
|
7 | 81fdc5f8 | ths | * This library is free software; you can redistribute it and/or
|
8 | 81fdc5f8 | ths | * modify it under the terms of the GNU Lesser General Public
|
9 | 81fdc5f8 | ths | * License as published by the Free Software Foundation; either
|
10 | 81fdc5f8 | ths | * version 2 of the License, or (at your option) any later version.
|
11 | 81fdc5f8 | ths | *
|
12 | 81fdc5f8 | ths | * This library is distributed in the hope that it will be useful,
|
13 | 81fdc5f8 | ths | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | 81fdc5f8 | ths | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | 81fdc5f8 | ths | * Lesser General Public License for more details.
|
16 | 81fdc5f8 | ths | *
|
17 | 81fdc5f8 | ths | * You should have received a copy of the GNU Lesser General Public
|
18 | 81fdc5f8 | ths | * License along with this library; if not, write to the Free Software
|
19 | 81fdc5f8 | ths | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
20 | 81fdc5f8 | ths | */
|
21 | 81fdc5f8 | ths | |
22 | 81fdc5f8 | ths | #include <assert.h> |
23 | 81fdc5f8 | ths | #include "exec.h" |
24 | 786c02f1 | edgar_igl | #include "mmu.h" |
25 | 81fdc5f8 | ths | |
26 | 81fdc5f8 | ths | #define MMUSUFFIX _mmu
|
27 | 273af660 | ths | #ifdef __s390__
|
28 | 273af660 | ths | # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) |
29 | 273af660 | ths | #else
|
30 | 273af660 | ths | # define GETPC() (__builtin_return_address(0)) |
31 | 273af660 | ths | #endif
|
32 | 81fdc5f8 | ths | |
33 | 81fdc5f8 | ths | #define SHIFT 0 |
34 | 81fdc5f8 | ths | #include "softmmu_template.h" |
35 | 81fdc5f8 | ths | |
36 | 81fdc5f8 | ths | #define SHIFT 1 |
37 | 81fdc5f8 | ths | #include "softmmu_template.h" |
38 | 81fdc5f8 | ths | |
39 | 81fdc5f8 | ths | #define SHIFT 2 |
40 | 81fdc5f8 | ths | #include "softmmu_template.h" |
41 | 81fdc5f8 | ths | |
42 | 81fdc5f8 | ths | #define SHIFT 3 |
43 | 81fdc5f8 | ths | #include "softmmu_template.h" |
44 | 81fdc5f8 | ths | |
45 | 786c02f1 | edgar_igl | #define D(x)
|
46 | 786c02f1 | edgar_igl | |
47 | 81fdc5f8 | ths | /* Try to fill the TLB and return an exception if error. If retaddr is
|
48 | 81fdc5f8 | ths | NULL, it means that the function was called in C code (i.e. not
|
49 | 81fdc5f8 | ths | from generated code or from helper.c) */
|
50 | 81fdc5f8 | ths | /* XXX: fix it to restore all registers */
|
51 | 6ebbf390 | j_mayer | void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
52 | 81fdc5f8 | ths | { |
53 | 81fdc5f8 | ths | TranslationBlock *tb; |
54 | 81fdc5f8 | ths | CPUState *saved_env; |
55 | 44f8625d | bellard | unsigned long pc; |
56 | 81fdc5f8 | ths | int ret;
|
57 | 81fdc5f8 | ths | |
58 | 81fdc5f8 | ths | /* XXX: hack to restore env in all cases, even if not called from
|
59 | 81fdc5f8 | ths | generated code */
|
60 | 81fdc5f8 | ths | saved_env = env; |
61 | 81fdc5f8 | ths | env = cpu_single_env; |
62 | b41f7df0 | edgar_igl | |
63 | ef29a70d | edgar_igl | D(fprintf(logfile, "%s pc=%x tpc=%x ra=%x\n", __func__,
|
64 | ef29a70d | edgar_igl | env->pc, env->debug1, retaddr)); |
65 | 6ebbf390 | j_mayer | ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
|
66 | 81fdc5f8 | ths | if (__builtin_expect(ret, 0)) { |
67 | 81fdc5f8 | ths | if (retaddr) {
|
68 | 81fdc5f8 | ths | /* now we have a real cpu fault */
|
69 | 44f8625d | bellard | pc = (unsigned long)retaddr; |
70 | 81fdc5f8 | ths | tb = tb_find_pc(pc); |
71 | 81fdc5f8 | ths | if (tb) {
|
72 | 81fdc5f8 | ths | /* the PC is inside the translated code. It means that we have
|
73 | 81fdc5f8 | ths | a virtual CPU fault */
|
74 | 81fdc5f8 | ths | cpu_restore_state(tb, env, pc, NULL);
|
75 | 81fdc5f8 | ths | } |
76 | 81fdc5f8 | ths | } |
77 | 81fdc5f8 | ths | cpu_loop_exit(); |
78 | 81fdc5f8 | ths | } |
79 | 81fdc5f8 | ths | env = saved_env; |
80 | 81fdc5f8 | ths | } |
81 | 81fdc5f8 | ths | |
82 | dceaf394 | edgar_igl | void helper_raise_exception(uint32_t index)
|
83 | 786c02f1 | edgar_igl | { |
84 | dceaf394 | edgar_igl | env->exception_index = index; |
85 | dceaf394 | edgar_igl | cpu_loop_exit(); |
86 | 786c02f1 | edgar_igl | } |
87 | 786c02f1 | edgar_igl | |
88 | b41f7df0 | edgar_igl | void helper_tlb_flush(void) |
89 | b41f7df0 | edgar_igl | { |
90 | b41f7df0 | edgar_igl | tlb_flush(env, 1);
|
91 | b41f7df0 | edgar_igl | } |
92 | b41f7df0 | edgar_igl | |
93 | b41f7df0 | edgar_igl | void helper_dump(uint32_t a0, uint32_t a1)
|
94 | b41f7df0 | edgar_igl | { |
95 | b41f7df0 | edgar_igl | (fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1));
|
96 | b41f7df0 | edgar_igl | } |
97 | b41f7df0 | edgar_igl | |
98 | b41f7df0 | edgar_igl | void helper_dummy(void) |
99 | b41f7df0 | edgar_igl | { |
100 | b41f7df0 | edgar_igl | |
101 | b41f7df0 | edgar_igl | } |
102 | b41f7df0 | edgar_igl | |
103 | dceaf394 | edgar_igl | void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
|
104 | dceaf394 | edgar_igl | { |
105 | dceaf394 | edgar_igl | uint32_t srs; |
106 | dceaf394 | edgar_igl | srs = env->pregs[PR_SRS]; |
107 | dceaf394 | edgar_igl | srs &= 3;
|
108 | dceaf394 | edgar_igl | env->sregs[srs][sreg] = env->regs[reg]; |
109 | dceaf394 | edgar_igl | |
110 | dceaf394 | edgar_igl | #if !defined(CONFIG_USER_ONLY)
|
111 | dceaf394 | edgar_igl | if (srs == 1 || srs == 2) { |
112 | dceaf394 | edgar_igl | if (sreg == 6) { |
113 | dceaf394 | edgar_igl | /* Writes to tlb-hi write to mm_cause as a side
|
114 | dceaf394 | edgar_igl | effect. */
|
115 | dceaf394 | edgar_igl | env->sregs[SFR_RW_MM_TLB_HI] = T0; |
116 | dceaf394 | edgar_igl | env->sregs[SFR_R_MM_CAUSE] = T0; |
117 | dceaf394 | edgar_igl | } |
118 | dceaf394 | edgar_igl | else if (sreg == 5) { |
119 | dceaf394 | edgar_igl | uint32_t set; |
120 | dceaf394 | edgar_igl | uint32_t idx; |
121 | dceaf394 | edgar_igl | uint32_t lo, hi; |
122 | dceaf394 | edgar_igl | uint32_t vaddr; |
123 | dceaf394 | edgar_igl | |
124 | dceaf394 | edgar_igl | vaddr = cris_mmu_tlb_latest_update(env); |
125 | dceaf394 | edgar_igl | D(fprintf(logfile, "tlb flush vaddr=%x\n", vaddr));
|
126 | dceaf394 | edgar_igl | tlb_flush_page(env, vaddr); |
127 | dceaf394 | edgar_igl | |
128 | dceaf394 | edgar_igl | idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; |
129 | dceaf394 | edgar_igl | set >>= 4;
|
130 | dceaf394 | edgar_igl | set &= 3;
|
131 | dceaf394 | edgar_igl | |
132 | dceaf394 | edgar_igl | idx &= 15;
|
133 | dceaf394 | edgar_igl | /* We've just made a write to tlb_lo. */
|
134 | dceaf394 | edgar_igl | lo = env->sregs[SFR_RW_MM_TLB_LO]; |
135 | dceaf394 | edgar_igl | /* Writes are done via r_mm_cause. */
|
136 | dceaf394 | edgar_igl | hi = env->sregs[SFR_R_MM_CAUSE]; |
137 | dceaf394 | edgar_igl | env->tlbsets[srs - 1][set][idx].lo = lo;
|
138 | dceaf394 | edgar_igl | env->tlbsets[srs - 1][set][idx].hi = hi;
|
139 | dceaf394 | edgar_igl | } |
140 | dceaf394 | edgar_igl | } |
141 | dceaf394 | edgar_igl | #endif
|
142 | dceaf394 | edgar_igl | } |
143 | dceaf394 | edgar_igl | |
144 | dceaf394 | edgar_igl | void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
|
145 | dceaf394 | edgar_igl | { |
146 | dceaf394 | edgar_igl | uint32_t srs; |
147 | dceaf394 | edgar_igl | env->pregs[PR_SRS] &= 3;
|
148 | dceaf394 | edgar_igl | srs = env->pregs[PR_SRS]; |
149 | dceaf394 | edgar_igl | |
150 | dceaf394 | edgar_igl | #if !defined(CONFIG_USER_ONLY)
|
151 | dceaf394 | edgar_igl | if (srs == 1 || srs == 2) |
152 | dceaf394 | edgar_igl | { |
153 | dceaf394 | edgar_igl | uint32_t set; |
154 | dceaf394 | edgar_igl | uint32_t idx; |
155 | dceaf394 | edgar_igl | uint32_t lo, hi; |
156 | dceaf394 | edgar_igl | |
157 | dceaf394 | edgar_igl | idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; |
158 | dceaf394 | edgar_igl | set >>= 4;
|
159 | dceaf394 | edgar_igl | set &= 3;
|
160 | dceaf394 | edgar_igl | idx &= 15;
|
161 | dceaf394 | edgar_igl | |
162 | dceaf394 | edgar_igl | /* Update the mirror regs. */
|
163 | dceaf394 | edgar_igl | hi = env->tlbsets[srs - 1][set][idx].hi;
|
164 | dceaf394 | edgar_igl | lo = env->tlbsets[srs - 1][set][idx].lo;
|
165 | dceaf394 | edgar_igl | env->sregs[SFR_RW_MM_TLB_HI] = hi; |
166 | dceaf394 | edgar_igl | env->sregs[SFR_RW_MM_TLB_LO] = lo; |
167 | dceaf394 | edgar_igl | } |
168 | dceaf394 | edgar_igl | #endif
|
169 | dceaf394 | edgar_igl | env->regs[reg] = env->sregs[srs][sreg]; |
170 | dceaf394 | edgar_igl | RETURN(); |
171 | dceaf394 | edgar_igl | } |
172 | dceaf394 | edgar_igl | |
173 | dceaf394 | edgar_igl | static void cris_ccs_rshift(CPUState *env) |
174 | dceaf394 | edgar_igl | { |
175 | dceaf394 | edgar_igl | uint32_t ccs; |
176 | dceaf394 | edgar_igl | |
177 | dceaf394 | edgar_igl | /* Apply the ccs shift. */
|
178 | dceaf394 | edgar_igl | ccs = env->pregs[PR_CCS]; |
179 | dceaf394 | edgar_igl | ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10); |
180 | dceaf394 | edgar_igl | if (ccs & U_FLAG)
|
181 | dceaf394 | edgar_igl | { |
182 | dceaf394 | edgar_igl | /* Enter user mode. */
|
183 | dceaf394 | edgar_igl | env->ksp = env->regs[R_SP]; |
184 | dceaf394 | edgar_igl | env->regs[R_SP] = env->pregs[PR_USP]; |
185 | dceaf394 | edgar_igl | } |
186 | dceaf394 | edgar_igl | |
187 | dceaf394 | edgar_igl | env->pregs[PR_CCS] = ccs; |
188 | dceaf394 | edgar_igl | } |
189 | dceaf394 | edgar_igl | |
190 | b41f7df0 | edgar_igl | void helper_rfe(void) |
191 | b41f7df0 | edgar_igl | { |
192 | b41f7df0 | edgar_igl | D(fprintf(logfile, "rfe: erp=%x pid=%x ccs=%x btarget=%x\n",
|
193 | b41f7df0 | edgar_igl | env->pregs[PR_ERP], env->pregs[PR_PID], |
194 | b41f7df0 | edgar_igl | env->pregs[PR_CCS], |
195 | b41f7df0 | edgar_igl | env->btarget)); |
196 | dceaf394 | edgar_igl | |
197 | dceaf394 | edgar_igl | cris_ccs_rshift(env); |
198 | dceaf394 | edgar_igl | |
199 | dceaf394 | edgar_igl | /* RFE sets the P_FLAG only if the R_FLAG is not set. */
|
200 | dceaf394 | edgar_igl | if (!(env->pregs[PR_CCS] & R_FLAG))
|
201 | dceaf394 | edgar_igl | env->pregs[PR_CCS] |= P_FLAG; |
202 | b41f7df0 | edgar_igl | } |
203 | b41f7df0 | edgar_igl | |
204 | b41f7df0 | edgar_igl | void helper_store(uint32_t a0)
|
205 | b41f7df0 | edgar_igl | { |
206 | b41f7df0 | edgar_igl | if (env->pregs[PR_CCS] & P_FLAG )
|
207 | b41f7df0 | edgar_igl | { |
208 | b41f7df0 | edgar_igl | cpu_abort(env, "cond_store_failed! pc=%x a0=%x\n",
|
209 | b41f7df0 | edgar_igl | env->pc, a0); |
210 | b41f7df0 | edgar_igl | } |
211 | b41f7df0 | edgar_igl | } |
212 | b41f7df0 | edgar_igl | |
213 | 81fdc5f8 | ths | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
214 | 81fdc5f8 | ths | int is_asi)
|
215 | 81fdc5f8 | ths | { |
216 | 786c02f1 | edgar_igl | D(printf("%s addr=%x w=%d ex=%d asi=%d\n",
|
217 | 786c02f1 | edgar_igl | __func__, addr, is_write, is_exec, is_asi)); |
218 | 81fdc5f8 | ths | } |
219 | b41f7df0 | edgar_igl | |
220 | b41f7df0 | edgar_igl | static void evaluate_flags_writeback(uint32_t flags) |
221 | b41f7df0 | edgar_igl | { |
222 | b41f7df0 | edgar_igl | int x;
|
223 | b41f7df0 | edgar_igl | |
224 | b41f7df0 | edgar_igl | /* Extended arithmetics, leave the z flag alone. */
|
225 | b41f7df0 | edgar_igl | env->debug3 = env->pregs[PR_CCS]; |
226 | b41f7df0 | edgar_igl | |
227 | b41f7df0 | edgar_igl | if (env->cc_x_live)
|
228 | b41f7df0 | edgar_igl | x = env->cc_x; |
229 | b41f7df0 | edgar_igl | else
|
230 | b41f7df0 | edgar_igl | x = env->pregs[PR_CCS] & X_FLAG; |
231 | b41f7df0 | edgar_igl | |
232 | b41f7df0 | edgar_igl | if ((x || env->cc_op == CC_OP_ADDC)
|
233 | b41f7df0 | edgar_igl | && flags & Z_FLAG) |
234 | b41f7df0 | edgar_igl | env->cc_mask &= ~Z_FLAG; |
235 | b41f7df0 | edgar_igl | |
236 | b41f7df0 | edgar_igl | /* all insn clear the x-flag except setf or clrf. */
|
237 | b41f7df0 | edgar_igl | env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG); |
238 | b41f7df0 | edgar_igl | flags &= env->cc_mask; |
239 | b41f7df0 | edgar_igl | env->pregs[PR_CCS] |= flags; |
240 | b41f7df0 | edgar_igl | } |
241 | b41f7df0 | edgar_igl | |
242 | b41f7df0 | edgar_igl | void helper_evaluate_flags_muls(void) |
243 | b41f7df0 | edgar_igl | { |
244 | b41f7df0 | edgar_igl | uint32_t src; |
245 | b41f7df0 | edgar_igl | uint32_t dst; |
246 | b41f7df0 | edgar_igl | uint32_t res; |
247 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
248 | dceaf394 | edgar_igl | int64_t tmp; |
249 | b41f7df0 | edgar_igl | int32_t mof; |
250 | b41f7df0 | edgar_igl | int dneg;
|
251 | b41f7df0 | edgar_igl | |
252 | b41f7df0 | edgar_igl | src = env->cc_src; |
253 | b41f7df0 | edgar_igl | dst = env->cc_dest; |
254 | b41f7df0 | edgar_igl | res = env->cc_result; |
255 | b41f7df0 | edgar_igl | |
256 | b41f7df0 | edgar_igl | dneg = ((int32_t)res) < 0;
|
257 | b41f7df0 | edgar_igl | |
258 | dceaf394 | edgar_igl | mof = env->pregs[PR_MOF]; |
259 | dceaf394 | edgar_igl | tmp = mof; |
260 | dceaf394 | edgar_igl | tmp <<= 32;
|
261 | dceaf394 | edgar_igl | tmp |= res; |
262 | b41f7df0 | edgar_igl | if (tmp == 0) |
263 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
264 | b41f7df0 | edgar_igl | else if (tmp < 0) |
265 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
266 | b41f7df0 | edgar_igl | if ((dneg && mof != -1) |
267 | b41f7df0 | edgar_igl | || (!dneg && mof != 0))
|
268 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
269 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
270 | b41f7df0 | edgar_igl | } |
271 | b41f7df0 | edgar_igl | |
272 | b41f7df0 | edgar_igl | void helper_evaluate_flags_mulu(void) |
273 | b41f7df0 | edgar_igl | { |
274 | b41f7df0 | edgar_igl | uint32_t src; |
275 | b41f7df0 | edgar_igl | uint32_t dst; |
276 | b41f7df0 | edgar_igl | uint32_t res; |
277 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
278 | dceaf394 | edgar_igl | uint64_t tmp; |
279 | b41f7df0 | edgar_igl | uint32_t mof; |
280 | b41f7df0 | edgar_igl | |
281 | b41f7df0 | edgar_igl | src = env->cc_src; |
282 | b41f7df0 | edgar_igl | dst = env->cc_dest; |
283 | b41f7df0 | edgar_igl | res = env->cc_result; |
284 | b41f7df0 | edgar_igl | |
285 | dceaf394 | edgar_igl | mof = env->pregs[PR_MOF]; |
286 | dceaf394 | edgar_igl | tmp = mof; |
287 | dceaf394 | edgar_igl | tmp <<= 32;
|
288 | dceaf394 | edgar_igl | tmp |= res; |
289 | b41f7df0 | edgar_igl | if (tmp == 0) |
290 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
291 | b41f7df0 | edgar_igl | else if (tmp >> 63) |
292 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
293 | b41f7df0 | edgar_igl | if (mof)
|
294 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
295 | b41f7df0 | edgar_igl | |
296 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
297 | b41f7df0 | edgar_igl | } |
298 | b41f7df0 | edgar_igl | |
299 | b41f7df0 | edgar_igl | void helper_evaluate_flags_mcp(void) |
300 | b41f7df0 | edgar_igl | { |
301 | b41f7df0 | edgar_igl | uint32_t src; |
302 | b41f7df0 | edgar_igl | uint32_t dst; |
303 | b41f7df0 | edgar_igl | uint32_t res; |
304 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
305 | b41f7df0 | edgar_igl | |
306 | b41f7df0 | edgar_igl | src = env->cc_src; |
307 | b41f7df0 | edgar_igl | dst = env->cc_dest; |
308 | b41f7df0 | edgar_igl | res = env->cc_result; |
309 | b41f7df0 | edgar_igl | |
310 | b41f7df0 | edgar_igl | if ((res & 0x80000000L) != 0L) |
311 | b41f7df0 | edgar_igl | { |
312 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
313 | b41f7df0 | edgar_igl | if (((src & 0x80000000L) == 0L) |
314 | b41f7df0 | edgar_igl | && ((dst & 0x80000000L) == 0L)) |
315 | b41f7df0 | edgar_igl | { |
316 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
317 | b41f7df0 | edgar_igl | } |
318 | b41f7df0 | edgar_igl | else if (((src & 0x80000000L) != 0L) && |
319 | b41f7df0 | edgar_igl | ((dst & 0x80000000L) != 0L)) |
320 | b41f7df0 | edgar_igl | { |
321 | b41f7df0 | edgar_igl | flags |= R_FLAG; |
322 | b41f7df0 | edgar_igl | } |
323 | b41f7df0 | edgar_igl | } |
324 | b41f7df0 | edgar_igl | else
|
325 | b41f7df0 | edgar_igl | { |
326 | b41f7df0 | edgar_igl | if (res == 0L) |
327 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
328 | b41f7df0 | edgar_igl | if (((src & 0x80000000L) != 0L) |
329 | b41f7df0 | edgar_igl | && ((dst & 0x80000000L) != 0L)) |
330 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
331 | b41f7df0 | edgar_igl | if ((dst & 0x80000000L) != 0L |
332 | b41f7df0 | edgar_igl | || (src & 0x80000000L) != 0L) |
333 | b41f7df0 | edgar_igl | flags |= R_FLAG; |
334 | b41f7df0 | edgar_igl | } |
335 | b41f7df0 | edgar_igl | |
336 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
337 | b41f7df0 | edgar_igl | } |
338 | b41f7df0 | edgar_igl | |
339 | b41f7df0 | edgar_igl | void helper_evaluate_flags_alu_4(void) |
340 | b41f7df0 | edgar_igl | { |
341 | b41f7df0 | edgar_igl | uint32_t src; |
342 | b41f7df0 | edgar_igl | uint32_t dst; |
343 | b41f7df0 | edgar_igl | uint32_t res; |
344 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
345 | b41f7df0 | edgar_igl | |
346 | b41f7df0 | edgar_igl | src = env->cc_src; |
347 | b41f7df0 | edgar_igl | dst = env->cc_dest; |
348 | b41f7df0 | edgar_igl | res = env->cc_result; |
349 | b41f7df0 | edgar_igl | |
350 | b41f7df0 | edgar_igl | if ((res & 0x80000000L) != 0L) |
351 | b41f7df0 | edgar_igl | { |
352 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
353 | b41f7df0 | edgar_igl | if (((src & 0x80000000L) == 0L) |
354 | b41f7df0 | edgar_igl | && ((dst & 0x80000000L) == 0L)) |
355 | b41f7df0 | edgar_igl | { |
356 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
357 | b41f7df0 | edgar_igl | } |
358 | b41f7df0 | edgar_igl | else if (((src & 0x80000000L) != 0L) && |
359 | b41f7df0 | edgar_igl | ((dst & 0x80000000L) != 0L)) |
360 | b41f7df0 | edgar_igl | { |
361 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
362 | b41f7df0 | edgar_igl | } |
363 | b41f7df0 | edgar_igl | } |
364 | b41f7df0 | edgar_igl | else
|
365 | b41f7df0 | edgar_igl | { |
366 | b41f7df0 | edgar_igl | if (res == 0L) |
367 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
368 | b41f7df0 | edgar_igl | if (((src & 0x80000000L) != 0L) |
369 | b41f7df0 | edgar_igl | && ((dst & 0x80000000L) != 0L)) |
370 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
371 | b41f7df0 | edgar_igl | if ((dst & 0x80000000L) != 0L |
372 | b41f7df0 | edgar_igl | || (src & 0x80000000L) != 0L) |
373 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
374 | b41f7df0 | edgar_igl | } |
375 | b41f7df0 | edgar_igl | |
376 | b41f7df0 | edgar_igl | if (env->cc_op == CC_OP_SUB
|
377 | b41f7df0 | edgar_igl | || env->cc_op == CC_OP_CMP) { |
378 | b41f7df0 | edgar_igl | flags ^= C_FLAG; |
379 | b41f7df0 | edgar_igl | } |
380 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
381 | b41f7df0 | edgar_igl | } |
382 | b41f7df0 | edgar_igl | |
383 | b41f7df0 | edgar_igl | void helper_evaluate_flags_move_4 (void) |
384 | b41f7df0 | edgar_igl | { |
385 | b41f7df0 | edgar_igl | uint32_t src; |
386 | b41f7df0 | edgar_igl | uint32_t res; |
387 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
388 | b41f7df0 | edgar_igl | |
389 | b41f7df0 | edgar_igl | src = env->cc_src; |
390 | b41f7df0 | edgar_igl | res = env->cc_result; |
391 | b41f7df0 | edgar_igl | |
392 | b41f7df0 | edgar_igl | if ((int32_t)res < 0) |
393 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
394 | b41f7df0 | edgar_igl | else if (res == 0L) |
395 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
396 | b41f7df0 | edgar_igl | |
397 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
398 | b41f7df0 | edgar_igl | } |
399 | b41f7df0 | edgar_igl | void helper_evaluate_flags_move_2 (void) |
400 | b41f7df0 | edgar_igl | { |
401 | b41f7df0 | edgar_igl | uint32_t src; |
402 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
403 | b41f7df0 | edgar_igl | uint16_t res; |
404 | b41f7df0 | edgar_igl | |
405 | b41f7df0 | edgar_igl | src = env->cc_src; |
406 | b41f7df0 | edgar_igl | res = env->cc_result; |
407 | b41f7df0 | edgar_igl | |
408 | b41f7df0 | edgar_igl | if ((int16_t)res < 0L) |
409 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
410 | b41f7df0 | edgar_igl | else if (res == 0) |
411 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
412 | b41f7df0 | edgar_igl | |
413 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
414 | b41f7df0 | edgar_igl | } |
415 | b41f7df0 | edgar_igl | |
416 | b41f7df0 | edgar_igl | /* TODO: This is expensive. We could split things up and only evaluate part of
|
417 | b41f7df0 | edgar_igl | CCR on a need to know basis. For now, we simply re-evaluate everything. */
|
418 | b41f7df0 | edgar_igl | void helper_evaluate_flags (void) |
419 | b41f7df0 | edgar_igl | { |
420 | b41f7df0 | edgar_igl | uint32_t src; |
421 | b41f7df0 | edgar_igl | uint32_t dst; |
422 | b41f7df0 | edgar_igl | uint32_t res; |
423 | b41f7df0 | edgar_igl | uint32_t flags = 0;
|
424 | b41f7df0 | edgar_igl | |
425 | b41f7df0 | edgar_igl | src = env->cc_src; |
426 | b41f7df0 | edgar_igl | dst = env->cc_dest; |
427 | b41f7df0 | edgar_igl | res = env->cc_result; |
428 | b41f7df0 | edgar_igl | |
429 | b41f7df0 | edgar_igl | |
430 | b41f7df0 | edgar_igl | /* Now, evaluate the flags. This stuff is based on
|
431 | b41f7df0 | edgar_igl | Per Zander's CRISv10 simulator. */
|
432 | b41f7df0 | edgar_igl | switch (env->cc_size)
|
433 | b41f7df0 | edgar_igl | { |
434 | b41f7df0 | edgar_igl | case 1: |
435 | b41f7df0 | edgar_igl | if ((res & 0x80L) != 0L) |
436 | b41f7df0 | edgar_igl | { |
437 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
438 | b41f7df0 | edgar_igl | if (((src & 0x80L) == 0L) |
439 | b41f7df0 | edgar_igl | && ((dst & 0x80L) == 0L)) |
440 | b41f7df0 | edgar_igl | { |
441 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
442 | b41f7df0 | edgar_igl | } |
443 | b41f7df0 | edgar_igl | else if (((src & 0x80L) != 0L) |
444 | b41f7df0 | edgar_igl | && ((dst & 0x80L) != 0L)) |
445 | b41f7df0 | edgar_igl | { |
446 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
447 | b41f7df0 | edgar_igl | } |
448 | b41f7df0 | edgar_igl | } |
449 | b41f7df0 | edgar_igl | else
|
450 | b41f7df0 | edgar_igl | { |
451 | b41f7df0 | edgar_igl | if ((res & 0xFFL) == 0L) |
452 | b41f7df0 | edgar_igl | { |
453 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
454 | b41f7df0 | edgar_igl | } |
455 | b41f7df0 | edgar_igl | if (((src & 0x80L) != 0L) |
456 | b41f7df0 | edgar_igl | && ((dst & 0x80L) != 0L)) |
457 | b41f7df0 | edgar_igl | { |
458 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
459 | b41f7df0 | edgar_igl | } |
460 | b41f7df0 | edgar_igl | if ((dst & 0x80L) != 0L |
461 | b41f7df0 | edgar_igl | || (src & 0x80L) != 0L) |
462 | b41f7df0 | edgar_igl | { |
463 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
464 | b41f7df0 | edgar_igl | } |
465 | b41f7df0 | edgar_igl | } |
466 | b41f7df0 | edgar_igl | break;
|
467 | b41f7df0 | edgar_igl | case 2: |
468 | b41f7df0 | edgar_igl | if ((res & 0x8000L) != 0L) |
469 | b41f7df0 | edgar_igl | { |
470 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
471 | b41f7df0 | edgar_igl | if (((src & 0x8000L) == 0L) |
472 | b41f7df0 | edgar_igl | && ((dst & 0x8000L) == 0L)) |
473 | b41f7df0 | edgar_igl | { |
474 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
475 | b41f7df0 | edgar_igl | } |
476 | b41f7df0 | edgar_igl | else if (((src & 0x8000L) != 0L) |
477 | b41f7df0 | edgar_igl | && ((dst & 0x8000L) != 0L)) |
478 | b41f7df0 | edgar_igl | { |
479 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
480 | b41f7df0 | edgar_igl | } |
481 | b41f7df0 | edgar_igl | } |
482 | b41f7df0 | edgar_igl | else
|
483 | b41f7df0 | edgar_igl | { |
484 | b41f7df0 | edgar_igl | if ((res & 0xFFFFL) == 0L) |
485 | b41f7df0 | edgar_igl | { |
486 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
487 | b41f7df0 | edgar_igl | } |
488 | b41f7df0 | edgar_igl | if (((src & 0x8000L) != 0L) |
489 | b41f7df0 | edgar_igl | && ((dst & 0x8000L) != 0L)) |
490 | b41f7df0 | edgar_igl | { |
491 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
492 | b41f7df0 | edgar_igl | } |
493 | b41f7df0 | edgar_igl | if ((dst & 0x8000L) != 0L |
494 | b41f7df0 | edgar_igl | || (src & 0x8000L) != 0L) |
495 | b41f7df0 | edgar_igl | { |
496 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
497 | b41f7df0 | edgar_igl | } |
498 | b41f7df0 | edgar_igl | } |
499 | b41f7df0 | edgar_igl | break;
|
500 | b41f7df0 | edgar_igl | case 4: |
501 | b41f7df0 | edgar_igl | if ((res & 0x80000000L) != 0L) |
502 | b41f7df0 | edgar_igl | { |
503 | b41f7df0 | edgar_igl | flags |= N_FLAG; |
504 | b41f7df0 | edgar_igl | if (((src & 0x80000000L) == 0L) |
505 | b41f7df0 | edgar_igl | && ((dst & 0x80000000L) == 0L)) |
506 | b41f7df0 | edgar_igl | { |
507 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
508 | b41f7df0 | edgar_igl | } |
509 | b41f7df0 | edgar_igl | else if (((src & 0x80000000L) != 0L) && |
510 | b41f7df0 | edgar_igl | ((dst & 0x80000000L) != 0L)) |
511 | b41f7df0 | edgar_igl | { |
512 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
513 | b41f7df0 | edgar_igl | } |
514 | b41f7df0 | edgar_igl | } |
515 | b41f7df0 | edgar_igl | else
|
516 | b41f7df0 | edgar_igl | { |
517 | b41f7df0 | edgar_igl | if (res == 0L) |
518 | b41f7df0 | edgar_igl | flags |= Z_FLAG; |
519 | b41f7df0 | edgar_igl | if (((src & 0x80000000L) != 0L) |
520 | b41f7df0 | edgar_igl | && ((dst & 0x80000000L) != 0L)) |
521 | b41f7df0 | edgar_igl | flags |= V_FLAG; |
522 | b41f7df0 | edgar_igl | if ((dst & 0x80000000L) != 0L |
523 | b41f7df0 | edgar_igl | || (src & 0x80000000L) != 0L) |
524 | b41f7df0 | edgar_igl | flags |= C_FLAG; |
525 | b41f7df0 | edgar_igl | } |
526 | b41f7df0 | edgar_igl | break;
|
527 | b41f7df0 | edgar_igl | default:
|
528 | b41f7df0 | edgar_igl | break;
|
529 | b41f7df0 | edgar_igl | } |
530 | b41f7df0 | edgar_igl | |
531 | b41f7df0 | edgar_igl | if (env->cc_op == CC_OP_SUB
|
532 | b41f7df0 | edgar_igl | || env->cc_op == CC_OP_CMP) { |
533 | b41f7df0 | edgar_igl | flags ^= C_FLAG; |
534 | b41f7df0 | edgar_igl | } |
535 | b41f7df0 | edgar_igl | evaluate_flags_writeback(flags); |
536 | b41f7df0 | edgar_igl | } |