Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ 4fcc562b

History | View | Annotate | Download (22.6 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 0633879f pbrook
    prot = PAGE_READ | PAGE_WRITE;
372 6ebbf390 j_mayer
    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
373 0633879f pbrook
}
374 0633879f pbrook
375 0633879f pbrook
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
376 0633879f pbrook
   be handled by the interrupt controller.  Real hardware only requests
377 0633879f pbrook
   the vector when the interrupt is acknowledged by the CPU.  For
378 0633879f pbrook
   simplicitly we calculate it when the interrupt is signalled.  */
379 0633879f pbrook
void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
380 0633879f pbrook
{
381 0633879f pbrook
    env->pending_level = level;
382 0633879f pbrook
    env->pending_vector = vector;
383 0633879f pbrook
    if (level)
384 0633879f pbrook
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
385 0633879f pbrook
    else
386 0633879f pbrook
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
387 0633879f pbrook
}
388 0633879f pbrook
389 0633879f pbrook
#endif
390 e1f3808e pbrook
391 e1f3808e pbrook
uint32_t HELPER(bitrev)(uint32_t x)
392 e1f3808e pbrook
{
393 e1f3808e pbrook
    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
394 e1f3808e pbrook
    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
395 e1f3808e pbrook
    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
396 e1f3808e pbrook
    return bswap32(x);
397 e1f3808e pbrook
}
398 e1f3808e pbrook
399 e1f3808e pbrook
uint32_t HELPER(ff1)(uint32_t x)
400 e1f3808e pbrook
{
401 e1f3808e pbrook
    int n;
402 e1f3808e pbrook
    for (n = 32; x; n--)
403 e1f3808e pbrook
        x >>= 1;
404 e1f3808e pbrook
    return n;
405 e1f3808e pbrook
}
406 e1f3808e pbrook
407 e1f3808e pbrook
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
408 e1f3808e pbrook
{
409 e1f3808e pbrook
    /* The result has the opposite sign to the original value.  */
410 e1f3808e pbrook
    if (ccr & CCF_V)
411 e1f3808e pbrook
        val = (((int32_t)val) >> 31) ^ SIGNBIT;
412 e1f3808e pbrook
    return val;
413 e1f3808e pbrook
}
414 e1f3808e pbrook
415 e1f3808e pbrook
uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
416 e1f3808e pbrook
{
417 e1f3808e pbrook
    uint32_t res;
418 e1f3808e pbrook
    uint32_t old_flags;
419 e1f3808e pbrook
420 e1f3808e pbrook
    old_flags = env->cc_dest;
421 e1f3808e pbrook
    if (env->cc_x) {
422 e1f3808e pbrook
        env->cc_x = (op1 <= op2);
423 e1f3808e pbrook
        env->cc_op = CC_OP_SUBX;
424 e1f3808e pbrook
        res = op1 - (op2 + 1);
425 e1f3808e pbrook
    } else {
426 e1f3808e pbrook
        env->cc_x = (op1 < op2);
427 e1f3808e pbrook
        env->cc_op = CC_OP_SUB;
428 e1f3808e pbrook
        res = op1 - op2;
429 e1f3808e pbrook
    }
430 e1f3808e pbrook
    env->cc_dest = res;
431 e1f3808e pbrook
    env->cc_src = op2;
432 e1f3808e pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
433 e1f3808e pbrook
    /* !Z is sticky.  */
434 e1f3808e pbrook
    env->cc_dest &= (old_flags | ~CCF_Z);
435 e1f3808e pbrook
    return res;
436 e1f3808e pbrook
}
437 e1f3808e pbrook
438 e1f3808e pbrook
uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
439 e1f3808e pbrook
{
440 e1f3808e pbrook
    uint32_t res;
441 e1f3808e pbrook
    uint32_t old_flags;
442 e1f3808e pbrook
443 e1f3808e pbrook
    old_flags = env->cc_dest;
444 e1f3808e pbrook
    if (env->cc_x) {
445 e1f3808e pbrook
        res = op1 + op2 + 1;
446 e1f3808e pbrook
        env->cc_x = (res <= op2);
447 e1f3808e pbrook
        env->cc_op = CC_OP_ADDX;
448 e1f3808e pbrook
    } else {
449 e1f3808e pbrook
        res = op1 + op2;
450 e1f3808e pbrook
        env->cc_x = (res < op2);
451 e1f3808e pbrook
        env->cc_op = CC_OP_ADD;
452 e1f3808e pbrook
    }
453 e1f3808e pbrook
    env->cc_dest = res;
454 e1f3808e pbrook
    env->cc_src = op2;
455 e1f3808e pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
456 e1f3808e pbrook
    /* !Z is sticky.  */
457 e1f3808e pbrook
    env->cc_dest &= (old_flags | ~CCF_Z);
458 e1f3808e pbrook
    return res;
459 e1f3808e pbrook
}
460 e1f3808e pbrook
461 e1f3808e pbrook
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
462 e1f3808e pbrook
{
463 e1f3808e pbrook
    return a < b;
464 e1f3808e pbrook
}
465 e1f3808e pbrook
466 e1f3808e pbrook
void HELPER(set_sr)(CPUState *env, uint32_t val)
467 e1f3808e pbrook
{
468 e1f3808e pbrook
    env->sr = val & 0xffff;
469 e1f3808e pbrook
    m68k_switch_sp(env);
470 e1f3808e pbrook
}
471 e1f3808e pbrook
472 e1f3808e pbrook
uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
473 e1f3808e pbrook
{
474 e1f3808e pbrook
    uint32_t result;
475 e1f3808e pbrook
    uint32_t cf;
476 e1f3808e pbrook
477 e1f3808e pbrook
    shift &= 63;
478 e1f3808e pbrook
    if (shift == 0) {
479 e1f3808e pbrook
        result = val;
480 e1f3808e pbrook
        cf = env->cc_src & CCF_C;
481 e1f3808e pbrook
    } else if (shift < 32) {
482 e1f3808e pbrook
        result = val << shift;
483 e1f3808e pbrook
        cf = (val >> (32 - shift)) & 1;
484 e1f3808e pbrook
    } else if (shift == 32) {
485 e1f3808e pbrook
        result = 0;
486 e1f3808e pbrook
        cf = val & 1;
487 e1f3808e pbrook
    } else /* shift > 32 */ {
488 e1f3808e pbrook
        result = 0;
489 e1f3808e pbrook
        cf = 0;
490 e1f3808e pbrook
    }
491 e1f3808e pbrook
    env->cc_src = cf;
492 e1f3808e pbrook
    env->cc_x = (cf != 0);
493 e1f3808e pbrook
    env->cc_dest = result;
494 e1f3808e pbrook
    return result;
495 e1f3808e pbrook
}
496 e1f3808e pbrook
497 e1f3808e pbrook
uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
498 e1f3808e pbrook
{
499 e1f3808e pbrook
    uint32_t result;
500 e1f3808e pbrook
    uint32_t cf;
501 e1f3808e pbrook
502 e1f3808e pbrook
    shift &= 63;
503 e1f3808e pbrook
    if (shift == 0) {
504 e1f3808e pbrook
        result = val;
505 e1f3808e pbrook
        cf = env->cc_src & CCF_C;
506 e1f3808e pbrook
    } else if (shift < 32) {
507 e1f3808e pbrook
        result = val >> shift;
508 e1f3808e pbrook
        cf = (val >> (shift - 1)) & 1;
509 e1f3808e pbrook
    } else if (shift == 32) {
510 e1f3808e pbrook
        result = 0;
511 e1f3808e pbrook
        cf = val >> 31;
512 e1f3808e pbrook
    } else /* shift > 32 */ {
513 e1f3808e pbrook
        result = 0;
514 e1f3808e pbrook
        cf = 0;
515 e1f3808e pbrook
    }
516 e1f3808e pbrook
    env->cc_src = cf;
517 e1f3808e pbrook
    env->cc_x = (cf != 0);
518 e1f3808e pbrook
    env->cc_dest = result;
519 e1f3808e pbrook
    return result;
520 e1f3808e pbrook
}
521 e1f3808e pbrook
522 e1f3808e pbrook
uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
523 e1f3808e pbrook
{
524 e1f3808e pbrook
    uint32_t result;
525 e1f3808e pbrook
    uint32_t cf;
526 e1f3808e pbrook
527 e1f3808e pbrook
    shift &= 63;
528 e1f3808e pbrook
    if (shift == 0) {
529 e1f3808e pbrook
        result = val;
530 e1f3808e pbrook
        cf = (env->cc_src & CCF_C) != 0;
531 e1f3808e pbrook
    } else if (shift < 32) {
532 e1f3808e pbrook
        result = (int32_t)val >> shift;
533 e1f3808e pbrook
        cf = (val >> (shift - 1)) & 1;
534 e1f3808e pbrook
    } else /* shift >= 32 */ {
535 e1f3808e pbrook
        result = (int32_t)val >> 31;
536 e1f3808e pbrook
        cf = val >> 31;
537 e1f3808e pbrook
    }
538 e1f3808e pbrook
    env->cc_src = cf;
539 e1f3808e pbrook
    env->cc_x = cf;
540 e1f3808e pbrook
    env->cc_dest = result;
541 e1f3808e pbrook
    return result;
542 e1f3808e pbrook
}
543 e1f3808e pbrook
544 e1f3808e pbrook
/* FPU helpers.  */
545 e1f3808e pbrook
uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
546 e1f3808e pbrook
{
547 e1f3808e pbrook
    return float64_to_int32(val, &env->fp_status);
548 e1f3808e pbrook
}
549 e1f3808e pbrook
550 e1f3808e pbrook
float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
551 e1f3808e pbrook
{
552 e1f3808e pbrook
    return float64_to_float32(val, &env->fp_status);
553 e1f3808e pbrook
}
554 e1f3808e pbrook
555 e1f3808e pbrook
float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
556 e1f3808e pbrook
{
557 e1f3808e pbrook
    return int32_to_float64(val, &env->fp_status);
558 e1f3808e pbrook
}
559 e1f3808e pbrook
560 e1f3808e pbrook
float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
561 e1f3808e pbrook
{
562 e1f3808e pbrook
    return float32_to_float64(val, &env->fp_status);
563 e1f3808e pbrook
}
564 e1f3808e pbrook
565 e1f3808e pbrook
float64 HELPER(iround_f64)(CPUState *env, float64 val)
566 e1f3808e pbrook
{
567 e1f3808e pbrook
    return float64_round_to_int(val, &env->fp_status);
568 e1f3808e pbrook
}
569 e1f3808e pbrook
570 e1f3808e pbrook
float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
571 e1f3808e pbrook
{
572 e1f3808e pbrook
    return float64_trunc_to_int(val, &env->fp_status);
573 e1f3808e pbrook
}
574 e1f3808e pbrook
575 e1f3808e pbrook
float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
576 e1f3808e pbrook
{
577 e1f3808e pbrook
    return float64_sqrt(val, &env->fp_status);
578 e1f3808e pbrook
}
579 e1f3808e pbrook
580 e1f3808e pbrook
float64 HELPER(abs_f64)(float64 val)
581 e1f3808e pbrook
{
582 e1f3808e pbrook
    return float64_abs(val);
583 e1f3808e pbrook
}
584 e1f3808e pbrook
585 e1f3808e pbrook
float64 HELPER(chs_f64)(float64 val)
586 e1f3808e pbrook
{
587 e1f3808e pbrook
    return float64_chs(val);
588 e1f3808e pbrook
}
589 e1f3808e pbrook
590 e1f3808e pbrook
float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
591 e1f3808e pbrook
{
592 e1f3808e pbrook
    return float64_add(a, b, &env->fp_status);
593 e1f3808e pbrook
}
594 e1f3808e pbrook
595 e1f3808e pbrook
float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
596 e1f3808e pbrook
{
597 e1f3808e pbrook
    return float64_sub(a, b, &env->fp_status);
598 e1f3808e pbrook
}
599 e1f3808e pbrook
600 e1f3808e pbrook
float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
601 e1f3808e pbrook
{
602 e1f3808e pbrook
    return float64_mul(a, b, &env->fp_status);
603 e1f3808e pbrook
}
604 e1f3808e pbrook
605 e1f3808e pbrook
float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
606 e1f3808e pbrook
{
607 e1f3808e pbrook
    return float64_div(a, b, &env->fp_status);
608 e1f3808e pbrook
}
609 e1f3808e pbrook
610 e1f3808e pbrook
float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
611 e1f3808e pbrook
{
612 e1f3808e pbrook
    /* ??? This may incorrectly raise exceptions.  */
613 e1f3808e pbrook
    /* ??? Should flush denormals to zero.  */
614 e1f3808e pbrook
    float64 res;
615 e1f3808e pbrook
    res = float64_sub(a, b, &env->fp_status);
616 e1f3808e pbrook
    if (float64_is_nan(res)) {
617 e1f3808e pbrook
        /* +/-inf compares equal against itself, but sub returns nan.  */
618 e1f3808e pbrook
        if (!float64_is_nan(a)
619 e1f3808e pbrook
            && !float64_is_nan(b)) {
620 e1f3808e pbrook
            res = float64_zero;
621 e1f3808e pbrook
            if (float64_lt_quiet(a, res, &env->fp_status))
622 e1f3808e pbrook
                res = float64_chs(res);
623 e1f3808e pbrook
        }
624 e1f3808e pbrook
    }
625 e1f3808e pbrook
    return res;
626 e1f3808e pbrook
}
627 e1f3808e pbrook
628 e1f3808e pbrook
uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
629 e1f3808e pbrook
{
630 e1f3808e pbrook
    return float64_compare_quiet(val, float64_zero, &env->fp_status);
631 e1f3808e pbrook
}
632 e1f3808e pbrook
633 e1f3808e pbrook
/* MAC unit.  */
634 e1f3808e pbrook
/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
635 e1f3808e pbrook
   take values,  others take register numbers and manipulate the contents
