|
|
1.1 root 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
1.1.1.3 root 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 18: */
1.1.1.5 ! root 19: #include "cpu.h"
! 20: #include "dyngen-exec.h"
1.1.1.2 root 21: #include "helpers.h"
1.1 root 22:
23: #if defined(CONFIG_USER_ONLY)
24:
1.1.1.4 root 25: void do_interrupt(CPUState *env1)
26: {
27: env1->exception_index = -1;
28: }
29:
30: void do_interrupt_m68k_hardirq(CPUState *env1)
1.1 root 31: {
32: }
33:
34: #else
35:
36: extern int semihosting_enabled;
37:
1.1.1.5 ! root 38: #include "softmmu_exec.h"
! 39:
1.1 root 40: #define MMUSUFFIX _mmu
41:
42: #define SHIFT 0
43: #include "softmmu_template.h"
44:
45: #define SHIFT 1
46: #include "softmmu_template.h"
47:
48: #define SHIFT 2
49: #include "softmmu_template.h"
50:
51: #define SHIFT 3
52: #include "softmmu_template.h"
53:
54: /* Try to fill the TLB and return an exception if error. If retaddr is
55: NULL, it means that the function was called in C code (i.e. not
56: from generated code or from helper.c) */
57: /* XXX: fix it to restore all registers */
1.1.1.5 ! root 58: void tlb_fill(CPUState *env1, target_ulong addr, int is_write, int mmu_idx,
! 59: void *retaddr)
1.1 root 60: {
61: TranslationBlock *tb;
62: CPUState *saved_env;
63: unsigned long pc;
64: int ret;
65:
66: saved_env = env;
1.1.1.5 ! root 67: env = env1;
! 68: ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx);
1.1.1.2 root 69: if (unlikely(ret)) {
1.1 root 70: if (retaddr) {
71: /* now we have a real cpu fault */
72: pc = (unsigned long)retaddr;
73: tb = tb_find_pc(pc);
74: if (tb) {
75: /* the PC is inside the translated code. It means that we have
76: a virtual CPU fault */
1.1.1.4 root 77: cpu_restore_state(tb, env, pc);
1.1 root 78: }
79: }
1.1.1.4 root 80: cpu_loop_exit(env);
1.1 root 81: }
82: env = saved_env;
83: }
84:
85: static void do_rte(void)
86: {
87: uint32_t sp;
88: uint32_t fmt;
89:
90: sp = env->aregs[7];
91: fmt = ldl_kernel(sp);
92: env->pc = ldl_kernel(sp + 4);
93: sp |= (fmt >> 28) & 3;
94: env->sr = fmt & 0xffff;
95: m68k_switch_sp(env);
96: env->aregs[7] = sp + 8;
97: }
98:
1.1.1.4 root 99: static void do_interrupt_all(int is_hw)
1.1 root 100: {
101: uint32_t sp;
102: uint32_t fmt;
103: uint32_t retaddr;
104: uint32_t vector;
105:
106: fmt = 0;
107: retaddr = env->pc;
108:
109: if (!is_hw) {
110: switch (env->exception_index) {
111: case EXCP_RTE:
112: /* Return from an exception. */
113: do_rte();
114: return;
115: case EXCP_HALT_INSN:
116: if (semihosting_enabled
117: && (env->sr & SR_S) != 0
118: && (env->pc & 3) == 0
119: && lduw_code(env->pc - 4) == 0x4e71
120: && ldl_code(env->pc) == 0x4e7bf000) {
121: env->pc += 4;
122: do_m68k_semihosting(env, env->dregs[0]);
123: return;
124: }
125: env->halted = 1;
126: env->exception_index = EXCP_HLT;
1.1.1.4 root 127: cpu_loop_exit(env);
1.1 root 128: return;
129: }
130: if (env->exception_index >= EXCP_TRAP0
131: && env->exception_index <= EXCP_TRAP15) {
132: /* Move the PC after the trap instruction. */
133: retaddr += 2;
134: }
135: }
136:
137: vector = env->exception_index << 2;
138:
139: sp = env->aregs[7];
140:
141: fmt |= 0x40000000;
142: fmt |= (sp & 3) << 28;
143: fmt |= vector << 16;
144: fmt |= env->sr;
145:
146: env->sr |= SR_S;
147: if (is_hw) {
148: env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
149: env->sr &= ~SR_M;
150: }
151: m68k_switch_sp(env);
152:
153: /* ??? This could cause MMU faults. */
154: sp &= ~3;
155: sp -= 4;
156: stl_kernel(sp, retaddr);
157: sp -= 4;
158: stl_kernel(sp, fmt);
159: env->aregs[7] = sp;
160: /* Jump to vector. */
161: env->pc = ldl_kernel(env->vbr + vector);
162: }
163:
1.1.1.4 root 164: void do_interrupt(CPUState *env1)
165: {
166: CPUState *saved_env;
167:
168: saved_env = env;
169: env = env1;
170: do_interrupt_all(0);
171: env = saved_env;
172: }
173:
174: void do_interrupt_m68k_hardirq(CPUState *env1)
175: {
176: CPUState *saved_env;
177:
178: saved_env = env;
179: env = env1;
180: do_interrupt_all(1);
181: env = saved_env;
182: }
1.1 root 183: #endif
1.1.1.2 root 184:
185: static void raise_exception(int tt)
186: {
187: env->exception_index = tt;
1.1.1.4 root 188: cpu_loop_exit(env);
1.1.1.2 root 189: }
190:
191: void HELPER(raise_exception)(uint32_t tt)
192: {
193: raise_exception(tt);
194: }
195:
196: void HELPER(divu)(CPUState *env, uint32_t word)
197: {
198: uint32_t num;
199: uint32_t den;
200: uint32_t quot;
201: uint32_t rem;
202: uint32_t flags;
203:
204: num = env->div1;
205: den = env->div2;
206: /* ??? This needs to make sure the throwing location is accurate. */
207: if (den == 0)
208: raise_exception(EXCP_DIV0);
209: quot = num / den;
210: rem = num % den;
211: flags = 0;
212: /* Avoid using a PARAM1 of zero. This breaks dyngen because it uses
213: the address of a symbol, and gcc knows symbols can't have address
214: zero. */
215: if (word && quot > 0xffff)
216: flags |= CCF_V;
217: if (quot == 0)
218: flags |= CCF_Z;
219: else if ((int32_t)quot < 0)
220: flags |= CCF_N;
221: env->div1 = quot;
222: env->div2 = rem;
223: env->cc_dest = flags;
224: }
225:
226: void HELPER(divs)(CPUState *env, uint32_t word)
227: {
228: int32_t num;
229: int32_t den;
230: int32_t quot;
231: int32_t rem;
232: int32_t flags;
233:
234: num = env->div1;
235: den = env->div2;
236: if (den == 0)
237: raise_exception(EXCP_DIV0);
238: quot = num / den;
239: rem = num % den;
240: flags = 0;
241: if (word && quot != (int16_t)quot)
242: flags |= CCF_V;
243: if (quot == 0)
244: flags |= CCF_Z;
245: else if (quot < 0)
246: flags |= CCF_N;
247: env->div1 = quot;
248: env->div2 = rem;
249: env->cc_dest = flags;
250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.