Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ a88790a1

History | View | Annotate | Download (22.7 kB)

1 e6e5906b pbrook
/*
2 e6e5906b pbrook
 *  m68k op helpers
3 5fafdf24 ths
 *
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 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 e6e5906b pbrook
 */
20 e6e5906b pbrook
21 e6e5906b pbrook
#include <stdio.h>
22 0402f767 pbrook
#include <string.h>
23 e6e5906b pbrook
24 e6e5906b pbrook
#include "config.h"
25 e6e5906b pbrook
#include "cpu.h"
26 e6e5906b pbrook
#include "exec-all.h"
27 ca10f867 aurel32
#include "qemu-common.h"
28 56aebc89 pbrook
#include "gdbstub.h"
29 e6e5906b pbrook
30 e1f3808e pbrook
#include "helpers.h"
31 e1f3808e pbrook
32 e1f3808e pbrook
#define SIGNBIT (1u << 31)
33 e1f3808e pbrook
34 0402f767 pbrook
enum m68k_cpuid {
35 0402f767 pbrook
    M68K_CPUID_M5206,
36 20dcee94 pbrook
    M68K_CPUID_M5208,
37 0402f767 pbrook
    M68K_CPUID_CFV4E,
38 0402f767 pbrook
    M68K_CPUID_ANY,
39 0402f767 pbrook
};
40 0402f767 pbrook
41 c227f099 Anthony Liguori
typedef struct m68k_def_t m68k_def_t;
42 aaed909a bellard
43 c227f099 Anthony Liguori
struct m68k_def_t {
44 0402f767 pbrook
    const char * name;
45 0402f767 pbrook
    enum m68k_cpuid id;
46 0402f767 pbrook
};
47 0402f767 pbrook
48 c227f099 Anthony Liguori
static m68k_def_t m68k_cpu_defs[] = {
49 5fafdf24 ths
    {"m5206", M68K_CPUID_M5206},
50 5fafdf24 ths
    {"m5208", M68K_CPUID_M5208},
51 0402f767 pbrook
    {"cfv4e", M68K_CPUID_CFV4E},
52 0402f767 pbrook
    {"any", M68K_CPUID_ANY},
53 5fafdf24 ths
    {NULL, 0},
54 0402f767 pbrook
};
55 0402f767 pbrook
56 009a4356 Laurent Vivier
void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
57 009a4356 Laurent Vivier
{
58 009a4356 Laurent Vivier
    unsigned int i;
59 009a4356 Laurent Vivier
60 009a4356 Laurent Vivier
    for (i = 0; m68k_cpu_defs[i].name; i++) {
61 009a4356 Laurent Vivier
        (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
62 009a4356 Laurent Vivier
    }
63 009a4356 Laurent Vivier
}
64 009a4356 Laurent Vivier
65 56aebc89 pbrook
static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
66 56aebc89 pbrook
{
67 56aebc89 pbrook
    if (n < 8) {
68 56aebc89 pbrook
        stfq_p(mem_buf, env->fregs[n]);
69 56aebc89 pbrook
        return 8;
70 56aebc89 pbrook
    }
71 56aebc89 pbrook
    if (n < 11) {
72 56aebc89 pbrook
        /* FP control registers (not implemented)  */
73 56aebc89 pbrook
        memset(mem_buf, 0, 4);
74 56aebc89 pbrook
        return 4;
75 56aebc89 pbrook
    }
76 56aebc89 pbrook
    return 0;
77 56aebc89 pbrook
}
78 56aebc89 pbrook
79 56aebc89 pbrook
static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
80 56aebc89 pbrook
{
81 56aebc89 pbrook
    if (n < 8) {
82 56aebc89 pbrook
        env->fregs[n] = ldfq_p(mem_buf);
83 56aebc89 pbrook
        return 8;
84 56aebc89 pbrook
    }
85 56aebc89 pbrook
    if (n < 11) {
86 56aebc89 pbrook
        /* FP control registers (not implemented)  */
87 56aebc89 pbrook
        return 4;
88 56aebc89 pbrook
    }
89 56aebc89 pbrook
    return 0;
90 56aebc89 pbrook
}
91 56aebc89 pbrook
92 0402f767 pbrook
static void m68k_set_feature(CPUM68KState *env, int feature)
93 0402f767 pbrook
{
94 0402f767 pbrook
    env->features |= (1u << feature);
95 0402f767 pbrook
}
96 0402f767 pbrook
97 aaed909a bellard
static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
98 0402f767 pbrook
{
99 c227f099 Anthony Liguori
    m68k_def_t *def;
100 0402f767 pbrook
101 0402f767 pbrook
    for (def = m68k_cpu_defs; def->name; def++) {
102 0402f767 pbrook
        if (strcmp(def->name, name) == 0)
103 0402f767 pbrook
            break;
104 0402f767 pbrook
    }
105 0402f767 pbrook
    if (!def->name)
106 aaed909a bellard
        return -1;
107 0402f767 pbrook
108 0402f767 pbrook
    switch (def->id) {
109 0402f767 pbrook
    case M68K_CPUID_M5206:
110 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
111 0402f767 pbrook
        break;
112 20dcee94 pbrook
    case M68K_CPUID_M5208:
113 20dcee94 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
114 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
115 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_BRAL);
116 20dcee94 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117 20dcee94 pbrook
        m68k_set_feature(env, M68K_FEATURE_USP);
118 20dcee94 pbrook
        break;
119 0402f767 pbrook
    case M68K_CPUID_CFV4E:
120 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
121 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
122 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_BRAL);
123 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
124 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
125 20dcee94 pbrook
        m68k_set_feature(env, M68K_FEATURE_USP);
126 0402f767 pbrook
        break;
127 0402f767 pbrook
    case M68K_CPUID_ANY:
128 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
129 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
130 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
131 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_BRAL);
132 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
133 acf930aa pbrook
        /* MAC and EMAC are mututally exclusive, so pick EMAC.
134 acf930aa pbrook
           It's mostly backwards compatible.  */
135 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
136 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
137 20dcee94 pbrook
        m68k_set_feature(env, M68K_FEATURE_USP);
138 0402f767 pbrook
        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