636 e1f3808e pbrook
   in-place.  */
637 e1f3808e pbrook
void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
638 e1f3808e pbrook
{
639 e1f3808e pbrook
    uint32_t mask;
640 e1f3808e pbrook
    env->macc[dest] = env->macc[src];
641 e1f3808e pbrook
    mask = MACSR_PAV0 << dest;
642 e1f3808e pbrook
    if (env->macsr & (MACSR_PAV0 << src))
643 e1f3808e pbrook
        env->macsr |= mask;
644 e1f3808e pbrook
    else
645 e1f3808e pbrook
        env->macsr &= ~mask;
646 e1f3808e pbrook
}
647 e1f3808e pbrook
648 e1f3808e pbrook
uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
649 e1f3808e pbrook
{
650 e1f3808e pbrook
    int64_t product;
651 e1f3808e pbrook
    int64_t res;
652 e1f3808e pbrook
653 e1f3808e pbrook
    product = (uint64_t)op1 * op2;
654 e1f3808e pbrook
    res = (product << 24) >> 24;
655 e1f3808e pbrook
    if (res != product) {
656 e1f3808e pbrook
        env->macsr |= MACSR_V;
657 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
658 e1f3808e pbrook
            /* Make sure the accumulate operation overflows.  */
659 e1f3808e pbrook
            if (product < 0)
660 e1f3808e pbrook
                res = ~(1ll << 50);
661 e1f3808e pbrook
            else
662 e1f3808e pbrook
                res = 1ll << 50;
663 e1f3808e pbrook
        }
664 e1f3808e pbrook
    }
