Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ 6e473128

History | View | Annotate | Download (7.2 kB)

1 e6e5906b pbrook
/*
2 e6e5906b pbrook
 *  m68k op helpers
3 e6e5906b pbrook
 * 
4 0633879f pbrook
 *  Copyright (c) 2006-2007 CodeSourcery
5 e6e5906b pbrook
 *  Written by Paul Brook
6 e6e5906b pbrook
 *
7 e6e5906b pbrook
 * This library is free software; you can redistribute it and/or
8 e6e5906b pbrook
 * modify it under the terms of the GNU Lesser General Public
9 e6e5906b pbrook
 * License as published by the Free Software Foundation; either
10 e6e5906b pbrook
 * version 2 of the License, or (at your option) any later version.
11 e6e5906b pbrook
 *
12 e6e5906b pbrook
 * This library is distributed in the hope that it will be useful,
13 e6e5906b pbrook
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 e6e5906b pbrook
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 e6e5906b pbrook
 * General Public License for more details.
16 e6e5906b pbrook
 *
17 e6e5906b pbrook
 * You should have received a copy of the GNU Lesser General Public
18 e6e5906b pbrook
 * License along with this library; if not, write to the Free Software
19 e6e5906b pbrook
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 e6e5906b pbrook
 */
21 e6e5906b pbrook
22 e6e5906b pbrook
#include <stdio.h>
23 0402f767 pbrook
#include <string.h>
24 e6e5906b pbrook
25 e6e5906b pbrook
#include "config.h"
26 e6e5906b pbrook
#include "cpu.h"
27 e6e5906b pbrook
#include "exec-all.h"
28 e6e5906b pbrook
29 0402f767 pbrook
enum m68k_cpuid {
30 0402f767 pbrook
    M68K_CPUID_M5206,
31 0402f767 pbrook
    M68K_CPUID_CFV4E,
32 0402f767 pbrook
    M68K_CPUID_ANY,
33 0402f767 pbrook
};
34 0402f767 pbrook
35 0402f767 pbrook
struct m68k_def_t {
36 0402f767 pbrook
    const char * name;
37 0402f767 pbrook
    enum m68k_cpuid id;
38 0402f767 pbrook
};
39 0402f767 pbrook
40 0402f767 pbrook
static m68k_def_t m68k_cpu_defs[] = {
41 0402f767 pbrook
    {"m5206", M68K_CPUID_M5206}, 
42 0402f767 pbrook
    {"cfv4e", M68K_CPUID_CFV4E},
43 0402f767 pbrook
    {"any", M68K_CPUID_ANY},
44 0402f767 pbrook
    {NULL, 0}, 
45 0402f767 pbrook
};
46 0402f767 pbrook
47 0402f767 pbrook
static void m68k_set_feature(CPUM68KState *env, int feature)
48 0402f767 pbrook
{
49 0402f767 pbrook
    env->features |= (1u << feature);
50 0402f767 pbrook
}
51 0402f767 pbrook
52 0402f767 pbrook
int cpu_m68k_set_model(CPUM68KState *env, const char * name)
53 0402f767 pbrook
{
54 0402f767 pbrook
    m68k_def_t *def;
55 0402f767 pbrook
56 0402f767 pbrook
    for (def = m68k_cpu_defs; def->name; def++) {
57 0402f767 pbrook
        if (strcmp(def->name, name) == 0)
58 0402f767 pbrook
            break;
59 0402f767 pbrook
    }
60 0402f767 pbrook
    if (!def->name)
61 0402f767 pbrook
        return 1;
62 0402f767 pbrook
63 0402f767 pbrook
    switch (def->id) {
64 0402f767 pbrook
    case M68K_CPUID_M5206:
65 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
66 0402f767 pbrook
        break;
67 0402f767 pbrook
    case M68K_CPUID_CFV4E:
68 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
69 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
70 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_C);
71 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
72 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_MAC);
73 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
74 0402f767 pbrook
        break;
75 0402f767 pbrook
    case M68K_CPUID_ANY:
76 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
77 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
78 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_C);
79 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
80 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_MAC);
81 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
82 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
83 0402f767 pbrook
        break;
84 0402f767 pbrook
    }
85 0402f767 pbrook
86 0402f767 pbrook
    register_m68k_insns(env);
87 0402f767 pbrook
88 0402f767 pbrook
    return 0;
89 0402f767 pbrook
}
90 0402f767 pbrook
91 e6e5906b pbrook
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
92 e6e5906b pbrook
{
93 e6e5906b pbrook
    int flags;
94 e6e5906b pbrook
    uint32_t src;
95 e6e5906b pbrook
    uint32_t dest;
96 e6e5906b pbrook
    uint32_t tmp;
97 e6e5906b pbrook
98 e6e5906b pbrook
#define HIGHBIT 0x80000000u
99 e6e5906b pbrook
100 e6e5906b pbrook
#define SET_NZ(x) do { \
101 e6e5906b pbrook
    if ((x) == 0) \
102 e6e5906b pbrook
        flags |= CCF_Z; \
103 e6e5906b pbrook
    else if ((int32_t)(x) < 0) \
104 e6e5906b pbrook
        flags |= CCF_N; \
105 e6e5906b pbrook
    } while (0)