139 d315c888 pbrook
        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
140 0402f767 pbrook
        break;
141 0402f767 pbrook
    }
142 0402f767 pbrook
143 0402f767 pbrook
    register_m68k_insns(env);
144 56aebc89 pbrook
    if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
145 56aebc89 pbrook
        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
146 56aebc89 pbrook
                                 11, "cf-fp.xml", 18);
147 56aebc89 pbrook
    }
148 56aebc89 pbrook
    /* TODO: Add [E]MAC registers.  */
149 4f6cf9e8 bellard
    return 0;
150 aaed909a bellard
}
151 aaed909a bellard
152 aaed909a bellard
void cpu_reset(CPUM68KState *env)
153 aaed909a bellard
{
154 eca1bdf4 aliguori
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
155 eca1bdf4 aliguori
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
156 eca1bdf4 aliguori
        log_cpu_state(env, 0);
157 eca1bdf4 aliguori
    }
158 eca1bdf4 aliguori
159 aaed909a bellard
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
160 aaed909a bellard
#if !defined (CONFIG_USER_ONLY)
161 aaed909a bellard
    env->sr = 0x2700;
162 aaed909a bellard
#endif
163 aaed909a bellard
    m68k_switch_sp(env);
164 aaed909a bellard
    /* ??? FP regs should be initialized to NaN.  */
165 aaed909a bellard
    env->cc_op = CC_OP_FLAGS;
166 aaed909a bellard
    /* TODO: We should set PC from the interrupt vector.  */
167 aaed909a bellard
    env->pc = 0;
168 aaed909a bellard
    tlb_flush(env, 1);
169 aaed909a bellard
}
170 aaed909a bellard
171 aaed909a bellard
CPUM68KState *cpu_m68k_init(const char *cpu_model)
172 aaed909a bellard
{
173 aaed909a bellard
    CPUM68KState *env;
174 e1f3808e pbrook
    static int inited;
175 aaed909a bellard
176 6ad1d22b pbrook
    env = qemu_mallocz(sizeof(CPUM68KState));
177 aaed909a bellard
    cpu_exec_init(env);
178 e1f3808e pbrook
    if (!inited) {
179 e1f3808e pbrook
        inited = 1;
180 e1f3808e pbrook
        m68k_tcg_init();
181 e1f3808e pbrook
    }
182 aaed909a bellard
183 01ba9816 ths
    env->cpu_model_str = cpu_model;
184 01ba9816 ths
185 aaed909a bellard
    if (cpu_m68k_set_model(env, cpu_model) < 0) {
186 aaed909a bellard
        cpu_m68k_close(env);
187 aaed909a bellard
        return NULL;
188 aaed909a bellard
    }
189 01ba9816 ths
190 aaed909a bellard
    cpu_reset(env);
191 0bf46a40 aliguori
    qemu_init_vcpu(env);
192 aaed909a bellard
    return env;
193 aaed909a bellard
}
194 0402f767 pbrook
195 aaed909a bellard
void cpu_m68k_close(CPUM68KState *env)
196 aaed909a bellard
{
197 aaed909a bellard
    qemu_free(env);
198 0402f767 pbrook
}
199 0402f767 pbrook
200 e6e5906b pbrook
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
201 e6e5906b pbrook
{
202 e6e5906b pbrook
    int flags;
203 e6e5906b pbrook
    uint32_t src;
204 e6e5906b pbrook
    uint32_t dest;
205 e6e5906b pbrook
    uint32_t tmp;
206 e6e5906b pbrook
207 e6e5906b pbrook
#define HIGHBIT 0x80000000u
208 e6e5906b pbrook
209 e6e5906b pbrook
#define SET_NZ(x) do { \
210 e6e5906b pbrook
    if ((x) == 0) \
211 e6e5906b pbrook
        flags |= CCF_Z; \
212 e6e5906b pbrook
    else if ((int32_t)(x) < 0) \
213 e6e5906b pbrook
        flags |= CCF_N; \
214 e6e5906b pbrook
    } while (0)
215 e6e5906b pbrook
216 e6e5906b pbrook
#define SET_FLAGS_SUB(type, utype) do { \
217 e6e5906b pbrook
    SET_NZ((type)dest); \
218 e6e5906b pbrook
    tmp = dest + src; \
219 e6e5906b pbrook
    if ((utype) tmp < (utype) src) \
220 e6e5906b pbrook
        flags |= CCF_C; \
221 e6e5906b pbrook
    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
222 e6e5906b pbrook
        flags |= CCF_V; \
223 e6e5906b pbrook
    } while (0)
224 e6e5906b pbrook
225 e6e5906b pbrook
    flags = 0;
226 e6e5906b pbrook
    src = env->cc_src;
227 e6e5906b pbrook
    dest = env->cc_dest;