665 e1f3808e pbrook
    return res;
666 e1f3808e pbrook
}
667 e1f3808e pbrook
668 e1f3808e pbrook
uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
669 e1f3808e pbrook
{
670 e1f3808e pbrook
    uint64_t product;
671 e1f3808e pbrook
672 e1f3808e pbrook
    product = (uint64_t)op1 * op2;
673 e1f3808e pbrook
    if (product & (0xffffffull << 40)) {
674 e1f3808e pbrook
        env->macsr |= MACSR_V;
675 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
676 e1f3808e pbrook
            /* Make sure the accumulate operation overflows.  */
677 e1f3808e pbrook
            product = 1ll << 50;
678 e1f3808e pbrook
        } else {
679 e1f3808e pbrook
            product &= ((1ull << 40) - 1);
680 e1f3808e pbrook
        }
681 e1f3808e pbrook
    }
682 e1f3808e pbrook
    return product;
683 e1f3808e pbrook
}
684 e1f3808e pbrook
685 e1f3808e pbrook
uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
686 e1f3808e pbrook
{
687 e1f3808e pbrook
    uint64_t product;
688 e1f3808e pbrook
    uint32_t remainder;
689 e1f3808e pbrook
690 e1f3808e pbrook
    product = (uint64_t)op1 * op2;
691 e1f3808e pbrook
    if (env->macsr & MACSR_RT) {
692 e1f3808e pbrook
        remainder = product & 0xffffff;
693 e1f3808e pbrook
        product >>= 24;
694 e1f3808e pbrook
        if (remainder > 0x800000)
695 e1f3808e pbrook
            product++;
696 e1f3808e pbrook
        else if (remainder == 0x800000)
697 e1f3808e pbrook
            product += (product & 1);
698 e1f3808e pbrook
    } else {
699 e1f3808e pbrook
        product >>= 24;
700 e1f3808e pbrook
    }
701 e1f3808e pbrook
    return product;
702 e1f3808e pbrook
}
703 e1f3808e pbrook
704 e1f3808e pbrook
void HELPER(macsats)(CPUState *env, uint32_t acc)
705 e1f3808e pbrook
{
706 e1f3808e pbrook
    int64_t tmp;
707 e1f3808e pbrook
    int64_t result;
708 e1f3808e pbrook
    tmp = env->macc[acc];
709 e1f3808e pbrook
    result = ((tmp << 16) >> 16);
710 e1f3808e pbrook
    if (result != tmp) {
711 e1f3808e pbrook
        env->macsr |= MACSR_V;
712 e1f3808e pbrook
    }
713 e1f3808e pbrook
    if (env->macsr & MACSR_V) {
714 e1f3808e pbrook
        env->macsr |= MACSR_PAV0 << acc;
715 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
716 e1f3808e pbrook
            /* The result is saturated to 32 bits, despite overflow occuring
717 e1f3808e pbrook
               at 48 bits.  Seems weird, but that's what the hardware docs
718 e1f3808e pbrook
               say.  */
719 e1f3808e pbrook
            result = (result >> 63) ^ 0x7fffffff;
720 e1f3808e pbrook
        }
721 e1f3808e pbrook
    }
