]> git.proxmox.com Git - mirror_qemu.git/blame - target-m68k/helper.c
target-m68k: Reorg flags handling
[mirror_qemu.git] / target-m68k / helper.c
CommitLineData
e6e5906b
PB
1/*
2 * m68k op helpers
5fafdf24 3 *
0633879f 4 * Copyright (c) 2006-2007 CodeSourcery
e6e5906b
PB
5 * Written by Paul Brook
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
e6e5906b
PB
19 */
20
d8416665 21#include "qemu/osdep.h"
e6e5906b 22#include "cpu.h"
63c91552 23#include "exec/exec-all.h"
022c62cb 24#include "exec/gdbstub.h"
e6e5906b 25
2ef6175a 26#include "exec/helper-proto.h"
e1f3808e
PB
27
28#define SIGNBIT (1u << 31)
29
11150915
AF
30/* Sort alphabetically, except for "any". */
31static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
009a4356 32{
11150915
AF
33 ObjectClass *class_a = (ObjectClass *)a;
34 ObjectClass *class_b = (ObjectClass *)b;
35 const char *name_a, *name_b;
36
37 name_a = object_class_get_name(class_a);
38 name_b = object_class_get_name(class_b);
7a9f812b 39 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
11150915 40 return 1;
7a9f812b 41 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
11150915
AF
42 return -1;
43 } else {
44 return strcasecmp(name_a, name_b);
009a4356
LV
45 }
46}
47
11150915
AF
48static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
49{
50 ObjectClass *c = data;
92a31361 51 CPUListState *s = user_data;
7a9f812b
AF
52 const char *typename;
53 char *name;
11150915 54
7a9f812b
AF
55 typename = object_class_get_name(c);
56 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
11150915 57 (*s->cpu_fprintf)(s->file, "%s\n",
7a9f812b
AF
58 name);
59 g_free(name);
11150915
AF
60}
61
62void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
63{
92a31361 64 CPUListState s = {
11150915
AF
65 .file = f,
66 .cpu_fprintf = cpu_fprintf,
67 };
68 GSList *list;
69
70 list = object_class_get_list(TYPE_M68K_CPU, false);
71 list = g_slist_sort(list, m68k_cpu_list_compare);
72 g_slist_foreach(list, m68k_cpu_list_entry, &s);
73 g_slist_free(list);
74}
75
2b3e3cfe 76static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
56aebc89
PB
77{
78 if (n < 8) {
79 stfq_p(mem_buf, env->fregs[n]);
80 return 8;
81 }
82 if (n < 11) {
83 /* FP control registers (not implemented) */
84 memset(mem_buf, 0, 4);
85 return 4;
86 }
87 return 0;
88}
89
2b3e3cfe 90static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
56aebc89
PB
91{
92 if (n < 8) {
93 env->fregs[n] = ldfq_p(mem_buf);
94 return 8;
95 }
96 if (n < 11) {
97 /* FP control registers (not implemented) */
98 return 4;
99 }
100 return 0;
101}
102
c7937d9f 103M68kCPU *cpu_m68k_init(const char *cpu_model)
aaed909a 104{
b9e7a234 105 M68kCPU *cpu;
aaed909a 106 CPUM68KState *env;
bc5b2da3 107 ObjectClass *oc;
aaed909a 108
bc5b2da3
AF
109 oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
110 if (oc == NULL) {
11150915
AF
111 return NULL;
112 }
bc5b2da3 113 cpu = M68K_CPU(object_new(object_class_get_name(oc)));
b9e7a234 114 env = &cpu->env;
01ba9816 115
11150915 116 register_m68k_insns(env);
6d1bbc62
AF
117
118 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
119
c7937d9f 120 return cpu;
6d1bbc62
AF
121}
122
123void m68k_cpu_init_gdb(M68kCPU *cpu)
124{
22169d41 125 CPUState *cs = CPU(cpu);
6d1bbc62
AF
126 CPUM68KState *env = &cpu->env;
127
11150915 128 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
22169d41 129 gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg,
11150915 130 11, "cf-fp.xml", 18);
aaed909a 131 }
11150915 132 /* TODO: Add [E]MAC registers. */
aaed909a 133}
0402f767 134
e1f3808e 135void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
0633879f 136{
a47dddd7
AF
137 M68kCPU *cpu = m68k_env_get_cpu(env);
138
0633879f
PB
139 switch (reg) {
140 case 0x02: /* CACR */
20dcee94
PB
141 env->cacr = val;
142 m68k_switch_sp(env);
143 break;
144 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
145 /* TODO: Implement Access Control Registers. */
0633879f
PB
146 break;
147 case 0x801: /* VBR */
148 env->vbr = val;
149 break;
150 /* TODO: Implement control registers. */
151 default:
a47dddd7 152 cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
0633879f
PB
153 reg, val);
154 }
155}
156
e1f3808e 157void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
acf930aa
PB
158{
159 uint32_t acc;
160 int8_t exthigh;
161 uint8_t extlow;
162 uint64_t regval;
163 int i;
164 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
165 for (i = 0; i < 4; i++) {
166 regval = env->macc[i];
167 exthigh = regval >> 40;
168 if (env->macsr & MACSR_FI) {
169 acc = regval >> 8;
170 extlow = regval;
171 } else {
172 acc = regval;
173 extlow = regval >> 32;
174 }
175 if (env->macsr & MACSR_FI) {
176 regval = (((uint64_t)acc) << 8) | extlow;
177 regval |= ((int64_t)exthigh) << 40;
178 } else if (env->macsr & MACSR_SU) {
179 regval = acc | (((int64_t)extlow) << 32);
180 regval |= ((int64_t)exthigh) << 40;
181 } else {
182 regval = acc | (((uint64_t)extlow) << 32);
183 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
184 }
185 env->macc[i] = regval;
186 }
187 }
188 env->macsr = val;
189}
190
20dcee94
PB
191void m68k_switch_sp(CPUM68KState *env)
192{
193 int new_sp;
194
195 env->sp[env->current_sp] = env->aregs[7];
196 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
197 ? M68K_SSP : M68K_USP;
198 env->aregs[7] = env->sp[new_sp];
199 env->current_sp = new_sp;
200}
201
5fafdf24 202#if defined(CONFIG_USER_ONLY)
0633879f 203
7510454e
AF
204int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
205 int mmu_idx)
0633879f 206{
7510454e
AF
207 M68kCPU *cpu = M68K_CPU(cs);
208
27103424 209 cs->exception_index = EXCP_ACCESS;
7510454e 210 cpu->env.mmu.ar = address;
0633879f
PB
211 return 1;
212}
213
214#else
215
4fcc562b
PB
216/* MMU */
217
218/* TODO: This will need fixing once the MMU is implemented. */
00b941e5 219hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
4fcc562b
PB
220{
221 return addr;
222}
223
7510454e
AF
224int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
225 int mmu_idx)
0633879f
PB
226{
227 int prot;
228
229 address &= TARGET_PAGE_MASK;
d4c430a8 230 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
0c591eb0 231 tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
d4c430a8 232 return 0;
0633879f
PB
233}
234
235/* Notify CPU of a pending interrupt. Prioritization and vectoring should
236 be handled by the interrupt controller. Real hardware only requests
237 the vector when the interrupt is acknowledged by the CPU. For
238 simplicitly we calculate it when the interrupt is signalled. */
cb3fb38e 239void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
0633879f 240{
d8ed887b 241 CPUState *cs = CPU(cpu);
cb3fb38e
AF
242 CPUM68KState *env = &cpu->env;
243
0633879f
PB
244 env->pending_level = level;
245 env->pending_vector = vector;
d8ed887b 246 if (level) {
c3affe56 247 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
d8ed887b
AF
248 } else {
249 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
250 }
0633879f
PB
251}
252
253#endif
e1f3808e
PB
254
255uint32_t HELPER(bitrev)(uint32_t x)
256{
257 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
258 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
259 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
260 return bswap32(x);
261}
262
263uint32_t HELPER(ff1)(uint32_t x)
264{
265 int n;
266 for (n = 32; x; n--)
267 x >>= 1;
268 return n;
269}
270
620c6cf6 271uint32_t HELPER(sats)(uint32_t val, uint32_t v)
e1f3808e
PB
272{
273 /* The result has the opposite sign to the original value. */
620c6cf6 274 if ((int32_t)v < 0) {
e1f3808e 275 val = (((int32_t)val) >> 31) ^ SIGNBIT;
620c6cf6 276 }
e1f3808e
PB
277 return val;
278}
279
2b3e3cfe 280uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e 281{
620c6cf6 282 uint32_t res, new_x;
e1f3808e 283
e1f3808e 284 if (env->cc_x) {
620c6cf6 285 new_x = (op1 <= op2);
e1f3808e
PB
286 res = op1 - (op2 + 1);
287 } else {
620c6cf6 288 new_x = (op1 < op2);
e1f3808e
PB
289 res = op1 - op2;
290 }
620c6cf6
RH
291 env->cc_x = new_x;
292 env->cc_c = new_x;
293 env->cc_n = res;
294 env->cc_z |= res; /* !Z is sticky */
295 env->cc_v = (res ^ op1) & (op1 ^ op2);
296
e1f3808e
PB
297 return res;
298}
299
2b3e3cfe 300uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e 301{
620c6cf6 302 uint32_t res, new_x;
e1f3808e 303
e1f3808e
PB
304 if (env->cc_x) {
305 res = op1 + op2 + 1;
620c6cf6 306 new_x = (res <= op2);
e1f3808e
PB
307 } else {
308 res = op1 + op2;
620c6cf6 309 new_x = (res < op2);
e1f3808e 310 }
620c6cf6
RH
311 env->cc_x = new_x;
312 env->cc_c = new_x;
313 env->cc_n = res;
314 env->cc_z |= res; /* !Z is sticky. */
315 env->cc_v = (res ^ op1) & ~(op1 ^ op2);
316
e1f3808e
PB
317 return res;
318}
319
2b3e3cfe 320void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
e1f3808e 321{
99c51448
RH
322 env->sr = val & 0xffe0;
323 cpu_m68k_set_ccr(env, val);
e1f3808e
PB
324 m68k_switch_sp(env);
325}
326
2b3e3cfe 327uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e 328{
620c6cf6 329 uint64_t result;
e1f3808e
PB
330
331 shift &= 63;
620c6cf6
RH
332 result = (uint64_t)val << shift;
333
334 env->cc_c = (result >> 32) & 1;
335 env->cc_n = result;
336 env->cc_z = result;
337 env->cc_v = 0;
338 env->cc_x = shift ? env->cc_c : env->cc_x;
339
e1f3808e
PB
340 return result;
341}
342
2b3e3cfe 343uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e 344{
620c6cf6 345 uint64_t temp;
e1f3808e 346 uint32_t result;
e1f3808e
PB
347
348 shift &= 63;
620c6cf6
RH
349 temp = (uint64_t)val << 32 >> shift;
350 result = temp >> 32;
351
352 env->cc_c = (temp >> 31) & 1;
353 env->cc_n = result;
354 env->cc_z = result;
355 env->cc_v = 0;
356 env->cc_x = shift ? env->cc_c : env->cc_x;
357
e1f3808e
PB
358 return result;
359}
360
2b3e3cfe 361uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e 362{
620c6cf6 363 uint64_t temp;
e1f3808e 364 uint32_t result;
e1f3808e
PB
365
366 shift &= 63;
620c6cf6
RH
367 temp = (int64_t)val << 32 >> shift;
368 result = temp >> 32;
369
370 env->cc_c = (temp >> 31) & 1;
371 env->cc_n = result;
372 env->cc_z = result;
373 env->cc_v = result ^ val;
374 env->cc_x = shift ? env->cc_c : env->cc_x;
375
e1f3808e
PB
376 return result;
377}
378
379/* FPU helpers. */
2b3e3cfe 380uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
e1f3808e
PB
381{
382 return float64_to_int32(val, &env->fp_status);
383}
384
2b3e3cfe 385float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
e1f3808e
PB
386{
387 return float64_to_float32(val, &env->fp_status);
388}
389
2b3e3cfe 390float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
e1f3808e
PB
391{
392 return int32_to_float64(val, &env->fp_status);
393}
394
2b3e3cfe 395float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
e1f3808e
PB
396{
397 return float32_to_float64(val, &env->fp_status);
398}
399
2b3e3cfe 400float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
401{
402 return float64_round_to_int(val, &env->fp_status);
403}
404
2b3e3cfe 405float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
406{
407 return float64_trunc_to_int(val, &env->fp_status);
408}
409
2b3e3cfe 410float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
411{
412 return float64_sqrt(val, &env->fp_status);
413}
414
415float64 HELPER(abs_f64)(float64 val)
416{
417 return float64_abs(val);
418}
419
420float64 HELPER(chs_f64)(float64 val)
421{
422 return float64_chs(val);
423}
424
2b3e3cfe 425float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
426{
427 return float64_add(a, b, &env->fp_status);
428}
429
2b3e3cfe 430float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
431{
432 return float64_sub(a, b, &env->fp_status);
433}
434
2b3e3cfe 435float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
436{
437 return float64_mul(a, b, &env->fp_status);
438}
439
2b3e3cfe 440float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
441{
442 return float64_div(a, b, &env->fp_status);
443}
444
2b3e3cfe 445float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
446{
447 /* ??? This may incorrectly raise exceptions. */
448 /* ??? Should flush denormals to zero. */
449 float64 res;
450 res = float64_sub(a, b, &env->fp_status);
af39bc8c 451 if (float64_is_quiet_nan(res, &env->fp_status)) {
e1f3808e 452 /* +/-inf compares equal against itself, but sub returns nan. */
af39bc8c
AM
453 if (!float64_is_quiet_nan(a, &env->fp_status)
454 && !float64_is_quiet_nan(b, &env->fp_status)) {
e1f3808e
PB
455 res = float64_zero;
456 if (float64_lt_quiet(a, res, &env->fp_status))
457 res = float64_chs(res);
458 }
459 }
460 return res;
461}
462
2b3e3cfe 463uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
464{
465 return float64_compare_quiet(val, float64_zero, &env->fp_status);
466}
467
468/* MAC unit. */
469/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
470 take values, others take register numbers and manipulate the contents
471 in-place. */
2b3e3cfe 472void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
e1f3808e
PB
473{
474 uint32_t mask;
475 env->macc[dest] = env->macc[src];
476 mask = MACSR_PAV0 << dest;
477 if (env->macsr & (MACSR_PAV0 << src))
478 env->macsr |= mask;
479 else
480 env->macsr &= ~mask;
481}
482
2b3e3cfe 483uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
484{
485 int64_t product;
486 int64_t res;
487
488 product = (uint64_t)op1 * op2;
489 res = (product << 24) >> 24;
490 if (res != product) {
491 env->macsr |= MACSR_V;
492 if (env->macsr & MACSR_OMC) {
493 /* Make sure the accumulate operation overflows. */
494 if (product < 0)
495 res = ~(1ll << 50);
496 else
497 res = 1ll << 50;
498 }
499 }
500 return res;
501}
502
2b3e3cfe 503uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
504{
505 uint64_t product;
506
507 product = (uint64_t)op1 * op2;
508 if (product & (0xffffffull << 40)) {
509 env->macsr |= MACSR_V;
510 if (env->macsr & MACSR_OMC) {
511 /* Make sure the accumulate operation overflows. */
512 product = 1ll << 50;
513 } else {
514 product &= ((1ull << 40) - 1);
515 }
516 }
517 return product;
518}
519
2b3e3cfe 520uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
521{
522 uint64_t product;
523 uint32_t remainder;
524
525 product = (uint64_t)op1 * op2;
526 if (env->macsr & MACSR_RT) {
527 remainder = product & 0xffffff;
528 product >>= 24;
529 if (remainder > 0x800000)
530 product++;
531 else if (remainder == 0x800000)
532 product += (product & 1);
533 } else {
534 product >>= 24;
535 }
536 return product;
537}
538
2b3e3cfe 539void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
540{
541 int64_t tmp;
542 int64_t result;
543 tmp = env->macc[acc];
544 result = ((tmp << 16) >> 16);
545 if (result != tmp) {
546 env->macsr |= MACSR_V;
547 }
548 if (env->macsr & MACSR_V) {
549 env->macsr |= MACSR_PAV0 << acc;
550 if (env->macsr & MACSR_OMC) {
a1c7273b 551 /* The result is saturated to 32 bits, despite overflow occurring
e1f3808e
PB
552 at 48 bits. Seems weird, but that's what the hardware docs
553 say. */
554 result = (result >> 63) ^ 0x7fffffff;
555 }
556 }
557 env->macc[acc] = result;
558}
559
2b3e3cfe 560void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
561{
562 uint64_t val;
563
564 val = env->macc[acc];
565 if (val & (0xffffull << 48)) {
566 env->macsr |= MACSR_V;
567 }
568 if (env->macsr & MACSR_V) {
569 env->macsr |= MACSR_PAV0 << acc;
570 if (env->macsr & MACSR_OMC) {
571 if (val > (1ull << 53))
572 val = 0;
573 else
574 val = (1ull << 48) - 1;
575 } else {
576 val &= ((1ull << 48) - 1);
577 }
578 }
579 env->macc[acc] = val;
580}
581
2b3e3cfe 582void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
583{
584 int64_t sum;
585 int64_t result;
586
587 sum = env->macc[acc];
588 result = (sum << 16) >> 16;
589 if (result != sum) {
590 env->macsr |= MACSR_V;
591 }
592 if (env->macsr & MACSR_V) {
593 env->macsr |= MACSR_PAV0 << acc;
594 if (env->macsr & MACSR_OMC) {
595 result = (result >> 63) ^ 0x7fffffffffffll;
596 }
597 }
598 env->macc[acc] = result;
599}
600
2b3e3cfe 601void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
602{
603 uint64_t val;
604 val = env->macc[acc];
c4162574 605 if (val == 0) {
e1f3808e 606 env->macsr |= MACSR_Z;
c4162574 607 } else if (val & (1ull << 47)) {
e1f3808e 608 env->macsr |= MACSR_N;
c4162574 609 }
e1f3808e
PB
610 if (env->macsr & (MACSR_PAV0 << acc)) {
611 env->macsr |= MACSR_V;
612 }
613 if (env->macsr & MACSR_FI) {
614 val = ((int64_t)val) >> 40;
615 if (val != 0 && val != -1)
616 env->macsr |= MACSR_EV;
617 } else if (env->macsr & MACSR_SU) {
618 val = ((int64_t)val) >> 32;
619 if (val != 0 && val != -1)
620 env->macsr |= MACSR_EV;
621 } else {
622 if ((val >> 32) != 0)
623 env->macsr |= MACSR_EV;
624 }
625}
626
620c6cf6
RH
627
628#define COMPUTE_CCR(op, x, n, z, v, c) { \
629 switch (op) { \
630 case CC_OP_FLAGS: \
631 /* Everything in place. */ \
632 break; \
633 case CC_OP_ADD: \
634 res = n; \
635 src2 = v; \
636 src1 = res - src2; \
637 c = x; \
638 z = n; \
639 v = (res ^ src1) & ~(src1 ^ src2); \
640 break; \
641 case CC_OP_SUB: \
642 res = n; \
643 src2 = v; \
644 src1 = res + src2; \
645 c = x; \
646 z = n; \
647 v = (res ^ src1) & (src1 ^ src2); \
648 break; \
649 case CC_OP_CMP: \
650 src1 = n; \
651 src2 = v; \
652 res = src1 - src2; \
653 n = res; \
654 z = res; \
655 c = src1 < src2; \
656 v = (res ^ src1) & (src1 ^ src2); \
657 break; \
658 case CC_OP_LOGIC: \
659 c = v = 0; \
660 z = n; \
661 break; \
662 default: \
663 cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op); \
664 } \
665} while (0)
666
667uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
e1f3808e 668{
620c6cf6
RH
669 uint32_t x, c, n, z, v;
670 uint32_t res, src1, src2;
671
672 x = env->cc_x;
673 c = env->cc_c;
674 n = env->cc_n;
675 z = env->cc_z;
676 v = env->cc_v;
677
678 COMPUTE_CCR(env->cc_op, x, n, z, v, c);
679
680 n = n >> 31;
681 v = v >> 31;
682 z = (z == 0);
683
684 return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
685}
686
687uint32_t HELPER(get_ccr)(CPUM68KState *env)
688{
689 return cpu_m68k_get_ccr(env);
690}
691
692void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
693{
694 env->cc_x = (ccr & CCF_X ? 1 : 0);
695 env->cc_n = (ccr & CCF_N ? -1 : 0);
696 env->cc_z = (ccr & CCF_Z ? 0 : 1);
697 env->cc_v = (ccr & CCF_V ? -1 : 0);
698 env->cc_c = (ccr & CCF_C ? 1 : 0);
699 env->cc_op = CC_OP_FLAGS;
700}
701
702void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
703{
704 cpu_m68k_set_ccr(env, ccr);
705}
706
707void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
708{
709 uint32_t res, src1, src2;
710
711 COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
712 env->cc_op = CC_OP_FLAGS;
e1f3808e
PB
713}
714
2b3e3cfe 715uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
e1f3808e
PB
716{
717 int rem;
718 uint32_t result;
719
720 if (env->macsr & MACSR_SU) {
721 /* 16-bit rounding. */
722 rem = val & 0xffffff;
723 val = (val >> 24) & 0xffffu;
724 if (rem > 0x800000)
725 val++;
726 else if (rem == 0x800000)
727 val += (val & 1);
728 } else if (env->macsr & MACSR_RT) {
729 /* 32-bit rounding. */
730 rem = val & 0xff;
731 val >>= 8;
732 if (rem > 0x80)
733 val++;
734 else if (rem == 0x80)
735 val += (val & 1);
736 } else {
737 /* No rounding. */
738 val >>= 8;
739 }
740 if (env->macsr & MACSR_OMC) {
741 /* Saturate. */
742 if (env->macsr & MACSR_SU) {
743 if (val != (uint16_t) val) {
744 result = ((val >> 63) ^ 0x7fff) & 0xffff;
745 } else {
746 result = val & 0xffff;
747 }
748 } else {
749 if (val != (uint32_t)val) {
750 result = ((uint32_t)(val >> 63) & 0x7fffffff);
751 } else {
752 result = (uint32_t)val;
753 }
754 }
755 } else {
756 /* No saturation. */
757 if (env->macsr & MACSR_SU) {
758 result = val & 0xffff;
759 } else {
760 result = (uint32_t)val;
761 }
762 }
763 return result;
764}
765
766uint32_t HELPER(get_macs)(uint64_t val)
767{
768 if (val == (int32_t)val) {
769 return (int32_t)val;
770 } else {
771 return (val >> 61) ^ ~SIGNBIT;
772 }
773}
774
775uint32_t HELPER(get_macu)(uint64_t val)
776{
777 if ((val >> 32) == 0) {
778 return (uint32_t)val;
779 } else {
780 return 0xffffffffu;
781 }
782}
783
2b3e3cfe 784uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
785{
786 uint32_t val;
787 val = env->macc[acc] & 0x00ff;
5ce747cf 788 val |= (env->macc[acc] >> 32) & 0xff00;
e1f3808e
PB
789 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
790 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
791 return val;
792}
793
2b3e3cfe 794uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
795{
796 uint32_t val;
797 val = (env->macc[acc] >> 32) & 0xffff;
798 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
799 return val;
800}
801
2b3e3cfe 802void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
803{
804 int64_t res;
805 int32_t tmp;
806 res = env->macc[acc] & 0xffffffff00ull;
807 tmp = (int16_t)(val & 0xff00);
808 res |= ((int64_t)tmp) << 32;
809 res |= val & 0xff;
810 env->macc[acc] = res;
811 res = env->macc[acc + 1] & 0xffffffff00ull;
812 tmp = (val & 0xff000000);
813 res |= ((int64_t)tmp) << 16;
814 res |= (val >> 16) & 0xff;
815 env->macc[acc + 1] = res;
816}
817
2b3e3cfe 818void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
819{
820 int64_t res;
821 int32_t tmp;
822 res = (uint32_t)env->macc[acc];
823 tmp = (int16_t)val;
824 res |= ((int64_t)tmp) << 32;
825 env->macc[acc] = res;
826 res = (uint32_t)env->macc[acc + 1];
827 tmp = val & 0xffff0000;
828 res |= (int64_t)tmp << 16;
829 env->macc[acc + 1] = res;
830}
831
2b3e3cfe 832void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
833{
834 uint64_t res;
835 res = (uint32_t)env->macc[acc];
836 res |= ((uint64_t)(val & 0xffff)) << 32;
837 env->macc[acc] = res;
838 res = (uint32_t)env->macc[acc + 1];
839 res |= (uint64_t)(val & 0xffff0000) << 16;
840 env->macc[acc + 1] = res;
841}