228 e6e5906b pbrook
    switch (cc_op) {
229 e6e5906b pbrook
    case CC_OP_FLAGS:
230 e6e5906b pbrook
        flags = dest;
231 e6e5906b pbrook
        break;
232 e6e5906b pbrook
    case CC_OP_LOGIC:
233 e6e5906b pbrook
        SET_NZ(dest);
234 e6e5906b pbrook
        break;
235 e6e5906b pbrook
    case CC_OP_ADD:
236 e6e5906b pbrook
        SET_NZ(dest);
237 e6e5906b pbrook
        if (dest < src)
238 e6e5906b pbrook
            flags |= CCF_C;
239 e6e5906b pbrook
        tmp = dest - src;
240 e6e5906b pbrook
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
241 e6e5906b pbrook
            flags |= CCF_V;
242 e6e5906b pbrook
        break;
243 e6e5906b pbrook
    case CC_OP_SUB:
244 e6e5906b pbrook
        SET_FLAGS_SUB(int32_t, uint32_t);
245 e6e5906b pbrook
        break;
246 e6e5906b pbrook
    case CC_OP_CMPB:
247 e6e5906b pbrook
        SET_FLAGS_SUB(int8_t, uint8_t);
248 e6e5906b pbrook
        break;
249 e6e5906b pbrook
    case CC_OP_CMPW:
250 e6e5906b pbrook
        SET_FLAGS_SUB(int16_t, uint16_t);
251 e6e5906b pbrook
        break;
252 e6e5906b pbrook
    case CC_OP_ADDX:
253 e6e5906b pbrook
        SET_NZ(dest);
254 e6e5906b pbrook
        if (dest <= src)
255 e6e5906b pbrook
            flags |= CCF_C;
256 e6e5906b pbrook
        tmp = dest - src - 1;
257 e6e5906b pbrook
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
258 e6e5906b pbrook
            flags |= CCF_V;
259 e6e5906b pbrook
        break;
260 e6e5906b pbrook
    case CC_OP_SUBX:
261 e6e5906b pbrook
        SET_NZ(dest);
262 e6e5906b pbrook
        tmp = dest + src + 1;
263 e6e5906b pbrook
        if (tmp <= src)
264 e6e5906b pbrook
            flags |= CCF_C;
265 e6e5906b pbrook
        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
266 e6e5906b pbrook
            flags |= CCF_V;
267 e6e5906b pbrook
        break;
268 e1f3808e pbrook
    case CC_OP_SHIFT:
269 e1f3808e pbrook
        SET_NZ(dest);
270 e1f3808e pbrook
        if (src)
271 e6e5906b pbrook
            flags |= CCF_C;
272 e6e5906b pbrook
        break;
273 e6e5906b pbrook
    default:
274 e6e5906b pbrook
        cpu_abort(env, "Bad CC_OP %d", cc_op);
275 e6e5906b pbrook
    }
276 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
277 e6e5906b pbrook
    env->cc_dest = flags;
278 e6e5906b pbrook
}
279 e6e5906b pbrook
280 e1f3808e pbrook
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
281 0633879f pbrook
{
282 0633879f pbrook
    switch (reg) {
283 0633879f pbrook
    case 0x02: /* CACR */
284 20dcee94 pbrook
        env->cacr = val;
285 20dcee94 pbrook
        m68k_switch_sp(env);
286 20dcee94 pbrook
        break;
287 20dcee94 pbrook
    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
288 20dcee94 pbrook
        /* TODO: Implement Access Control Registers.  */
289 0633879f pbrook
        break;
290 0633879f pbrook
    case 0x801: /* VBR */
291 0633879f pbrook
        env->vbr = val;
292 0633879f pbrook
        break;
293 0633879f pbrook
    /* TODO: Implement control registers.  */
294 0633879f pbrook
    default:
295 0633879f pbrook
        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
296 0633879f pbrook
                  reg, val);
297 0633879f pbrook
    }
298 0633879f pbrook
}
299 0633879f pbrook
300 e1f3808e pbrook
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
301 acf930aa pbrook
{
302 acf930aa pbrook
    uint32_t acc;
303 acf930aa pbrook
    int8_t exthigh;
304 acf930aa pbrook
    uint8_t extlow;
305 acf930aa pbrook
    uint64_t regval;
306 acf930aa pbrook
    int i;
307 acf930aa pbrook
    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
308 acf930aa pbrook
        for (i = 0; i < 4; i++) {
309 acf930aa pbrook
            regval = env->macc[i];
310 acf930aa pbrook
            exthigh = regval >> 40;
311 acf930aa pbrook
            if (env->macsr & MACSR_FI) {
312 acf930aa pbrook
                acc = regval >> 8;
313 acf930aa pbrook
                extlow = regval;
314 acf930aa pbrook
            } else {
315 acf930aa pbrook
                acc = regval;
316 acf930aa pbrook
                extlow = regval >> 32;
317 acf930aa pbrook
            }
318 acf930aa pbrook
            if (env->macsr & MACSR_FI) {
319 acf930aa pbrook
                regval = (((uint64_t)acc) << 8) | extlow;
320 acf930aa pbrook
                regval |= ((int64_t)exthigh) << 40;
321 acf930aa pbrook
            } else if (env->macsr & MACSR_SU) {
322 acf930aa pbrook
                regval = acc | (((int64_t)extlow) << 32);
323 acf930aa pbrook
                regval |= ((int64_t)exthigh) << 40;
324 acf930aa pbrook
            } else {
325 acf930aa pbrook
                regval = acc | (((uint64_t)extlow) << 32);
326 acf930aa pbrook
                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
327 acf930aa pbrook
            }
328 acf930aa pbrook
            env->macc[i] = regval;
329 acf930aa pbrook
        }
330 acf930aa pbrook
    }
331 acf930aa pbrook
    env->macsr = val;
332 acf930aa pbrook
}
333 acf930aa pbrook
334 20dcee94 pbrook
void m68k_switch_sp(CPUM68KState *env)
335 20dcee94 pbrook
{
336 20dcee94 pbrook
    int new_sp;
337 20dcee94 pbrook
338 20dcee94 pbrook
    env->sp[env->current_sp] = env->aregs[7];
339 20dcee94 pbrook
    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
340 20dcee94 pbrook
             ? M68K_SSP : M68K_USP;
341 20dcee94 pbrook
    env->aregs[7] = env->sp[new_sp];
342 20dcee94 pbrook
    env->current_sp = new_sp;
343 20dcee94 pbrook
}
344 20dcee94 pbrook
345 5fafdf24 ths
#if defined(CONFIG_USER_ONLY)
346 0633879f pbrook
347 0633879f pbrook
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
348 6ebbf390 j_mayer
                               int mmu_idx, int is_softmmu)
349 0633879f pbrook
{
350 0633879f pbrook
    env->exception_index = EXCP_ACCESS;
351 0633879f pbrook
    env->mmu.ar = address;
352 0633879f pbrook
    return 1;
353 0633879f pbrook
}
354 0633879f pbrook
355 0633879f pbrook
#else
356 0633879f pbrook
357 4fcc562b Paul Brook
/* MMU */
358 4fcc562b Paul Brook
359 4fcc562b Paul Brook
/* TODO: This will need fixing once the MMU is implemented.  */
360 4fcc562b Paul Brook
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
361 4fcc562b Paul Brook
{
362 4fcc562b Paul Brook
    return addr;
363 4fcc562b Paul Brook
}
364 4fcc562b Paul Brook
365 0633879f pbrook
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
366 6ebbf390 j_mayer
                               int mmu_idx, int is_softmmu)