722 e1f3808e pbrook
    env->macc[acc] = result;
723 e1f3808e pbrook
}
724 e1f3808e pbrook
725 e1f3808e pbrook
void HELPER(macsatu)(CPUState *env, uint32_t acc)
726 e1f3808e pbrook
{
727 e1f3808e pbrook
    uint64_t val;
728 e1f3808e pbrook
729 e1f3808e pbrook
    val = env->macc[acc];
730 e1f3808e pbrook
    if (val & (0xffffull << 48)) {
731 e1f3808e pbrook
        env->macsr |= MACSR_V;
732 e1f3808e pbrook
    }
733 e1f3808e pbrook
    if (env->macsr & MACSR_V) {
734 e1f3808e pbrook
        env->macsr |= MACSR_PAV0 << acc;
735 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
736 e1f3808e pbrook
            if (val > (1ull << 53))
737 e1f3808e pbrook
                val = 0;
738 e1f3808e pbrook
            else
739 e1f3808e pbrook
                val = (1ull << 48) - 1;
740 e1f3808e pbrook
        } else {
741 e1f3808e pbrook
            val &= ((1ull << 48) - 1);
742 e1f3808e pbrook
        }
743 e1f3808e pbrook
    }
744 e1f3808e pbrook
    env->macc[acc] = val;
