Fix "make test2".
[qemu/mini2440.git] / target-m68k / helper.c
blob6b8f18d15d37ca8c0f50ec398ab7bd0b1ba543c8
1 /*
2 * m68k op helpers
3 *
4 * Copyright (c) 2006 CodeSourcery
5 * Written by Paul Brook
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.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdio.h>
24 #include "config.h"
25 #include "cpu.h"
26 #include "exec-all.h"
28 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
30 int flags;
31 uint32_t src;
32 uint32_t dest;
33 uint32_t tmp;
35 #define HIGHBIT 0x80000000u
37 #define SET_NZ(x) do { \
38 if ((x) == 0) \
39 flags |= CCF_Z; \
40 else if ((int32_t)(x) < 0) \
41 flags |= CCF_N; \
42 } while (0)
44 #define SET_FLAGS_SUB(type, utype) do { \
45 SET_NZ((type)dest); \
46 tmp = dest + src; \
47 if ((utype) tmp < (utype) src) \
48 flags |= CCF_C; \
49 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
50 flags |= CCF_V; \
51 } while (0)
53 flags = 0;
54 src = env->cc_src;
55 dest = env->cc_dest;
56 switch (cc_op) {
57 case CC_OP_FLAGS:
58 flags = dest;
59 break;
60 case CC_OP_LOGIC:
61 SET_NZ(dest);
62 break;
63 case CC_OP_ADD:
64 SET_NZ(dest);
65 if (dest < src)
66 flags |= CCF_C;
67 tmp = dest - src;
68 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
69 flags |= CCF_V;
70 break;
71 case CC_OP_SUB:
72 SET_FLAGS_SUB(int32_t, uint32_t);
73 break;
74 case CC_OP_CMPB:
75 SET_FLAGS_SUB(int8_t, uint8_t);
76 break;
77 case CC_OP_CMPW:
78 SET_FLAGS_SUB(int16_t, uint16_t);
79 break;
80 case CC_OP_ADDX:
81 SET_NZ(dest);
82 if (dest <= src)
83 flags |= CCF_C;
84 tmp = dest - src - 1;
85 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
86 flags |= CCF_V;
87 break;
88 case CC_OP_SUBX:
89 SET_NZ(dest);
90 tmp = dest + src + 1;
91 if (tmp <= src)
92 flags |= CCF_C;
93 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
94 flags |= CCF_V;
95 break;
96 case CC_OP_SHL:
97 if (src >= 32) {
98 SET_NZ(0);
99 } else {
100 tmp = dest << src;
101 SET_NZ(tmp);
103 if (src && src <= 32 && (dest & (1 << (32 - src))))
104 flags |= CCF_C;
105 break;
106 case CC_OP_SHR:
107 if (src >= 32) {
108 SET_NZ(0);
109 } else {
110 tmp = dest >> src;
111 SET_NZ(tmp);
113 if (src && src <= 32 && ((dest >> (src - 1)) & 1))
114 flags |= CCF_C;
115 break;
116 case CC_OP_SAR:
117 if (src >= 32) {
118 SET_NZ(-1);
119 } else {
120 tmp = (int32_t)dest >> src;
121 SET_NZ(tmp);
123 if (src && src <= 32 && (((int32_t)dest >> (src - 1)) & 1))
124 flags |= CCF_C;
125 break;
126 default:
127 cpu_abort(env, "Bad CC_OP %d", cc_op);
129 env->cc_op = CC_OP_FLAGS;
130 env->cc_dest = flags;
133 float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1)
135 /* ??? This may incorrectly raise exceptions. */
136 /* ??? Should flush denormals to zero. */
137 float64 res;
138 res = float64_sub(src0, src1, &env->fp_status);
139 if (float64_is_nan(res)) {
140 /* +/-inf compares equal against itself, but sub returns nan. */
141 if (!float64_is_nan(src0)
142 && !float64_is_nan(src1)) {
143 res = 0;
144 if (float64_lt_quiet(src0, res, &env->fp_status))
145 res = float64_chs(res);
148 return res;