367 0633879f pbrook
{
368 0633879f pbrook
    int prot;
369 0633879f pbrook
370 0633879f pbrook
    address &= TARGET_PAGE_MASK;
371 d4c430a8 Paul Brook
    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
372 d4c430a8 Paul Brook
    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
373 d4c430a8 Paul Brook
    return 0;
374 0633879f pbrook
}
375 0633879f pbrook
376 0633879f pbrook
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
377 0633879f pbrook
   be handled by the interrupt controller.  Real hardware only requests
378 0633879f pbrook
   the vector when the interrupt is acknowledged by the CPU.  For
379 0633879f pbrook
   simplicitly we calculate it when the interrupt is signalled.  */
380 0633879f pbrook
void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
381 0633879f pbrook
{
382 0633879f pbrook
    env->pending_level = level;
383 0633879f pbrook
    env->pending_vector = vector;
384 0633879f pbrook
    if (level)
385 0633879f pbrook
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
386 0633879f pbrook
    else
387 0633879f pbrook
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
388 0633879f pbrook
}
389 0633879f pbrook
390 0633879f pbrook
#endif
391 e1f3808e pbrook
392 e1f3808e pbrook
uint32_t HELPER(bitrev)(uint32_t x)
393 e1f3808e pbrook
{
394 e1f3808e pbrook
    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
395 e1f3808e pbrook
    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
396 e1f3808e pbrook
    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
397 e1f3808e pbrook
    return bswap32(x);
398 e1f3808e pbrook
}
399 e1f3808e pbrook
400 e1f3808e pbrook
uint32_t HELPER(ff1)(uint32_t x)
401 e1f3808e pbrook
{
402 e1f3808e pbrook
    int n;
403 e1f3808e pbrook
    for (n = 32; x; n--)
404 e1f3808e pbrook
        x >>= 1;
405 e1f3808e pbrook
    return n;
406 e1f3808e pbrook
}
407 e1f3808e pbrook
408 e1f3808e pbrook
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
409 e1f3808e pbrook
{
410 e1f3808e pbrook
    /* The result has the opposite sign to the original value.  */
411 e1f3808e pbrook
    if (ccr & CCF_V)
412 e1f3808e pbrook
        val = (((int32_t)val) >> 31) ^ SIGNBIT;
413 e1f3808e pbrook
    return val;
414 e1f3808e pbrook
}
415 e1f3808e pbrook
416 e1f3808e pbrook
uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
417 e1f3808e pbrook
{
418 e1f3808e pbrook
    uint32_t res;
419 e1f3808e pbrook
    uint32_t old_flags;
420 e1f3808e pbrook
421 e1f3808e pbrook
    old_flags = env->cc_dest;
422 e1f3808e pbrook
    if (env->cc_x) {
423 e1f3808e pbrook
        env->cc_x = (op1 <= op2);
424 e1f3808e pbrook
        env->cc_op = CC_OP_SUBX;
425 e1f3808e pbrook
        res = op1 - (op2 + 1);
426 e1f3808e pbrook
    } else {
427 e1f3808e pbrook
        env->cc_x = (op1 < op2);
428 e1f3808e pbrook
        env->cc_op = CC_OP_SUB;
429 e1f3808e pbrook
        res = op1 - op2;
430 e1f3808e pbrook
    }
431 e1f3808e pbrook
    env->cc_dest = res;
432 e1f3808e pbrook
    env->cc_src = op2;
433 e1f3808e pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
434 e1f3808e pbrook
    /* !Z is sticky.  */
435 e1f3808e pbrook
    env->cc_dest &= (old_flags | ~CCF_Z);
436 e1f3808e pbrook
    return res;
437 e1f3808e pbrook
}
438 e1f3808e pbrook
439 e1f3808e pbrook
uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
440 e1f3808e pbrook
{
441 e1f3808e pbrook
    uint32_t res;
442 e1f3808e pbrook
    uint32_t old_flags;
443 e1f3808e pbrook
444 e1f3808e pbrook
    old_flags = env->cc_dest;
445 e1f3808e pbrook
    if (env->cc_x) {
446 e1f3808e pbrook
        res = op1 + op2 + 1;
447 e1f3808e pbrook
        env->cc_x = (res <= op2);
448 e1f3808e pbrook
        env->cc_op = CC_OP_ADDX;
449 e1f3808e pbrook
    } else {
450 e1f3808e pbrook
        res = op1 + op2;
451 e1f3808e pbrook
        env->cc_x = (res < op2);
452 e1f3808e pbrook
        env->cc_op = CC_OP_ADD;
453 e1f3808e pbrook
    }
454 e1f3808e pbrook
    env->cc_dest = res;
455 e1f3808e pbrook
    env->cc_src = op2;
456 e1f3808e pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
457 e1f3808e pbrook
    /* !Z is sticky.  */
458 e1f3808e pbrook
    env->cc_dest &= (old_flags | ~CCF_Z);
459 e1f3808e pbrook
    return res;
460 e1f3808e pbrook
}
461 e1f3808e pbrook
462 e1f3808e pbrook
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
463 e1f3808e pbrook
{
464 e1f3808e pbrook
    return a < b;
465 e1f3808e pbrook
}
466 e1f3808e pbrook
467 e1f3808e pbrook
void HELPER(set_sr)(CPUState *env, uint32_t val)
468 e1f3808e pbrook
{
469 e1f3808e pbrook
    env->sr = val & 0xffff;
470 e1f3808e pbrook
    m68k_switch_sp(env);
471 e1f3808e pbrook
}
472 e1f3808e pbrook
473 e1f3808e pbrook
uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
474 e1f3808e pbrook
{
475 e1f3808e pbrook
    uint32_t result;
476 e1f3808e pbrook
    uint32_t cf;
477 e1f3808e pbrook
478 e1f3808e pbrook
    shift &= 63;
479 e1f3808e pbrook
    if (shift == 0) {
480 e1f3808e pbrook
        result = val;
481 e1f3808e pbrook
        cf = env->cc_src & CCF_C;
482 e1f3808e pbrook
    } else if (shift < 32) {
483 e1f3808e pbrook
        result = val << shift;
484 e1f3808e pbrook
        cf = (val >> (32 - shift)) & 1;
485 e1f3808e pbrook
    } else if (shift == 32) {
486 e1f3808e pbrook
        result = 0;
487 e1f3808e pbrook
        cf = val & 1;
488 e1f3808e pbrook
    } else /* shift > 32 */ {
489 e1f3808e pbrook
        result = 0;
490 e1f3808e pbrook
        cf = 0;
491 e1f3808e pbrook
    }
492 e1f3808e pbrook
    env->cc_src = cf;
493 e1f3808e pbrook
    env->cc_x = (cf != 0);
494 e1f3808e pbrook
    env->cc_dest = result;
495 e1f3808e pbrook
    return result;
496 e1f3808e pbrook
}
497 e1f3808e pbrook
498 e1f3808e pbrook
uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
499 e1f3808e pbrook
{
500 e1f3808e pbrook
    uint32_t result;
501 e1f3808e pbrook
    uint32_t cf;
502 e1f3808e pbrook
503 e1f3808e pbrook
    shift &= 63;
504 e1f3808e pbrook
    if (shift == 0) {
505 e1f3808e pbrook
        result = val;
506 e1f3808e pbrook
        cf = env->cc_src & CCF_C;
507 e1f3808e pbrook
    } else if (shift < 32) {
508 e1f3808e pbrook
        result = val >> shift;
509 e1f3808e pbrook
        cf = (val >> (shift - 1)) & 1;
510 e1f3808e pbrook
    } else if (shift == 32) {
511 e1f3808e pbrook
        result = 0;
512 e1f3808e pbrook
        cf = val >> 31;
513 e1f3808e pbrook
    } else /* shift > 32 */ {
514 e1f3808e pbrook
        result = 0;
515 e1f3808e pbrook
        cf = 0;
516 e1f3808e pbrook
    }
517 e1f3808e pbrook
    env->cc_src = cf;
518 e1f3808e pbrook
    env->cc_x = (cf != 0);
519 e1f3808e pbrook
    env->cc_dest = result;
520 e1f3808e pbrook
    return result;
521 e1f3808e pbrook
}
522 e1f3808e pbrook
523 e1f3808e pbrook
uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
524 e1f3808e pbrook
{
525 e1f3808e pbrook
    uint32_t result;
526 e1f3808e pbrook
    uint32_t cf;
527 e1f3808e pbrook
528 e1f3808e pbrook
    shift &= 63;
529 e1f3808e pbrook
    if (shift == 0) {
530 e1f3808e pbrook
        result = val;
531 e1f3808e pbrook
        cf = (env->cc_src & CCF_C) != 0;
532 e1f3808e pbrook
    } else if (shift < 32) {
533 e1f3808e pbrook
        result = (int32_t)val >> shift;
534 e1f3808e pbrook
        cf = (val >> (shift - 1)) & 1;
535 e1f3808e pbrook
    } else /* shift >= 32 */ {
536 e1f3808e pbrook
        result = (int32_t)val >> 31;
537 e1f3808e pbrook
        cf = val >> 31;
538 e1f3808e pbrook
    }
539 e1f3808e pbrook
    env->cc_src = cf;
540 e1f3808e pbrook
    env->cc_x = cf;
541 e1f3808e pbrook
    env->cc_dest = result;
542 e1f3808e pbrook
    return result;
543 e1f3808e pbrook
}
544 e1f3808e pbrook
545 e1f3808e pbrook
/* FPU helpers.  */
546 e1f3808e pbrook
uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
547 e1f3808e pbrook
{
548 e1f3808e pbrook
    return float64_to_int32(val, &env->fp_status);
549 e1f3808e pbrook
}
550 e1f3808e pbrook
551 e1f3808e pbrook
float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
552 e1f3808e pbrook
{
553 e1f3808e pbrook
    return float64_to_float32(val, &env->fp_status);
554 e1f3808e pbrook
}
555 e1f3808e pbrook
556 e1f3808e pbrook
float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
557 e1f3808e pbrook
{
558 e1f3808e pbrook
    return int32_to_float64(val, &env->fp_status);
559 e1f3808e pbrook
}
560 e1f3808e pbrook
561 e1f3808e pbrook
float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
562 e1f3808e pbrook
{
563 e1f3808e pbrook
    return float32_to_float64(val, &env->fp_status);
564 e1f3808e pbrook
}
565 e1f3808e pbrook
566 e1f3808e pbrook
float64 HELPER(iround_f64)(CPUState *env, float64 val)
567 e1f3808e pbrook
{
568 e1f3808e pbrook
    return float64_round_to_int(val, &env->fp_status);
569 e1f3808e pbrook
}
570 e1f3808e pbrook
571 e1f3808e pbrook
float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
572 e1f3808e pbrook
{
573 e1f3808e pbrook
    return float64_trunc_to_int(val, &env->fp_status);
574 e1f3808e pbrook
}
575 e1f3808e pbrook
576 e1f3808e pbrook
float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
577 e1f3808e pbrook
{
578 e1f3808e pbrook
    return float64_sqrt(val, &env->fp_status);
579 e1f3808e pbrook
}
580 e1f3808e pbrook
581 e1f3808e pbrook
float64 HELPER(abs_f64)(float64 val)
582 e1f3808e pbrook
{
583 e1f3808e pbrook
    return float64_abs(val);
584 e1f3808e pbrook
}
585 e1f3808e pbrook
586 e1f3808e pbrook
float64 HELPER(chs_f64)(float64 val)
587 e1f3808e pbrook
{
588 e1f3808e pbrook
    return float64_chs(val);
589 e1f3808e pbrook
}
590 e1f3808e pbrook
591 e1f3808e pbrook
float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
592 e1f3808e pbrook
{
593 e1f3808e pbrook
    return float64_add(a, b, &env->fp_status);
594 e1f3808e pbrook
}
595 e1f3808e pbrook
596 e1f3808e pbrook
float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
597 e1f3808e pbrook
{
598 e1f3808e pbrook
    return float64_sub(a, b, &env->fp_status);
599 e1f3808e pbrook
}
600 e1f3808e pbrook
601 e1f3808e pbrook
float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
602 e1f3808e pbrook
{
603 e1f3808e pbrook
    return float64_mul(a, b, &env->fp_status);
604 e1f3808e pbrook
}
605 e1f3808e pbrook
606 e1f3808e pbrook
float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
607 e1f3808e pbrook
{
608 e1f3808e pbrook
    return float64_div(a, b, &env->fp_status);
609 e1f3808e pbrook
}
610 e1f3808e pbrook
611 e1f3808e pbrook
float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
612 e1f3808e pbrook
{
613 e1f3808e pbrook
    /* ??? This may incorrectly raise exceptions.  */
614 e1f3808e pbrook
    /* ??? Should flush denormals to zero.  */
615 e1f3808e pbrook
    float64 res;
616 e1f3808e pbrook
    res = float64_sub(a, b, &env->fp_status);
617 e1f3808e pbrook
    if (float64_is_nan(res)) {
618 e1f3808e pbrook
        /* +/-inf compares equal against itself, but sub returns nan.  */
619 e1f3808e pbrook
        if (!float64_is_nan(a)
620 e1f3808e pbrook
            && !float64_is_nan(b)) {
621 e1f3808e pbrook
            res = float64_zero;
622 e1f3808e pbrook
            if (float64_lt_quiet(a, res, &env->fp_status))
623 e1f3808e pbrook
                res = float64_chs(res);
624 e1f3808e pbrook
        }
625 e1f3808e pbrook
    }
626 e1f3808e pbrook
    return res;
627 e1f3808e pbrook
}
628 e1f3808e pbrook
629 e1f3808e pbrook
uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
630 e1f3808e pbrook
{
631 e1f3808e pbrook
    return float64_compare_quiet(val, float64_zero, &env->fp_status);
632 e1f3808e pbrook
}
633 e1f3808e pbrook
634 e1f3808e pbrook
/* MAC unit.  */
635 e1f3808e pbrook
/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
636 e1f3808e pbrook
   take values,  others take register numbers and manipulate the contents
