]> Git Repo - qemu.git/blame - target-m68k/helper.c
virtio-gpu: fix information leak in getting capset info dispatch
[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 280void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
e1f3808e 281{
99c51448
RH
282 env->sr = val & 0xffe0;
283 cpu_m68k_set_ccr(env, val);
e1f3808e
PB
284 m68k_switch_sp(env);
285}
286
2b3e3cfe 287uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e 288{
620c6cf6 289 uint64_t result;
e1f3808e
PB
290
291 shift &= 63;
620c6cf6
RH
292 result = (uint64_t)val << shift;
293
294 env->cc_c = (result >> 32) & 1;
295 env->cc_n = result;
296 env->cc_z = result;
297 env->cc_v = 0;
298 env->cc_x = shift ? env->cc_c : env->cc_x;
299
e1f3808e
PB
300 return result;
301}
302
2b3e3cfe 303uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e 304{
620c6cf6 305 uint64_t temp;
e1f3808e 306 uint32_t result;
e1f3808e
PB
307
308 shift &= 63;
620c6cf6
RH
309 temp = (uint64_t)val << 32 >> shift;
310 result = temp >> 32;
311
312 env->cc_c = (temp >> 31) & 1;
313 env->cc_n = result;
314 env->cc_z = result;
315 env->cc_v = 0;
316 env->cc_x = shift ? env->cc_c : env->cc_x;
317
e1f3808e
PB
318 return result;
319}
320
2b3e3cfe 321uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
e1f3808e 322{
620c6cf6 323 uint64_t temp;
e1f3808e 324 uint32_t result;
e1f3808e
PB
325
326 shift &= 63;
620c6cf6
RH
327 temp = (int64_t)val << 32 >> shift;
328 result = temp >> 32;
329
330 env->cc_c = (temp >> 31) & 1;
331 env->cc_n = result;
332 env->cc_z = result;
333 env->cc_v = result ^ val;
334 env->cc_x = shift ? env->cc_c : env->cc_x;
335
e1f3808e
PB
336 return result;
337}
338
339/* FPU helpers. */
2b3e3cfe 340uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
e1f3808e
PB
341{
342 return float64_to_int32(val, &env->fp_status);
343}
344
2b3e3cfe 345float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
e1f3808e
PB
346{
347 return float64_to_float32(val, &env->fp_status);
348}
349
2b3e3cfe 350float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
e1f3808e
PB
351{
352 return int32_to_float64(val, &env->fp_status);
353}
354
2b3e3cfe 355float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
e1f3808e
PB
356{
357 return float32_to_float64(val, &env->fp_status);
358}
359
2b3e3cfe 360float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
361{
362 return float64_round_to_int(val, &env->fp_status);
363}
364
2b3e3cfe 365float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
366{
367 return float64_trunc_to_int(val, &env->fp_status);
368}
369
2b3e3cfe 370float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
371{
372 return float64_sqrt(val, &env->fp_status);
373}
374
375float64 HELPER(abs_f64)(float64 val)
376{
377 return float64_abs(val);
378}
379
380float64 HELPER(chs_f64)(float64 val)
381{
382 return float64_chs(val);
383}
384
2b3e3cfe 385float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
386{
387 return float64_add(a, b, &env->fp_status);
388}
389
2b3e3cfe 390float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
391{
392 return float64_sub(a, b, &env->fp_status);
393}
394
2b3e3cfe 395float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
396{
397 return float64_mul(a, b, &env->fp_status);
398}
399
2b3e3cfe 400float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
401{
402 return float64_div(a, b, &env->fp_status);
403}
404
2b3e3cfe 405float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
e1f3808e
PB
406{
407 /* ??? This may incorrectly raise exceptions. */
408 /* ??? Should flush denormals to zero. */
409 float64 res;
410 res = float64_sub(a, b, &env->fp_status);
af39bc8c 411 if (float64_is_quiet_nan(res, &env->fp_status)) {
e1f3808e 412 /* +/-inf compares equal against itself, but sub returns nan. */
af39bc8c
AM
413 if (!float64_is_quiet_nan(a, &env->fp_status)
414 && !float64_is_quiet_nan(b, &env->fp_status)) {
e1f3808e
PB
415 res = float64_zero;
416 if (float64_lt_quiet(a, res, &env->fp_status))
417 res = float64_chs(res);
418 }
419 }
420 return res;
421}
422
2b3e3cfe 423uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
e1f3808e
PB
424{
425 return float64_compare_quiet(val, float64_zero, &env->fp_status);
426}
427
428/* MAC unit. */
429/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
430 take values, others take register numbers and manipulate the contents
431 in-place. */
2b3e3cfe 432void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
e1f3808e
PB
433{
434 uint32_t mask;
435 env->macc[dest] = env->macc[src];
436 mask = MACSR_PAV0 << dest;
437 if (env->macsr & (MACSR_PAV0 << src))
438 env->macsr |= mask;
439 else
440 env->macsr &= ~mask;
441}
442
2b3e3cfe 443uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
444{
445 int64_t product;
446 int64_t res;
447
448 product = (uint64_t)op1 * op2;
449 res = (product << 24) >> 24;
450 if (res != product) {
451 env->macsr |= MACSR_V;
452 if (env->macsr & MACSR_OMC) {
453 /* Make sure the accumulate operation overflows. */
454 if (product < 0)
455 res = ~(1ll << 50);
456 else
457 res = 1ll << 50;
458 }
459 }
460 return res;
461}
462
2b3e3cfe 463uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
464{
465 uint64_t product;
466
467 product = (uint64_t)op1 * op2;
468 if (product & (0xffffffull << 40)) {
469 env->macsr |= MACSR_V;
470 if (env->macsr & MACSR_OMC) {
471 /* Make sure the accumulate operation overflows. */
472 product = 1ll << 50;
473 } else {
474 product &= ((1ull << 40) - 1);
475 }
476 }
477 return product;
478}
479
2b3e3cfe 480uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
481{
482 uint64_t product;
483 uint32_t remainder;
484
485 product = (uint64_t)op1 * op2;
486 if (env->macsr & MACSR_RT) {
487 remainder = product & 0xffffff;
488 product >>= 24;
489 if (remainder > 0x800000)
490 product++;
491 else if (remainder == 0x800000)
492 product += (product & 1);
493 } else {
494 product >>= 24;
495 }
496 return product;
497}
498
2b3e3cfe 499void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
500{
501 int64_t tmp;
502 int64_t result;
503 tmp = env->macc[acc];
504 result = ((tmp << 16) >> 16);
505 if (result != tmp) {
506 env->macsr |= MACSR_V;
507 }
508 if (env->macsr & MACSR_V) {
509 env->macsr |= MACSR_PAV0 << acc;
510 if (env->macsr & MACSR_OMC) {
a1c7273b 511 /* The result is saturated to 32 bits, despite overflow occurring
e1f3808e
PB
512 at 48 bits. Seems weird, but that's what the hardware docs
513 say. */
514 result = (result >> 63) ^ 0x7fffffff;
515 }
516 }
517 env->macc[acc] = result;
518}
519
2b3e3cfe 520void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
521{
522 uint64_t val;
523
524 val = env->macc[acc];
525 if (val & (0xffffull << 48)) {
526 env->macsr |= MACSR_V;
527 }
528 if (env->macsr & MACSR_V) {
529 env->macsr |= MACSR_PAV0 << acc;
530 if (env->macsr & MACSR_OMC) {
531 if (val > (1ull << 53))
532 val = 0;
533 else
534 val = (1ull << 48) - 1;
535 } else {
536 val &= ((1ull << 48) - 1);
537 }
538 }
539 env->macc[acc] = val;
540}
541
2b3e3cfe 542void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
543{
544 int64_t sum;
545 int64_t result;
546
547 sum = env->macc[acc];
548 result = (sum << 16) >> 16;
549 if (result != sum) {
550 env->macsr |= MACSR_V;
551 }
552 if (env->macsr & MACSR_V) {
553 env->macsr |= MACSR_PAV0 << acc;
554 if (env->macsr & MACSR_OMC) {
555 result = (result >> 63) ^ 0x7fffffffffffll;
556 }
557 }
558 env->macc[acc] = result;
559}
560
2b3e3cfe 561void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
562{
563 uint64_t val;
564 val = env->macc[acc];
c4162574 565 if (val == 0) {
e1f3808e 566 env->macsr |= MACSR_Z;
c4162574 567 } else if (val & (1ull << 47)) {
e1f3808e 568 env->macsr |= MACSR_N;
c4162574 569 }
e1f3808e
PB
570 if (env->macsr & (MACSR_PAV0 << acc)) {
571 env->macsr |= MACSR_V;
572 }
573 if (env->macsr & MACSR_FI) {
574 val = ((int64_t)val) >> 40;
575 if (val != 0 && val != -1)
576 env->macsr |= MACSR_EV;
577 } else if (env->macsr & MACSR_SU) {
578 val = ((int64_t)val) >> 32;
579 if (val != 0 && val != -1)
580 env->macsr |= MACSR_EV;
581 } else {
582 if ((val >> 32) != 0)
583 env->macsr |= MACSR_EV;
584 }
585}
586
db3d7945
LV
587#define EXTSIGN(val, index) ( \
588 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
589)
620c6cf6
RH
590
591#define COMPUTE_CCR(op, x, n, z, v, c) { \
592 switch (op) { \
593 case CC_OP_FLAGS: \
594 /* Everything in place. */ \
595 break; \
db3d7945
LV
596 case CC_OP_ADDB: \
597 case CC_OP_ADDW: \
598 case CC_OP_ADDL: \
620c6cf6
RH
599 res = n; \
600 src2 = v; \
db3d7945 601 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \
620c6cf6
RH
602 c = x; \
603 z = n; \
604 v = (res ^ src1) & ~(src1 ^ src2); \
605 break; \
db3d7945
LV
606 case CC_OP_SUBB: \
607 case CC_OP_SUBW: \
608 case CC_OP_SUBL: \
620c6cf6
RH
609 res = n; \
610 src2 = v; \
db3d7945 611 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \
620c6cf6
RH
612 c = x; \
613 z = n; \
614 v = (res ^ src1) & (src1 ^ src2); \
615 break; \
db3d7945
LV
616 case CC_OP_CMPB: \
617 case CC_OP_CMPW: \
618 case CC_OP_CMPL: \
620c6cf6
RH
619 src1 = n; \
620 src2 = v; \
db3d7945 621 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \
620c6cf6
RH
622 n = res; \
623 z = res; \
624 c = src1 < src2; \
625 v = (res ^ src1) & (src1 ^ src2); \
626 break; \
627 case CC_OP_LOGIC: \
628 c = v = 0; \
629 z = n; \
630 break; \
631 default: \
632 cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op); \
633 } \
634} while (0)
635
636uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
e1f3808e 637{
620c6cf6
RH
638 uint32_t x, c, n, z, v;
639 uint32_t res, src1, src2;
640
641 x = env->cc_x;
620c6cf6
RH
642 n = env->cc_n;
643 z = env->cc_z;
644 v = env->cc_v;
db3d7945 645 c = env->cc_c;
620c6cf6
RH
646
647 COMPUTE_CCR(env->cc_op, x, n, z, v, c);
648
649 n = n >> 31;
620c6cf6 650 z = (z == 0);
db3d7945 651 v = v >> 31;
620c6cf6
RH
652
653 return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
654}
655
656uint32_t HELPER(get_ccr)(CPUM68KState *env)
657{
658 return cpu_m68k_get_ccr(env);
659}
660
661void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
662{
663 env->cc_x = (ccr & CCF_X ? 1 : 0);
664 env->cc_n = (ccr & CCF_N ? -1 : 0);
665 env->cc_z = (ccr & CCF_Z ? 0 : 1);
666 env->cc_v = (ccr & CCF_V ? -1 : 0);
667 env->cc_c = (ccr & CCF_C ? 1 : 0);
668 env->cc_op = CC_OP_FLAGS;
669}
670
671void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
672{
673 cpu_m68k_set_ccr(env, ccr);
674}
675
676void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
677{
678 uint32_t res, src1, src2;
679
680 COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
681 env->cc_op = CC_OP_FLAGS;
e1f3808e
PB
682}
683
2b3e3cfe 684uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
e1f3808e
PB
685{
686 int rem;
687 uint32_t result;
688
689 if (env->macsr & MACSR_SU) {
690 /* 16-bit rounding. */
691 rem = val & 0xffffff;
692 val = (val >> 24) & 0xffffu;
693 if (rem > 0x800000)
694 val++;
695 else if (rem == 0x800000)
696 val += (val & 1);
697 } else if (env->macsr & MACSR_RT) {
698 /* 32-bit rounding. */
699 rem = val & 0xff;
700 val >>= 8;
701 if (rem > 0x80)
702 val++;
703 else if (rem == 0x80)
704 val += (val & 1);
705 } else {
706 /* No rounding. */
707 val >>= 8;
708 }
709 if (env->macsr & MACSR_OMC) {
710 /* Saturate. */
711 if (env->macsr & MACSR_SU) {
712 if (val != (uint16_t) val) {
713 result = ((val >> 63) ^ 0x7fff) & 0xffff;
714 } else {
715 result = val & 0xffff;
716 }
717 } else {
718 if (val != (uint32_t)val) {
719 result = ((uint32_t)(val >> 63) & 0x7fffffff);
720 } else {
721 result = (uint32_t)val;
722 }
723 }
724 } else {
725 /* No saturation. */
726 if (env->macsr & MACSR_SU) {
727 result = val & 0xffff;
728 } else {
729 result = (uint32_t)val;
730 }
731 }
732 return result;
733}
734
735uint32_t HELPER(get_macs)(uint64_t val)
736{
737 if (val == (int32_t)val) {
738 return (int32_t)val;
739 } else {
740 return (val >> 61) ^ ~SIGNBIT;
741 }
742}
743
744uint32_t HELPER(get_macu)(uint64_t val)
745{
746 if ((val >> 32) == 0) {
747 return (uint32_t)val;
748 } else {
749 return 0xffffffffu;
750 }
751}
752
2b3e3cfe 753uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
754{
755 uint32_t val;
756 val = env->macc[acc] & 0x00ff;
5ce747cf 757 val |= (env->macc[acc] >> 32) & 0xff00;
e1f3808e
PB
758 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
759 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
760 return val;
761}
762
2b3e3cfe 763uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
764{
765 uint32_t val;
766 val = (env->macc[acc] >> 32) & 0xffff;
767 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
768 return val;
769}
770
2b3e3cfe 771void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
772{
773 int64_t res;
774 int32_t tmp;
775 res = env->macc[acc] & 0xffffffff00ull;
776 tmp = (int16_t)(val & 0xff00);
777 res |= ((int64_t)tmp) << 32;
778 res |= val & 0xff;
779 env->macc[acc] = res;
780 res = env->macc[acc + 1] & 0xffffffff00ull;
781 tmp = (val & 0xff000000);
782 res |= ((int64_t)tmp) << 16;
783 res |= (val >> 16) & 0xff;
784 env->macc[acc + 1] = res;
785}
786
2b3e3cfe 787void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
788{
789 int64_t res;
790 int32_t tmp;
791 res = (uint32_t)env->macc[acc];
792 tmp = (int16_t)val;
793 res |= ((int64_t)tmp) << 32;
794 env->macc[acc] = res;
795 res = (uint32_t)env->macc[acc + 1];
796 tmp = val & 0xffff0000;
797 res |= (int64_t)tmp << 16;
798 env->macc[acc + 1] = res;
799}
800
2b3e3cfe 801void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
802{
803 uint64_t res;
804 res = (uint32_t)env->macc[acc];
805 res |= ((uint64_t)(val & 0xffff)) << 32;
806 env->macc[acc] = res;
807 res = (uint32_t)env->macc[acc + 1];
808 res |= (uint64_t)(val & 0xffff0000) << 16;
809 env->macc[acc + 1] = res;
810}
This page took 0.956235 seconds and 4 git commands to generate.