106 e6e5906b pbrook
107 e6e5906b pbrook
#define SET_FLAGS_SUB(type, utype) do { \
108 e6e5906b pbrook
    SET_NZ((type)dest); \
109 e6e5906b pbrook
    tmp = dest + src; \
110 e6e5906b pbrook
    if ((utype) tmp < (utype) src) \
111 e6e5906b pbrook
        flags |= CCF_C; \
112 e6e5906b pbrook
    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
113 e6e5906b pbrook
        flags |= CCF_V; \
114 e6e5906b pbrook
    } while (0)
115 e6e5906b pbrook
116 e6e5906b pbrook
    flags = 0;
117 e6e5906b pbrook
    src = env->cc_src;
118 e6e5906b pbrook
    dest = env->cc_dest;
119 e6e5906b pbrook
    switch (cc_op) {
120 e6e5906b pbrook
    case CC_OP_FLAGS:
121 e6e5906b pbrook
        flags = dest;
122 e6e5906b pbrook
        break;
123 e6e5906b pbrook
    case CC_OP_LOGIC:
124 e6e5906b pbrook
        SET_NZ(dest);
125 e6e5906b pbrook
        break;
126 e6e5906b pbrook
    case CC_OP_ADD:
127 e6e5906b pbrook
        SET_NZ(dest);
128 e6e5906b pbrook
        if (dest < src)
129 e6e5906b pbrook
            flags |= CCF_C;
130 e6e5906b pbrook
        tmp = dest - src;
131 e6e5906b pbrook
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
132 e6e5906b pbrook
            flags |= CCF_V;
133 e6e5906b pbrook
        break;
134 e6e5906b pbrook
    case CC_OP_SUB:
135 e6e5906b pbrook
        SET_FLAGS_SUB(int32_t, uint32_t);
136 e6e5906b pbrook
        break;
137 e6e5906b pbrook
    case CC_OP_CMPB:
138 e6e5906b pbrook
        SET_FLAGS_SUB(int8_t, uint8_t);
139 e6e5906b pbrook
        break;
140 e6e5906b pbrook
    case CC_OP_CMPW:
141 e6e5906b pbrook
        SET_FLAGS_SUB(int16_t, uint16_t);
142 e6e5906b pbrook
        break;
143 e6e5906b pbrook
    case CC_OP_ADDX:
144 e6e5906b pbrook
        SET_NZ(dest);
145 e6e5906b pbrook
        if (dest <= src)
146 e6e5906b pbrook
            flags |= CCF_C;
147 e6e5906b pbrook
        tmp = dest - src - 1;
148 e6e5906b pbrook
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
149 e6e5906b pbrook
            flags |= CCF_V;
150 e6e5906b pbrook
        break;
151 e6e5906b pbrook
    case CC_OP_SUBX:
152 e6e5906b pbrook
        SET_NZ(dest);
153 e6e5906b pbrook
        tmp = dest + src + 1;
154 e6e5906b pbrook
        if (tmp <= src)
155 e6e5906b pbrook
            flags |= CCF_C;
156 e6e5906b pbrook
        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
157 e6e5906b pbrook
            flags |= CCF_V;
158 e6e5906b pbrook
        break;
159 e6e5906b pbrook
    case CC_OP_SHL:
160 e6e5906b pbrook
        if (src >= 32) {
161 e6e5906b pbrook
            SET_NZ(0);
162 e6e5906b pbrook
        } else {
163 e6e5906b pbrook
            tmp = dest << src;
164 e6e5906b pbrook
            SET_NZ(tmp);
165 e6e5906b pbrook
        }
166 e6e5906b pbrook
        if (src && src <= 32 && (dest & (1 << (32 - src))))
167 e6e5906b pbrook
            flags |= CCF_C;
168 e6e5906b pbrook
        break;
169 e6e5906b pbrook
    case CC_OP_SHR:
170 e6e5906b pbrook
        if (src >= 32) {
171 e6e5906b pbrook
            SET_NZ(0);
172 e6e5906b pbrook
        } else {
173 e6e5906b pbrook
            tmp = dest >> src;
174 e6e5906b pbrook
            SET_NZ(tmp);
175 e6e5906b pbrook
        }
176 e6e5906b pbrook
        if (src && src <= 32 && ((dest >> (src - 1)) & 1))
177 e6e5906b pbrook
            flags |= CCF_C;
178 e6e5906b pbrook
        break;
179 e6e5906b pbrook
    case CC_OP_SAR:
180 e6e5906b pbrook
        if (src >= 32) {
181 e6e5906b pbrook
            SET_NZ(-1);
182 e6e5906b pbrook
        } else {
183 e6e5906b pbrook
            tmp = (int32_t)dest >> src;
184 e6e5906b pbrook
            SET_NZ(tmp);
185 e6e5906b pbrook
        }
186 e6e5906b pbrook
        if (src && src <= 32 && (((int32_t)dest >> (src - 1)) & 1))
187 e6e5906b pbrook
            flags |= CCF_C;
188 e6e5906b pbrook
        break;
189 e6e5906b pbrook
    default:
190 e6e5906b pbrook
        cpu_abort(env, "Bad CC_OP %d", cc_op);
191 e6e5906b pbrook
    }