637 e1f3808e pbrook
   in-place.  */
638 e1f3808e pbrook
void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
639 e1f3808e pbrook
{
640 e1f3808e pbrook
    uint32_t mask;
641 e1f3808e pbrook
    env->macc[dest] = env->macc[src];
642 e1f3808e pbrook
    mask = MACSR_PAV0 << dest;
643 e1f3808e pbrook
    if (env->macsr & (MACSR_PAV0 << src))
644 e1f3808e pbrook
        env->macsr |= mask;
645 e1f3808e pbrook
    else
646 e1f3808e pbrook
        env->macsr &= ~mask;
647 e1f3808e pbrook
}
648 e1f3808e pbrook
649 e1f3808e pbrook
uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
650 e1f3808e pbrook
{
651 e1f3808e pbrook
    int64_t product;
652 e1f3808e pbrook
    int64_t res;
653 e1f3808e pbrook
654 e1f3808e pbrook
    product = (uint64_t)op1 * op2;
655 e1f3808e pbrook
    res = (product << 24) >> 24;
656 e1f3808e pbrook
    if (res != product) {
657 e1f3808e pbrook
        env->macsr |= MACSR_V;
658 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
659 e1f3808e pbrook
            /* Make sure the accumulate operation overflows.  */
660 e1f3808e pbrook
            if (product < 0)
661 e1f3808e pbrook
                res = ~(1ll << 50);
662 e1f3808e pbrook
            else
663 e1f3808e pbrook
                res = 1ll << 50;
664 e1f3808e pbrook
        }
665 e1f3808e pbrook
    }