745 e1f3808e pbrook
}
746 e1f3808e pbrook
747 e1f3808e pbrook
void HELPER(macsatf)(CPUState *env, uint32_t acc)
748 e1f3808e pbrook
{
749 e1f3808e pbrook
    int64_t sum;
750 e1f3808e pbrook
    int64_t result;
751 e1f3808e pbrook
752 e1f3808e pbrook
    sum = env->macc[acc];
753 e1f3808e pbrook
    result = (sum << 16) >> 16;
754 e1f3808e pbrook
    if (result != sum) {
755 e1f3808e pbrook
        env->macsr |= MACSR_V;
756 e1f3808e pbrook
    }
757 e1f3808e pbrook
    if (env->macsr & MACSR_V) {
758 e1f3808e pbrook
        env->macsr |= MACSR_PAV0 << acc;
759 e1f3808e pbrook
        if (env->macsr & MACSR_OMC) {
760 e1f3808e pbrook
            result = (result >> 63) ^ 0x7fffffffffffll;
761 e1f3808e pbrook
        }
762 e1f3808e pbrook
    }
763 e1f3808e pbrook
    env->macc[acc] = result;
764 e1f3808e pbrook
}
765 e1f3808e pbrook
766 e1f3808e pbrook
void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
767 e1f3808e pbrook
{
768 e1f3808e pbrook
    uint64_t val;
769 e1f3808e pbrook
    val = env->macc[acc];
770 e1f3808e pbrook
    if (val == 0)
771 e1f3808e pbrook
        env->macsr |= MACSR_Z;
772 e1f3808e pbrook
    else if (val & (1ull << 47));
773 e1f3808e pbrook
        env->macsr |= MACSR_N;
774 e1f3808e pbrook
    if (env->macsr & (MACSR_PAV0 << acc)) {
775 e1f3808e pbrook
        env->macsr |= MACSR_V;
776 e1f3808e pbrook
    }
777 e1f3808e pbrook
    if (env->macsr & MACSR_FI) {
778 e1f3808e pbrook
        val = ((int64_t)val) >> 40;
779 e1f3808e pbrook
        if (val != 0 && val != -1)
780 e1f3808e pbrook
            env->macsr |= MACSR_EV;
781 e1f3808e pbrook
    } else if (env->macsr & MACSR_SU) {
782 e1f3808e pbrook
        val = ((int64_t)val) >> 32;
783 e1f3808e pbrook
        if (val != 0 && val != -1)
784 e1f3808e pbrook
            env->macsr |= MACSR_EV;
785 e1f3808e pbrook
    } else {
786 e1f3808e pbrook
        if ((val >> 32) != 0)
787 e1f3808e pbrook
            env->macsr |= MACSR_EV;
788 e1f3808e pbrook
    }
789 e1f3808e pbrook
}
790 e1f3808e pbrook
791 e1f3808e pbrook
void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
792 e1f3808e pbrook
{
793 e1f3808e pbrook
    cpu_m68k_flush_flags(env, cc_op);
794 e1f3808e pbrook
}
795 e1f3808e pbrook
796 e1f3808e pbrook
uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
797 e1f3808e pbrook
{
798 e1f3808e pbrook
    int rem;
799 e1f3808e pbrook
    uint32_t result;
800 e1f3808e pbrook
801 e1f3808e pbrook
    if (env->macsr & MACSR_SU) {
802 e1f3808e pbrook
        /* 16-bit rounding.  */
803 e1f3808e pbrook
        rem = val & 0xffffff;
804 e1f3808e pbrook
        val = (val >> 24) & 0xffffu;
805 e1f3808e pbrook
        if (rem > 0x800000)
806 e1f3808e pbrook
            val++;
807 e1f3808e pbrook
        else if (rem == 0x800000)
808 e1f3808e pbrook
            val += (val & 1);
809 e1f3808e pbrook
    } else if (env->macsr & MACSR_RT) {
810 e1f3808e pbrook
        /* 32-bit rounding.  */
811 e1f3808e pbrook
        rem = val & 0xff;
812 e1f3808e pbrook
        val >>= 8;
813 e1f3808e pbrook
        if (rem > 0x80)
814 e1f3808e pbrook
            val++;
815 e1f3808e pbrook
        else if (rem == 0x80)
816 e1f3808e pbrook
            val += (val & 1);
817 e1f3808e pbrook
    } else {
818 e1f3808e pbrook
        /* No rounding.  */
819 e1f3808e pbrook
        val >>= 8;
820 e1f3808e pbrook
    }
821 e1f3808e pbrook
    if (env->macsr & MACSR_OMC) {
822 e1f3808e pbrook
        /* Saturate.  */
823 e1f3808e pbrook
        if (env->macsr & MACSR_SU) {
824 e1f3808e pbrook
            if (val != (uint16_t) val) {
825 e1f3808e pbrook
                result = ((val >> 63) ^ 0x7fff) & 0xffff;
826 e1f3808e pbrook
            } else {
827 e1f3808e pbrook
                result = val & 0xffff;
828 e1f3808e pbrook
            }
829 e1f3808e pbrook
        } else {
830 e1f3808e pbrook
            if (val != (uint32_t)val) {
831 e1f3808e pbrook
                result = ((uint32_t)(val >> 63) & 0x7fffffff);
832 e1f3808e pbrook
            } else {
833 e1f3808e pbrook
                result = (uint32_t)val;
834 e1f3808e pbrook
            }
835 e1f3808e pbrook
        }
836 e1f3808e pbrook
    } else {
837 e1f3808e pbrook
        /* No saturation.  */
838 e1f3808e pbrook
        if (env->macsr & MACSR_SU) {
839 e1f3808e pbrook
            result = val & 0xffff;
840 e1f3808e pbrook
        } else {
841 e1f3808e pbrook
            result = (uint32_t)val;
842 e1f3808e pbrook
        }
843 e1f3808e pbrook
    }
844 e1f3808e pbrook
    return result;
845 e1f3808e pbrook
}
846 e1f3808e pbrook
847 e1f3808e pbrook
uint32_t HELPER(get_macs)(uint64_t val)
848 e1f3808e pbrook
{
849 e1f3808e pbrook
    if (val == (int32_t)val) {
850 e1f3808e pbrook
        return (int32_t)val;
851 e1f3808e pbrook
    } else {
852 e1f3808e pbrook
        return (val >> 61) ^ ~SIGNBIT;
853 e1f3808e pbrook
    }
854 e1f3808e pbrook
}
855 e1f3808e pbrook
856 e1f3808e pbrook
uint32_t HELPER(get_macu)(uint64_t val)
857 e1f3808e pbrook
{
858 e1f3808e pbrook
    if ((val >> 32) == 0) {
859 e1f3808e pbrook
        return (uint32_t)val;
860 e1f3808e pbrook
    } else {
861 e1f3808e pbrook
        return 0xffffffffu;
862 e1f3808e pbrook
    }
863 e1f3808e pbrook
}
864 e1f3808e pbrook
865 e1f3808e pbrook
uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
866 e1f3808e pbrook
{
867 e1f3808e pbrook
    uint32_t val;
868 e1f3808e pbrook
    val = env->macc[acc] & 0x00ff;
869 e1f3808e pbrook
    val = (env->macc[acc] >> 32) & 0xff00;
870 e1f3808e pbrook
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
871 e1f3808e pbrook
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
872 e1f3808e pbrook
    return val;
873 e1f3808e pbrook
}
874 e1f3808e pbrook
875 e1f3808e pbrook
uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
876 e1f3808e pbrook
{
877 e1f3808e pbrook
    uint32_t val;
878 e1f3808e pbrook
    val = (env->macc[acc] >> 32) & 0xffff;
879 e1f3808e pbrook
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
880 e1f3808e pbrook
    return val;
881 e1f3808e pbrook
}
882 e1f3808e pbrook
883 e1f3808e pbrook
void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
884 e1f3808e pbrook
{
885 e1f3808e pbrook
    int64_t res;
886 e1f3808e pbrook
    int32_t tmp;
887 e1f3808e pbrook
    res = env->macc[acc] & 0xffffffff00ull;
888 e1f3808e pbrook
    tmp = (int16_t)(val & 0xff00);
889 e1f3808e pbrook
    res |= ((int64_t)tmp) << 32;
890 e1f3808e pbrook
    res |= val & 0xff;
891 e1f3808e pbrook
    env->macc[acc] = res;
892 e1f3808e pbrook
    res = env->macc[acc + 1] & 0xffffffff00ull;
893 e1f3808e pbrook
    tmp = (val & 0xff000000);
894 e1f3808e pbrook
    res |= ((int64_t)tmp) << 16;
895 e1f3808e pbrook
    res |= (val >> 16) & 0xff;
896 e1f3808e pbrook
    env->macc[acc + 1] = res;
897 e1f3808e pbrook
}
898 e1f3808e pbrook
899 e1f3808e pbrook
void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
900 e1f3808e pbrook
{
901 e1f3808e pbrook
    int64_t res;
902 e1f3808e pbrook
    int32_t tmp;
903 e1f3808e pbrook
    res = (uint32_t)env->macc[acc];
904 e1f3808e pbrook
    tmp = (int16_t)val;
905 e1f3808e pbrook
    res |= ((int64_t)tmp) << 32;
906 e1f3808e pbrook
    env->macc[acc] = res;
907 e1f3808e pbrook
    res = (uint32_t)env->macc[acc + 1];
908 e1f3808e pbrook
    tmp = val & 0xffff0000;
909 e1f3808e pbrook
    res |= (int64_t)tmp << 16;
910 e1f3808e pbrook
    env->macc[acc + 1] = res;
911 e1f3808e pbrook
}
912 e1f3808e pbrook
913 e1f3808e pbrook
void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
914 e1f3808e pbrook
{
915 e1f3808e pbrook
    uint64_t res;
916 e1f3808e pbrook
    res = (uint32_t)env->macc[acc];
917 e1f3808e pbrook
    res |= ((uint64_t)(val & 0xffff)) << 32;
918 e1f3808e pbrook
    env->macc[acc] = res;
919 e1f3808e pbrook
    res = (uint32_t)env->macc[acc + 1];
920 e1f3808e pbrook
    res |= (uint64_t)(val & 0xffff0000) << 16;
921 e1f3808e pbrook
    env->macc[acc + 1] = res;
922 e1f3808e pbrook
}