192 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
193 e6e5906b pbrook
    env->cc_dest = flags;
194 e6e5906b pbrook
}
195 e6e5906b pbrook
196 e6e5906b pbrook
float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1)
197 e6e5906b pbrook
{
198 e6e5906b pbrook
    /* ??? This may incorrectly raise exceptions.  */
199 e6e5906b pbrook
    /* ??? Should flush denormals to zero.  */
200 e6e5906b pbrook
    float64 res;
201 e6e5906b pbrook
    res = float64_sub(src0, src1, &env->fp_status);
202 e6e5906b pbrook
    if (float64_is_nan(res)) {
203 e6e5906b pbrook
        /* +/-inf compares equal against itself, but sub returns nan.  */
204 e6e5906b pbrook
        if (!float64_is_nan(src0)
205 e6e5906b pbrook
            && !float64_is_nan(src1)) {
206 e6e5906b pbrook
            res = 0;
207 e6e5906b pbrook
            if (float64_lt_quiet(src0, res, &env->fp_status))
208 e6e5906b pbrook
                res = float64_chs(res);
209 e6e5906b pbrook
        }
210 e6e5906b pbrook
    }
211 e6e5906b pbrook
    return res;
212 e6e5906b pbrook
}
213 0633879f pbrook
214 0633879f pbrook
void helper_movec(CPUM68KState *env, int reg, uint32_t val)
215 0633879f pbrook
{
216 0633879f pbrook
    switch (reg) {
217 0633879f pbrook
    case 0x02: /* CACR */
218 0633879f pbrook
        /* Ignored.  */
219 0633879f pbrook
        break;
220 0633879f pbrook
    case 0x801: /* VBR */
221 0633879f pbrook
        env->vbr = val;
222 0633879f pbrook
        break;
223 0633879f pbrook
    /* TODO: Implement control registers.  */
224 0633879f pbrook
    default:
225 0633879f pbrook
        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
226 0633879f pbrook
                  reg, val);
227 0633879f pbrook
    }
228 0633879f pbrook
}
229 0633879f pbrook
230 0633879f pbrook
/* MMU */
231 0633879f pbrook
232 0633879f pbrook
/* TODO: This will need fixing once the MMU is implemented.  */
233 0633879f pbrook
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
234 0633879f pbrook
{
235 0633879f pbrook
    return addr;
236 0633879f pbrook
}
237 0633879f pbrook
238 0633879f pbrook
#if defined(CONFIG_USER_ONLY) 
239 0633879f pbrook
240 0633879f pbrook
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
241 0633879f pbrook
                               int is_user, int is_softmmu)
242 0633879f pbrook
{
243 0633879f pbrook
    env->exception_index = EXCP_ACCESS;
244 0633879f pbrook
    env->mmu.ar = address;
245 0633879f pbrook
    return 1;
246 0633879f pbrook
}
247 0633879f pbrook
248 0633879f pbrook
#else
249 0633879f pbrook
250 0633879f pbrook
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
251 0633879f pbrook
                               int is_user, int is_softmmu)
252 0633879f pbrook
{
253 0633879f pbrook
    int prot;
254 0633879f pbrook
255 0633879f pbrook
    address &= TARGET_PAGE_MASK;
256 0633879f pbrook
    prot = PAGE_READ | PAGE_WRITE;
257 0633879f pbrook
    return tlb_set_page(env, address, address, prot, is_user, is_softmmu);
258 0633879f pbrook
}
259 0633879f pbrook
260 0633879f pbrook
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
261 0633879f pbrook
   be handled by the interrupt controller.  Real hardware only requests
262 0633879f pbrook
   the vector when the interrupt is acknowledged by the CPU.  For
263 0633879f pbrook
   simplicitly we calculate it when the interrupt is signalled.  */
264 0633879f pbrook
void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
265 0633879f pbrook
{
266 0633879f pbrook
    env->pending_level = level;
267 0633879f pbrook
    env->pending_vector = vector;
268 0633879f pbrook
    if (level)
269 0633879f pbrook
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
270 0633879f pbrook
    else
271 0633879f pbrook
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
272 0633879f pbrook
}
273 0633879f pbrook
274 0633879f pbrook
#endif