666 e1f3808e pbrook
    return res;
667 e1f3808e pbrook
}
668 e1f3808e pbrook
669 e1f3808e pbrook
uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
670 e1f3808e pbrook
{
671 e1f3808e pbrook
    uint64_t product;
672 e1f3808e pbrook
673 e1f3808e pbrook
    product = (uint64_t)op1 * op2;
674 e1f3808e pbrook
    if (product & (0xffffffull << 40)) {
675 e1f3808e pbrook
        env->macsr |= MACSR_V;
676 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
677 e1f3808e pbrook
            /* Make sure the accumulate operation overflows.  */
678 e1f3808e pbrook
            product = 1ll << 50;
679 e1f3808e pbrook
        } else {
680 e1f3808e pbrook
            product &= ((1ull << 40) - 1);
681 e1f3808e pbrook
        }
682 e1f3808e pbrook
    }
683 e1f3808e pbrook
    return product;
684 e1f3808e pbrook
}
685 e1f3808e pbrook
686 e1f3808e pbrook
uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
687 e1f3808e pbrook
{
688 e1f3808e pbrook
    uint64_t product;
689 e1f3808e pbrook
    uint32_t remainder;
690 e1f3808e pbrook
691 e1f3808e pbrook
    product = (uint64_t)op1 * op2;
692 e1f3808e pbrook
    if (env->macsr & MACSR_RT) {
693 e1f3808e pbrook
        remainder = product & 0xffffff;
694 e1f3808e pbrook
        product >>= 24;
695 e1f3808e pbrook
        if (remainder > 0x800000)
696 e1f3808e pbrook
            product++;
697 e1f3808e pbrook
        else if (remainder == 0x800000)
698 e1f3808e pbrook
            product += (product & 1);
699 e1f3808e pbrook
    } else {
700 e1f3808e pbrook
        product >>= 24;
701 e1f3808e pbrook
    }
702 e1f3808e pbrook
    return product;
703 e1f3808e pbrook
}
704 e1f3808e pbrook
705 e1f3808e pbrook
void HELPER(macsats)(CPUState *env, uint32_t acc)
706 e1f3808e pbrook
{
707 e1f3808e pbrook
    int64_t tmp;
708 e1f3808e pbrook
    int64_t result;
709 e1f3808e pbrook
    tmp = env->macc[acc];
710 e1f3808e pbrook
    result = ((tmp << 16) >> 16);
711 e1f3808e pbrook
    if (result != tmp) {
712 e1f3808e pbrook
        env->macsr |= MACSR_V;
713 e1f3808e pbrook
    }
714 e1f3808e pbrook
    if (env->macsr & MACSR_V) {
715 e1f3808e pbrook
        env->macsr |= MACSR_PAV0 << acc;
716 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
717 e1f3808e pbrook
            /* The result is saturated to 32 bits, despite overflow occuring
718 e1f3808e pbrook
               at 48 bits.  Seems weird, but that's what the hardware docs
719 e1f3808e pbrook
               say.  */
720 e1f3808e pbrook
            result = (result >> 63) ^ 0x7fffffff;
721 e1f3808e pbrook
        }
722 e1f3808e pbrook
    }
723 e1f3808e pbrook
    env->macc[acc] = result;
724 e1f3808e pbrook
}
725 e1f3808e pbrook
726 e1f3808e pbrook
void HELPER(macsatu)(CPUState *env, uint32_t acc)
727 e1f3808e pbrook
{
728 e1f3808e pbrook
    uint64_t val;
729 e1f3808e pbrook
730 e1f3808e pbrook
    val = env->macc[acc];
731 e1f3808e pbrook
    if (val & (0xffffull << 48)) {
732 e1f3808e pbrook
        env->macsr |= MACSR_V;
733 e1f3808e pbrook
    }
734 e1f3808e pbrook
    if (env->macsr & MACSR_V) {
735 e1f3808e pbrook
        env->macsr |= MACSR_PAV0 << acc;
736 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
737 e1f3808e pbrook
            if (val > (1ull << 53))
738 e1f3808e pbrook
                val = 0;
739 e1f3808e pbrook
            else
740 e1f3808e pbrook
                val = (1ull << 48) - 1;
741 e1f3808e pbrook
        } else {
742 e1f3808e pbrook
            val &= ((1ull << 48) - 1);
743 e1f3808e pbrook
        }
744 e1f3808e pbrook
    }
745 e1f3808e pbrook
    env->macc[acc] = val;
746 e1f3808e pbrook
}
747 e1f3808e pbrook
748 e1f3808e pbrook
void HELPER(macsatf)(CPUState *env, uint32_t acc)
749 e1f3808e pbrook
{
750 e1f3808e pbrook
    int64_t sum;
751 e1f3808e pbrook
    int64_t result;
752 e1f3808e pbrook
753 e1f3808e pbrook
    sum = env->macc[acc];
754 e1f3808e pbrook
    result = (sum << 16) >> 16;
755 e1f3808e pbrook
    if (result != sum) {
756 e1f3808e pbrook
        env->macsr |= MACSR_V;
757 e1f3808e pbrook
    }
758 e1f3808e pbrook
    if (env->macsr & MACSR_V) {
759 e1f3808e pbrook
        env->macsr |= MACSR_PAV0 << acc;
760 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
761 e1f3808e pbrook
            result = (result >> 63) ^ 0x7fffffffffffll;
762 e1f3808e pbrook
        }
763 e1f3808e pbrook
    }
764 e1f3808e pbrook
    env->macc[acc] = result;
765 e1f3808e pbrook
}
766 e1f3808e pbrook
767 e1f3808e pbrook
void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
768 e1f3808e pbrook
{
769 e1f3808e pbrook
    uint64_t val;
770 e1f3808e pbrook
    val = env->macc[acc];
771 c4162574 Blue Swirl
    if (val == 0) {
772 e1f3808e pbrook
        env->macsr |= MACSR_Z;
773 c4162574 Blue Swirl
    } else if (val & (1ull << 47)) {
774 e1f3808e pbrook
        env->macsr |= MACSR_N;
775 c4162574 Blue Swirl
    }
776 e1f3808e pbrook
    if (env->macsr & (MACSR_PAV0 << acc)) {
777 e1f3808e pbrook
        env->macsr |= MACSR_V;
778 e1f3808e pbrook
    }
779 e1f3808e pbrook
    if (env->macsr & MACSR_FI) {
780 e1f3808e pbrook
        val = ((int64_t)val) >> 40;
781 e1f3808e pbrook
        if (val != 0 && val != -1)
782 e1f3808e pbrook
            env->macsr |= MACSR_EV;
783 e1f3808e pbrook
    } else if (env->macsr & MACSR_SU) {
784 e1f3808e pbrook
        val = ((int64_t)val) >> 32;
785 e1f3808e pbrook
        if (val != 0 && val != -1)
786 e1f3808e pbrook
            env->macsr |= MACSR_EV;
787 e1f3808e pbrook
    } else {
788 e1f3808e pbrook
        if ((val >> 32) != 0)
789 e1f3808e pbrook
            env->macsr |= MACSR_EV;
790 e1f3808e pbrook
    }
791 e1f3808e pbrook
}
792 e1f3808e pbrook
793 e1f3808e pbrook
void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
794 e1f3808e pbrook
{
795 e1f3808e pbrook
    cpu_m68k_flush_flags(env, cc_op);
796 e1f3808e pbrook
}
797 e1f3808e pbrook
798 e1f3808e pbrook
uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
799 e1f3808e pbrook
{
800 e1f3808e pbrook
    int rem;
801 e1f3808e pbrook
    uint32_t result;
802 e1f3808e pbrook
803 e1f3808e pbrook
    if (env->macsr & MACSR_SU) {
804 e1f3808e pbrook
        /* 16-bit rounding.  */
805 e1f3808e pbrook
        rem = val & 0xffffff;
806 e1f3808e pbrook
        val = (val >> 24) & 0xffffu;
807 e1f3808e pbrook
        if (rem > 0x800000)
808 e1f3808e pbrook
            val++;
809 e1f3808e pbrook
        else if (rem == 0x800000)
810 e1f3808e pbrook
            val += (val & 1);
811 e1f3808e pbrook
    } else if (env->macsr & MACSR_RT) {
812 e1f3808e pbrook
        /* 32-bit rounding.  */
813 e1f3808e pbrook
        rem = val & 0xff;
814 e1f3808e pbrook
        val >>= 8;
815 e1f3808e pbrook
        if (rem > 0x80)
816 e1f3808e pbrook
            val++;
817 e1f3808e pbrook
        else if (rem == 0x80)
818 e1f3808e pbrook
            val += (val & 1);
819 e1f3808e pbrook
    } else {
820 e1f3808e pbrook
        /* No rounding.  */
821 e1f3808e pbrook
        val >>= 8;
822 e1f3808e pbrook
    }
823 e1f3808e pbrook
    if (env->macsr & MACSR_OMC) {
824 e1f3808e pbrook
        /* Saturate.  */
825 e1f3808e pbrook
        if (env->macsr & MACSR_SU) {
826 e1f3808e pbrook
            if (val != (uint16_t) val) {
827 e1f3808e pbrook
                result = ((val >> 63) ^ 0x7fff) & 0xffff;
828 e1f3808e pbrook
            } else {
829 e1f3808e pbrook
                result = val & 0xffff;
830 e1f3808e pbrook
            }
831 e1f3808e pbrook
        } else {
832 e1f3808e pbrook
            if (val != (uint32_t)val) {
833 e1f3808e pbrook
                result = ((uint32_t)(val >> 63) & 0x7fffffff);
834 e1f3808e pbrook
            } else {
835 e1f3808e pbrook
                result = (uint32_t)val;
836 e1f3808e pbrook
            }
837 e1f3808e pbrook
        }
838 e1f3808e pbrook
    } else {
839 e1f3808e pbrook
        /* No saturation.  */
840 e1f3808e pbrook
        if (env->macsr & MACSR_SU) {
841 e1f3808e pbrook
            result = val & 0xffff;
842 e1f3808e pbrook
        } else {
843 e1f3808e pbrook
            result = (uint32_t)val;
844 e1f3808e pbrook
        }
845 e1f3808e pbrook
    }
846 e1f3808e pbrook
    return result;
847 e1f3808e pbrook
}
848 e1f3808e pbrook
849 e1f3808e pbrook
uint32_t HELPER(get_macs)(uint64_t val)
850 e1f3808e pbrook
{
851 e1f3808e pbrook
    if (val == (int32_t)val) {
852 e1f3808e pbrook
        return (int32_t)val;
853 e1f3808e pbrook
    } else {
854 e1f3808e pbrook
        return (val >> 61) ^ ~SIGNBIT;
855 e1f3808e pbrook
    }
856 e1f3808e pbrook
}
857 e1f3808e pbrook
858 e1f3808e pbrook
uint32_t HELPER(get_macu)(uint64_t val)
859 e1f3808e pbrook
{
860 e1f3808e pbrook
    if ((val >> 32) == 0) {
861 e1f3808e pbrook
        return (uint32_t)val;
862 e1f3808e pbrook
    } else {
863 e1f3808e pbrook
        return 0xffffffffu;
864 e1f3808e pbrook
    }
865 e1f3808e pbrook
}
866 e1f3808e pbrook
867 e1f3808e pbrook
uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
868 e1f3808e pbrook
{
869 e1f3808e pbrook
    uint32_t val;
870 e1f3808e pbrook
    val = env->macc[acc] & 0x00ff;
871 e1f3808e pbrook
    val = (env->macc[acc] >> 32) & 0xff00;
872 e1f3808e pbrook
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
873 e1f3808e pbrook
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
874 e1f3808e pbrook
    return val;
875 e1f3808e pbrook
}
876 e1f3808e pbrook
877 e1f3808e pbrook
uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
878 e1f3808e pbrook
{
879 e1f3808e pbrook
    uint32_t val;
880 e1f3808e pbrook
    val = (env->macc[acc] >> 32) & 0xffff;
881 e1f3808e pbrook
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
882 e1f3808e pbrook
    return val;
883 e1f3808e pbrook
}
884 e1f3808e pbrook
885 e1f3808e pbrook
void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
886 e1f3808e pbrook
{
887 e1f3808e pbrook
    int64_t res;
888 e1f3808e pbrook
    int32_t tmp;
889 e1f3808e pbrook
    res = env->macc[acc] & 0xffffffff00ull;
890 e1f3808e pbrook
    tmp = (int16_t)(val & 0xff00);
891 e1f3808e pbrook
    res |= ((int64_t)tmp) << 32;
892 e1f3808e pbrook
    res |= val & 0xff;
893 e1f3808e pbrook
    env->macc[acc] = res;
894 e1f3808e pbrook
    res = env->macc[acc + 1] & 0xffffffff00ull;
895 e1f3808e pbrook
    tmp = (val & 0xff000000);
896 e1f3808e pbrook
    res |= ((int64_t)tmp) << 16;
897 e1f3808e pbrook
    res |= (val >> 16) & 0xff;
898 e1f3808e pbrook
    env->macc[acc + 1] = res;
899 e1f3808e pbrook
}
900 e1f3808e pbrook
901 e1f3808e pbrook
void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
902 e1f3808e pbrook
{
903 e1f3808e pbrook
    int64_t res;
904 e1f3808e pbrook
    int32_t tmp;
905 e1f3808e pbrook
    res = (uint32_t)env->macc[acc];
906 e1f3808e pbrook
    tmp = (int16_t)val;
907 e1f3808e pbrook
    res |= ((int64_t)tmp) << 32;
908 e1f3808e pbrook
    env->macc[acc] = res;
909 e1f3808e pbrook
    res = (uint32_t)env->macc[acc + 1];
910 e1f3808e pbrook
    tmp = val & 0xffff0000;
911 e1f3808e pbrook
    res |= (int64_t)tmp << 16;
912 e1f3808e pbrook
    env->macc[acc + 1] = res;
913 e1f3808e pbrook
}
914 e1f3808e pbrook
915 e1f3808e pbrook
void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
916 e1f3808e pbrook
{
917 e1f3808e pbrook
    uint64_t res;
918 e1f3808e pbrook
    res = (uint32_t)env->macc[acc];
919 e1f3808e pbrook
    res |= ((uint64_t)(val & 0xffff)) << 32;
920 e1f3808e pbrook
    env->macc[acc] = res;
921 e1f3808e pbrook
    res = (uint32_t)env->macc[acc + 1];
922 e1f3808e pbrook
    res |= (uint64_t)(val & 0xffff0000) << 16;
923 e1f3808e pbrook
    env->macc[acc + 1] = res;
924 e1f3808e pbrook
}