ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/m68k.h
Revision: 1.8
Committed: 2012-03-30T01:25:46Z (12 years, 8 months ago) by asvitkine
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +21 -7 lines
Log Message:
Add GPLv2 notices to files from UAE Amiga Emulator, as retrieved from the
COPYING file of uae-0.8.29, retrieved from http://www.amigaemulator.org/
via uae-0.8.29.tar.bz2 (MD5 = 54abbabb5e8580b679c52de019141d61).

File Contents

# Content
1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * MC68000 emulation - machine dependent bits
5 *
6 * Copyright 1996 Bernd Schmidt
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #ifndef M68K_FLAGS_H
24 #define M68K_FLAGS_H
25
26 #ifdef OPTIMIZED_FLAGS
27
28 #if (defined(__i386__) && defined(X86_ASSEMBLY)) || (defined(__x86_64__) && defined(X86_64_ASSEMBLY))
29
30 #ifndef SAHF_SETO_PROFITABLE
31
32 /* PUSH/POP instructions are naturally 64-bit sized on x86-64, thus
33 unsigned long hereunder is either 64-bit or 32-bit wide depending
34 on the target. */
35 struct flag_struct {
36 unsigned long cznv;
37 unsigned long x;
38 };
39
40 #define FLAGVAL_Z 0x40
41 #define FLAGVAL_N 0x80
42
43 #define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x40) | (((y) & 1) << 6))
44 #define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~1) | ((y) & 1))
45 #define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x800) | (((y) & 1) << 11))
46 #define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x80) | (((y) & 1) << 7))
47 #define SET_XFLG(y) (regflags.x = (y))
48
49 #define GET_ZFLG ((regflags.cznv >> 6) & 1)
50 #define GET_CFLG (regflags.cznv & 1)
51 #define GET_VFLG ((regflags.cznv >> 11) & 1)
52 #define GET_NFLG ((regflags.cznv >> 7) & 1)
53 #define GET_XFLG (regflags.x & 1)
54
55 #define CLEAR_CZNV (regflags.cznv = 0)
56 #define GET_CZNV (regflags.cznv)
57 #define IOR_CZNV(X) (regflags.cznv |= (X))
58 #define SET_CZNV(X) (regflags.cznv = (X))
59
60 #define COPY_CARRY (regflags.x = regflags.cznv)
61
62 extern struct flag_struct regflags __asm__ ("regflags");
63
64 static __inline__ int cctrue(int cc)
65 {
66 uae_u32 cznv = regflags.cznv;
67 switch(cc){
68 case 0: return 1; /* T */
69 case 1: return 0; /* F */
70 case 2: return (cznv & 0x41) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
71 case 3: return (cznv & 0x41) != 0; /* GET_CFLG || GET_ZFLG; LS */
72 case 4: return (cznv & 1) == 0; /* !GET_CFLG; CC */
73 case 5: return (cznv & 1) != 0; /* GET_CFLG; CS */
74 case 6: return (cznv & 0x40) == 0; /* !GET_ZFLG; NE */
75 case 7: return (cznv & 0x40) != 0; /* GET_ZFLG; EQ */
76 case 8: return (cznv & 0x800) == 0;/* !GET_VFLG; VC */
77 case 9: return (cznv & 0x800) != 0;/* GET_VFLG; VS */
78 case 10:return (cznv & 0x80) == 0; /* !GET_NFLG; PL */
79 case 11:return (cznv & 0x80) != 0; /* GET_NFLG; MI */
80 case 12:return (((cznv << 4) ^ cznv) & 0x800) == 0; /* GET_NFLG == GET_VFLG; GE */
81 case 13:return (((cznv << 4) ^ cznv) & 0x800) != 0;/* GET_NFLG != GET_VFLG; LT */
82 case 14:
83 cznv &= 0x8c0;
84 return (((cznv << 4) ^ cznv) & 0x840) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
85 case 15:
86 cznv &= 0x8c0;
87 return (((cznv << 4) ^ cznv) & 0x840) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
88 }
89 return 0;
90 }
91
92 #define optflag_testl(v) \
93 __asm__ __volatile__ ("andl %1,%1\n\t" \
94 "pushf\n\t" \
95 "pop %0\n\t" \
96 : "=r" (regflags.cznv) : "r" (v) : "cc")
97
98 #define optflag_testw(v) \
99 __asm__ __volatile__ ("andw %w1,%w1\n\t" \
100 "pushf\n\t" \
101 "pop %0\n\t" \
102 : "=r" (regflags.cznv) : "r" (v) : "cc")
103
104 #define optflag_testb(v) \
105 __asm__ __volatile__ ("andb %b1,%b1\n\t" \
106 "pushf\n\t" \
107 "pop %0\n\t" \
108 : "=r" (regflags.cznv) : "q" (v) : "cc")
109
110 #define optflag_addl(v, s, d) do { \
111 __asm__ __volatile__ ("addl %k2,%k1\n\t" \
112 "pushf\n\t" \
113 "pop %0\n\t" \
114 : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
115 COPY_CARRY; \
116 } while (0)
117
118 #define optflag_addw(v, s, d) do { \
119 __asm__ __volatile__ ("addw %w2,%w1\n\t" \
120 "pushf\n\t" \
121 "pop %0\n\t" \
122 : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
123 COPY_CARRY; \
124 } while (0)
125
126 #define optflag_addb(v, s, d) do { \
127 __asm__ __volatile__ ("addb %b2,%b1\n\t" \
128 "pushf\n\t" \
129 "pop %0\n\t" \
130 : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
131 COPY_CARRY; \
132 } while (0)
133
134 #define optflag_subl(v, s, d) do { \
135 __asm__ __volatile__ ("subl %k2,%k1\n\t" \
136 "pushf\n\t" \
137 "pop %0\n\t" \
138 : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
139 COPY_CARRY; \
140 } while (0)
141
142 #define optflag_subw(v, s, d) do { \
143 __asm__ __volatile__ ("subw %w2,%w1\n\t" \
144 "pushf\n\t" \
145 "pop %0\n\t" \
146 : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
147 COPY_CARRY; \
148 } while (0)
149
150 #define optflag_subb(v, s, d) do { \
151 __asm__ __volatile__ ("subb %b2,%b1\n\t" \
152 "pushf\n\t" \
153 "pop %0\n\t" \
154 : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
155 COPY_CARRY; \
156 } while (0)
157
158 #define optflag_cmpl(s, d) \
159 __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \
160 "pushf\n\t" \
161 "pop %0\n\t" \
162 : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
163
164 #define optflag_cmpw(s, d) \
165 __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \
166 "pushf\n\t" \
167 "pop %0\n\t" \
168 : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
169
170 #define optflag_cmpb(s, d) \
171 __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \
172 "pushf\n\t" \
173 "pop %0\n\t" \
174 : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc")
175
176 #else
177
178 struct flag_struct {
179 uae_u32 cznv;
180 uae_u32 x;
181 };
182
183 #define FLAGVAL_Z 0x4000
184 #define FLAGVAL_N 0x8000
185
186 #define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14))
187 #define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8))
188 #define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1)))
189 #define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15))
190 #define SET_XFLG(y) (regflags.x = (y))
191
192 #define GET_ZFLG ((regflags.cznv >> 14) & 1)
193 #define GET_CFLG ((regflags.cznv >> 8) & 1)
194 #define GET_VFLG ((regflags.cznv >> 0) & 1)
195 #define GET_NFLG ((regflags.cznv >> 15) & 1)
196 #define GET_XFLG (regflags.x & 1)
197
198 #define CLEAR_CZNV (regflags.cznv = 0)
199 #define GET_CZNV (regflags.cznv)
200 #define IOR_CZNV(X) (regflags.cznv |= (X))
201 #define SET_CZNV(X) (regflags.cznv = (X))
202
203 #define COPY_CARRY (regflags.x = (regflags.cznv)>>8)
204
205 extern struct flag_struct regflags __asm__ ("regflags");
206
207 static __inline__ int cctrue(int cc)
208 {
209 uae_u32 cznv = regflags.cznv;
210 switch(cc){
211 case 0: return 1; /* T */
212 case 1: return 0; /* F */
213 case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
214 case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */
215 case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */
216 case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */
217 case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */
218 case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */
219 case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */
220 case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */
221 case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */
222 case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */
223 case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */
224 case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */
225 case 14:
226 cznv &= 0xc001;
227 return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
228 case 15:
229 cznv &= 0xc001;
230 return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
231 }
232 abort();
233 return 0;
234 }
235
236 /* Manually emit LAHF instruction so that 64-bit assemblers can grok it */
237 #if defined __x86_64__ && defined __GNUC__
238 #define ASM_LAHF ".byte 0x9f"
239 #else
240 #define ASM_LAHF "lahf"
241 #endif
242
243 /* Is there any way to do this without declaring *all* memory clobbered?
244 I.e. any way to tell gcc that some byte-sized value is in %al? */
245 #define optflag_testl(v) \
246 __asm__ __volatile__ ("andl %0,%0\n\t" \
247 ASM_LAHF "\n\t" \
248 "seto %%al\n\t" \
249 "movb %%al,regflags\n\t" \
250 "movb %%ah,regflags+1\n\t" \
251 : : "r" (v) : "%eax","cc","memory")
252
253 #define optflag_testw(v) \
254 __asm__ __volatile__ ("andw %w0,%w0\n\t" \
255 ASM_LAHF "\n\t" \
256 "seto %%al\n\t" \
257 "movb %%al,regflags\n\t" \
258 "movb %%ah,regflags+1\n\t" \
259 : : "r" (v) : "%eax","cc","memory")
260
261 #define optflag_testb(v) \
262 __asm__ __volatile__ ("andb %b0,%b0\n\t" \
263 ASM_LAHF "\n\t" \
264 "seto %%al\n\t" \
265 "movb %%al,regflags\n\t" \
266 "movb %%ah,regflags+1\n\t" \
267 : : "q" (v) : "%eax","cc","memory")
268
269 #define optflag_addl(v, s, d) do { \
270 __asm__ __volatile__ ("addl %k1,%k0\n\t" \
271 ASM_LAHF "\n\t" \
272 "seto %%al\n\t" \
273 "movb %%al,regflags\n\t" \
274 "movb %%ah,regflags+1\n\t" \
275 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
276 COPY_CARRY; \
277 } while (0)
278
279 #define optflag_addw(v, s, d) do { \
280 __asm__ __volatile__ ("addw %w1,%w0\n\t" \
281 ASM_LAHF "\n\t" \
282 "seto %%al\n\t" \
283 "movb %%al,regflags\n\t" \
284 "movb %%ah,regflags+1\n\t" \
285 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
286 COPY_CARRY; \
287 } while (0)
288
289 #define optflag_addb(v, s, d) do { \
290 __asm__ __volatile__ ("addb %b1,%b0\n\t" \
291 ASM_LAHF "\n\t" \
292 "seto %%al\n\t" \
293 "movb %%al,regflags\n\t" \
294 "movb %%ah,regflags+1\n\t" \
295 : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
296 COPY_CARRY; \
297 } while (0)
298
299 #define optflag_subl(v, s, d) do { \
300 __asm__ __volatile__ ("subl %k1,%k0\n\t" \
301 ASM_LAHF "\n\t" \
302 "seto %%al\n\t" \
303 "movb %%al,regflags\n\t" \
304 "movb %%ah,regflags+1\n\t" \
305 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
306 COPY_CARRY; \
307 } while (0)
308
309 #define optflag_subw(v, s, d) do { \
310 __asm__ __volatile__ ("subw %w1,%w0\n\t" \
311 ASM_LAHF "\n\t" \
312 "seto %%al\n\t" \
313 "movb %%al,regflags\n\t" \
314 "movb %%ah,regflags+1\n\t" \
315 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
316 COPY_CARRY; \
317 } while (0)
318
319 #define optflag_subb(v, s, d) do { \
320 __asm__ __volatile__ ("subb %b1,%b0\n\t" \
321 ASM_LAHF "\n\t" \
322 "seto %%al\n\t" \
323 "movb %%al,regflags\n\t" \
324 "movb %%ah,regflags+1\n\t" \
325 : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
326 COPY_CARRY; \
327 } while (0)
328
329 #define optflag_cmpl(s, d) \
330 __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
331 ASM_LAHF "\n\t" \
332 "seto %%al\n\t" \
333 "movb %%al,regflags\n\t" \
334 "movb %%ah,regflags+1\n\t" \
335 : : "rmi" (s), "r" (d) : "%eax","cc","memory")
336
337 #define optflag_cmpw(s, d) \
338 __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
339 ASM_LAHF "\n\t" \
340 "seto %%al\n\t" \
341 "movb %%al,regflags\n\t" \
342 "movb %%ah,regflags+1\n\t" \
343 : : "rmi" (s), "r" (d) : "%eax","cc","memory");
344
345 #define optflag_cmpb(s, d) \
346 __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
347 ASM_LAHF "\n\t" \
348 "seto %%al\n\t" \
349 "movb %%al,regflags\n\t" \
350 "movb %%ah,regflags+1\n\t" \
351 : : "qmi" (s), "q" (d) : "%eax","cc","memory")
352
353 #endif
354
355 #elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
356
357 struct flag_struct {
358 unsigned char nzvc;
359 unsigned char x;
360 };
361
362 extern struct flag_struct regflags;
363
364 #define FLAGVAL_Z 0x04
365 #define FLAGVAL_N 0x08
366
367 #define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2))
368 #define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1))
369 #define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1))
370 #define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3))
371 #define SET_XFLG(y) (regflags.x = (y))
372
373 #define GET_ZFLG ((regflags.nzvc >> 2) & 1)
374 #define GET_CFLG (regflags.nzvc & 1)
375 #define GET_VFLG ((regflags.nzvc >> 1) & 1)
376 #define GET_NFLG ((regflags.nzvc >> 3) & 1)
377 #define GET_XFLG (regflags.x & 1)
378
379 #define CLEAR_CZNV (regflags.nzvc = 0)
380 #define GET_CZNV (reflags.nzvc)
381 #define IOR_CZNV(X) (refglags.nzvc |= (X))
382 #define SET_CZNV(X) (regflags.nzvc = (X))
383
384 #define COPY_CARRY (regflags.x = regflags.nzvc)
385
386 static __inline__ int cctrue(int cc)
387 {
388 uae_u32 nzvc = regflags.nzvc;
389 switch(cc){
390 case 0: return 1; /* T */
391 case 1: return 0; /* F */
392 case 2: return (nzvc & 0x05) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
393 case 3: return (nzvc & 0x05) != 0; /* GET_CFLG || GET_ZFLG; LS */
394 case 4: return (nzvc & 1) == 0; /* !GET_CFLG; CC */
395 case 5: return (nzvc & 1) != 0; /* GET_CFLG; CS */
396 case 6: return (nzvc & 0x04) == 0; /* !GET_ZFLG; NE */
397 case 7: return (nzvc & 0x04) != 0; /* GET_ZFLG; EQ */
398 case 8: return (nzvc & 0x02) == 0;/* !GET_VFLG; VC */
399 case 9: return (nzvc & 0x02) != 0;/* GET_VFLG; VS */
400 case 10:return (nzvc & 0x08) == 0; /* !GET_NFLG; PL */
401 case 11:return (nzvc & 0x08) != 0; /* GET_NFLG; MI */
402 case 12:return (((nzvc << 2) ^ nzvc) & 0x08) == 0; /* GET_NFLG == GET_VFLG; GE */
403 case 13:return (((nzvc << 2) ^ nzvc) & 0x08) != 0;/* GET_NFLG != GET_VFLG; LT */
404 case 14:
405 nzvc &= 0x0e;
406 return (((nzvc << 2) ^ nzvc) & 0x0c) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
407 case 15:
408 nzvc &= 0x0e;
409 return (((nzvc << 2) ^ nzvc) & 0x0c) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
410 }
411 return 0;
412 }
413
414 #ifdef SPARC_V8_ASSEMBLY
415
416 static inline uae_u32 sparc_v8_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
417 {
418 uae_u32 value;
419 __asm__ ("\n"
420 " sll %2, 24, %%o0\n"
421 " sll %3, 24, %%o1\n"
422 " addcc %%o0, %%o1, %%o0\n"
423 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
424 " srl %%o0, 24, %0\n"
425 " stb %%o1, [%1 + 1]\n"
426 " bl,a .+8\n"
427 " or %%o1, 0x08, %%o1 ! N flag\n"
428 " bz,a .+8\n"
429 " or %%o1, 0x04, %%o1 ! Z flag\n"
430 " bvs,a .+8\n"
431 " or %%o1, 0x02, %%o1 ! V flag\n"
432 " stb %%o1, [%1]\n"
433 : "=&r" (value)
434 : "r" (flags), "r" (dst), "r" (src)
435 : "cc", "o0", "o1"
436 );
437 return value;
438 }
439
440 static inline uae_u32 sparc_v8_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
441 {
442 uae_u32 value;
443 __asm__ ("\n"
444 " sll %2, 16, %%o0\n"
445 " sll %3, 16, %%o1\n"
446 " addcc %%o0, %%o1, %%o0\n"
447 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
448 " srl %%o0, 16, %0\n"
449 " stb %%o1, [%1 + 1]\n"
450 " bl,a .+8\n"
451 " or %%o1, 0x08, %%o1 ! N flag\n"
452 " bz,a .+8\n"
453 " or %%o1, 0x04, %%o1 ! Z flag\n"
454 " bvs,a .+8\n"
455 " or %%o1, 0x02, %%o1 ! V flag\n"
456 " stb %%o1, [%1]\n"
457 : "=&r" (value)
458 : "r" (flags), "r" (dst), "r" (src)
459 : "cc", "o0", "o1"
460 );
461 return value;
462 }
463
464 static inline uae_u32 sparc_v8_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
465 {
466 uae_u32 value;
467 __asm__ ("\n"
468 " addcc %2, %3, %0\n"
469 " addx %%g0, %%g0, %%o0 ! X,C flags\n"
470 " stb %%o0, [%1 + 1]\n"
471 " bl,a .+8\n"
472 " or %%o0, 0x08, %%o0 ! N flag\n"
473 " bz,a .+8\n"
474 " or %%o0, 0x04, %%o0 ! Z flag\n"
475 " bvs,a .+8\n"
476 " or %%o0, 0x02, %%o0 ! V flag\n"
477 " stb %%o0, [%1]\n"
478 : "=&r" (value)
479 : "r" (flags), "r" (dst), "r" (src)
480 : "cc", "o0"
481 );
482 return value;
483 }
484
485 static inline uae_u32 sparc_v8_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
486 {
487 uae_u32 value;
488 __asm__ ("\n"
489 " sll %2, 24, %%o0\n"
490 " sll %3, 24, %%o1\n"
491 " subcc %%o0, %%o1, %%o0\n"
492 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
493 " srl %%o0, 24, %0\n"
494 " stb %%o1, [%1 + 1]\n"
495 " bl,a .+8\n"
496 " or %%o1, 0x08, %%o1 ! N flag\n"
497 " bz,a .+8\n"
498 " or %%o1, 0x04, %%o1 ! Z flag\n"
499 " bvs,a .+8\n"
500 " or %%o1, 0x02, %%o1 ! V flag\n"
501 " stb %%o1, [%1]\n"
502 : "=&r" (value)
503 : "r" (flags), "r" (dst), "r" (src)
504 : "cc", "o0", "o1"
505 );
506 return value;
507 }
508
509 static inline uae_u32 sparc_v8_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
510 {
511 uae_u32 value;
512 __asm__ ("\n"
513 " sll %2, 16, %%o0\n"
514 " sll %3, 16, %%o1\n"
515 " subcc %%o0, %%o1, %%o0\n"
516 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
517 " srl %%o0, 16, %0\n"
518 " stb %%o1, [%1 + 1]\n"
519 " bl,a .+8\n"
520 " or %%o1, 0x08, %%o1 ! N flag\n"
521 " bz,a .+8\n"
522 " or %%o1, 0x04, %%o1 ! Z flag\n"
523 " bvs,a .+8\n"
524 " or %%o1, 0x02, %%o1 ! V flag\n"
525 " stb %%o1, [%1]\n"
526 : "=&r" (value)
527 : "r" (flags), "r" (dst), "r" (src)
528 : "cc", "o0", "o1"
529 );
530 return value;
531 }
532
533 static inline uae_u32 sparc_v8_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
534 {
535 uae_u32 value;
536 __asm__ ("\n"
537 " subcc %2, %3, %0\n"
538 " addx %%g0, %%g0, %%o0 ! X,C flags\n"
539 " stb %%o0, [%1 + 1]\n"
540 " bl,a .+8\n"
541 " or %%o0, 0x08, %%o0 ! N flag\n"
542 " bz,a .+8\n"
543 " or %%o0, 0x04, %%o0 ! Z flag\n"
544 " bvs,a .+8\n"
545 " or %%o0, 0x02, %%o0 ! V flag\n"
546 " stb %%o0, [%1]\n"
547 : "=&r" (value)
548 : "r" (flags), "r" (dst), "r" (src)
549 : "cc", "o0"
550 );
551 return value;
552 }
553
554 static inline void sparc_v8_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
555 {
556 __asm__ ("\n"
557 " sll %1, 24, %%o0\n"
558 " sll %2, 24, %%o1\n"
559 " subcc %%o0, %%o1, %%g0\n"
560 " addx %%g0, %%g0, %%o0 ! C flag\n"
561 " bl,a .+8\n"
562 " or %%o0, 0x08, %%o0 ! N flag\n"
563 " bz,a .+8\n"
564 " or %%o0, 0x04, %%o0 ! Z flag\n"
565 " bvs,a .+8\n"
566 " or %%o0, 0x02, %%o0 ! V flag\n"
567 " stb %%o0, [%0]\n"
568 : /* no outputs */
569 : "r" (flags), "r" (dst), "r" (src)
570 : "cc", "o0", "o1"
571 );
572 }
573
574 static inline void sparc_v8_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
575 {
576 __asm__ ("\n"
577 " sll %1, 16, %%o0\n"
578 " sll %2, 16, %%o1\n"
579 " subcc %%o0, %%o1, %%g0\n"
580 " addx %%g0, %%g0, %%o0 ! C flag\n"
581 " bl,a .+8\n"
582 " or %%o0, 0x08, %%o0 ! N flag\n"
583 " bz,a .+8\n"
584 " or %%o0, 0x04, %%o0 ! Z flag\n"
585 " bvs,a .+8\n"
586 " or %%o0, 0x02, %%o0 ! V flag\n"
587 " stb %%o0, [%0]\n"
588 : /* no outputs */
589 : "r" (flags), "r" (dst), "r" (src)
590 : "cc", "o0", "o1"
591 );
592 }
593
594 static inline void sparc_v8_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
595 {
596 __asm__ ("\n"
597 " subcc %1, %2, %%o1\n"
598 " srl %%o1, 31, %%o0\n"
599 " sll %%o0, 3, %%o0\n"
600 " addx %%o0, %%g0, %%o0\n"
601 " bvs,a .+8\n"
602 " or %%o0, 0x02, %%o0\n"
603 " subcc %%g0, %%o1, %%g0\n"
604 " addx %%g0, 7, %%o1\n"
605 " and %%o1, 0x04, %%o1\n"
606 " or %%o0, %%o1, %%o0\n"
607 " stb %%o0, [%0]\n"
608 : /* no outputs */
609 : "r" (flags), "r" (dst), "r" (src)
610 : "cc", "o0", "o1"
611 );
612 }
613
614 static inline uae_u32 sparc_v8_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
615 {
616 uae_u32 value;
617 __asm__ ("\n"
618 " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
619 " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
620 " addxcc %2, %3, %0\n"
621 : "=&r" (value)
622 : "r" (flags), "r" (dst), "r" (src)
623 : "cc", "o0", "o1"
624 );
625 return value;
626 }
627
628 #if 0
629 VERY SLOW...
630 static inline uae_u32 sparc_v8_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
631 {
632 uae_u32 value;
633 __asm__ ("\n"
634 " sll %2, 24, %%o0\n"
635 " sll %3, 24, %%o1\n"
636 " addcc %%o0, %%o1, %%o0\n"
637 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
638 " bvs,a .+8\n"
639 " or %%o1, 0x02, %%o1 ! V flag\n"
640 " ldub [%1 + 1], %%o2\n"
641 " subcc %%g0, %%o2, %%g0\n"
642 " addx %%g0, %%g0, %%o2\n"
643 " sll %%o2, 24, %%o2\n"
644 " addcc %%o0, %%o2, %%o0\n"
645 " srl %%o0, 24, %0\n"
646 " addx %%g0, %%g0, %%o2\n"
647 " or %%o1, %%o2, %%o1 ! update X,C flags\n"
648 " bl,a .+8\n"
649 " or %%o1, 0x08, %%o1 ! N flag\n"
650 " ldub [%1], %%o0 ! retreive the old NZVC flags (XXX)\n"
651 " bvs,a .+8\n"
652 " or %%o1, 0x02, %%o1 ! update V flag\n"
653 " and %%o0, 0x04, %%o0 ! (XXX) but keep only Z flag\n"
654 " and %%o1, 1, %%o2 ! keep C flag in %%o2\n"
655 " bnz,a .+8\n"
656 " or %%g0, %%g0, %%o0 ! Z flag cleared if non-zero result\n"
657 " stb %%o2, [%1 + 1] ! store the X flag\n"
658 " or %%o1, %%o0, %%o1\n"
659 " stb %%o1, [%1]\n"
660 : "=&r" (value)
661 : "r" (flags), "r" (dst), "r" (src)
662 : "cc", "o0", "o1", "o2"
663 );
664 return value;
665 }
666 #endif
667
668 static inline uae_u32 sparc_v8_flag_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
669 {
670 uae_u32 value;
671 __asm__ ("\n"
672 " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
673 " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
674 " addxcc %2, %3, %0\n"
675 " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
676 " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
677 " addx %%o0, %%g0, %%o0 ! X,C flags\n"
678 " bl,a .+8\n"
679 " or %%o0, 0x08, %%o0 ! N flag\n"
680 " bvs,a .+8\n"
681 " or %%o0, 0x02, %%o0 ! V flag\n"
682 " bnz,a .+8\n"
683 " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
684 " stb %%o0, [%1]\n"
685 " stb %%o0, [%1 + 1]\n"
686 : "=&r" (value)
687 : "r" (flags), "r" (dst), "r" (src)
688 : "cc", "o0"
689 );
690 return value;
691 }
692
693 #endif /* SPARC_V8_ASSEMBLY */
694
695 #ifdef SPARC_V9_ASSEMBLY
696
697 static inline uae_u32 sparc_v9_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
698 {
699 uae_u32 value;
700 __asm__ ("\n"
701 " sll %2, 24, %%o0\n"
702 " sll %3, 24, %%o1\n"
703 " addcc %%o0, %%o1, %%o0\n"
704 " rd %%ccr, %%o1\n"
705 " srl %%o0, 24, %0\n"
706 " stb %%o1, [%1]\n"
707 " stb %%o1, [%1+1]\n"
708 : "=&r" (value)
709 : "r" (flags), "r" (dst), "r" (src)
710 : "cc", "o0", "o1"
711 );
712 return value;
713 }
714
715 static inline uae_u32 sparc_v9_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
716 {
717 uae_u32 value;
718 __asm__ ("\n"
719 " sll %2, 16, %%o0\n"
720 " sll %3, 16, %%o1\n"
721 " addcc %%o0, %%o1, %%o0\n"
722 " rd %%ccr, %%o1\n"
723 " srl %%o0, 16, %0\n"
724 " stb %%o1, [%1]\n"
725 " stb %%o1, [%1+1]\n"
726 : "=&r" (value)
727 : "r" (flags), "r" (dst), "r" (src)
728 : "cc", "o0", "o1"
729 );
730 return value;
731 }
732
733 static inline uae_u32 sparc_v9_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
734 {
735 uae_u32 value;
736 __asm__ ("\n"
737 " addcc %2, %3, %0\n"
738 " rd %%ccr, %%o0\n"
739 " stb %%o0, [%1]\n"
740 " stb %%o0, [%1+1]\n"
741 : "=&r" (value)
742 : "r" (flags), "r" (dst), "r" (src)
743 : "cc", "o0"
744 );
745 return value;
746 }
747
748 static inline uae_u32 sparc_v9_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
749 {
750 uae_u32 value;
751 __asm__ ("\n"
752 " sll %2, 24, %%o0\n"
753 " sll %3, 24, %%o1\n"
754 " subcc %%o0, %%o1, %%o0\n"
755 " rd %%ccr, %%o1\n"
756 " srl %%o0, 24, %0\n"
757 " stb %%o1, [%1]\n"
758 " stb %%o1, [%1+1]\n"
759 : "=&r" (value)
760 : "r" (flags), "r" (dst), "r" (src)
761 : "cc", "o0", "o1"
762 );
763 return value;
764 }
765
766 static inline uae_u32 sparc_v9_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
767 {
768 uae_u32 value;
769 __asm__ ("\n"
770 " sll %2, 16, %%o0\n"
771 " sll %3, 16, %%o1\n"
772 " subcc %%o0, %%o1, %%o0\n"
773 " rd %%ccr, %%o1\n"
774 " srl %%o0, 16, %0\n"
775 " stb %%o1, [%1]\n"
776 " stb %%o1, [%1+1]\n"
777 : "=&r" (value)
778 : "r" (flags), "r" (dst), "r" (src)
779 : "cc", "o0", "o1"
780 );
781 return value;
782 }
783
784 static inline uae_u32 sparc_v9_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
785 {
786 uae_u32 value;
787 __asm__ ("\n"
788 " subcc %2, %3, %0\n"
789 " rd %%ccr, %%o0\n"
790 " stb %%o0, [%1]\n"
791 " stb %%o0, [%1+1]\n"
792 : "=&r" (value)
793 : "r" (flags), "r" (dst), "r" (src)
794 : "cc", "o0"
795 );
796 return value;
797 }
798
799 static inline void sparc_v9_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
800 {
801 __asm__ ("\n"
802 " sll %1, 24, %%o0\n"
803 " sll %2, 24, %%o1\n"
804 " subcc %%o0, %%o1, %%g0\n"
805 " rd %%ccr, %%o0\n"
806 " stb %%o0, [%0]\n"
807 : /* no outputs */
808 : "r" (flags), "r" (dst), "r" (src)
809 : "cc", "o0", "o1"
810 );
811 }
812
813 static inline void sparc_v9_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
814 {
815 __asm__ ("\n"
816 " sll %1, 16, %%o0\n"
817 " sll %2, 16, %%o1\n"
818 " subcc %%o0, %%o1, %%g0\n"
819 " rd %%ccr, %%o0\n"
820 " stb %%o0, [%0]\n"
821 : /* no outputs */
822 : "r" (flags), "r" (dst), "r" (src)
823 : "cc", "o0", "o1"
824 );
825 }
826
827 static inline void sparc_v9_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
828 {
829 __asm__ ("\n"
830 " subcc %1, %2, %%g0\n"
831 #if 0
832 " subcc %1, %2, %%o1\n"
833 " srl %%o1, 31, %%o0\n"
834 " sll %%o0, 3, %%o0\n"
835 " addx %%o0, %%g0, %%o0\n"
836 " bvs,a .+8\n"
837 " or %%o0, 0x02, %%o0\n"
838 " subcc %%g0, %%o1, %%g0\n"
839 " addx %%g0, 7, %%o1\n"
840 " and %%o1, 0x04, %%o1\n"
841 " or %%o0, %%o1, %%o0\n"
842 #endif
843 #if 0
844 " subcc %1, %2, %%o1\n"
845 " srl %%o1, 31, %%o0\n"
846 " sll %%o0, 3, %%o0\n"
847 " addx %%o0, %%g0, %%o0\n"
848 " bvs,pt,a .+8\n"
849 " or %%o0, 0x02, %%o0\n"
850 " subcc %%g0, %%o1, %%g0\n"
851 " addx %%g0, 7, %%o1\n"
852 " and %%o1, 0x04, %%o1\n"
853 " or %%o0, %%o1, %%o0\n"
854 " stb %%o0, [%0]\n"
855 #endif
856 " rd %%ccr, %%o0\n"
857 " stb %%o0, [%0]\n"
858 : /* no outputs */
859 : "r" (flags), "r" (dst), "r" (src)
860 : "cc", "o0", "o1"
861 );
862 }
863
864 #if 1
865 static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
866 {
867 __asm__ ("\n"
868 " sll %1, 24, %%o0\n"
869 " subcc %%o0, %%g0, %%g0\n"
870 " rd %%ccr, %%o0\n"
871 " stb %%o0, [%0]\n"
872 : /* no outputs */
873 : "r" (flags), "r" (val)
874 : "cc", "o0"
875 );
876 }
877
878 static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
879 {
880 __asm__ ("\n"
881 " sll %1, 16, %%o0\n"
882 " subcc %%o0, %%g0, %%g0\n"
883 " rd %%ccr, %%o0\n"
884 " stb %%o0, [%0]\n"
885 : /* no outputs */
886 : "r" (flags), "r" (val)
887 : "cc", "o0"
888 );
889 }
890
891 static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
892 {
893 __asm__ ("\n"
894 " subcc %1, %%g0, %%g0\n"
895 " rd %%ccr, %%o0\n"
896 " stb %%o0, [%0]\n"
897 : /* no outputs */
898 : "r" (flags), "r" (val)
899 : "cc", "o0"
900 );
901 }
902 #else
903 static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
904 {
905 __asm__ ("\n"
906 " sll %1, 24, %%o0\n"
907 " subcc %%o0, %%g0, %%o1\n"
908 " srl %%o1, 31, %%o0\n"
909 " sll %%o0, 3, %%o0\n"
910 " addx %%o0, %%g0, %%o0\n"
911 " bvs,a .+8\n"
912 " or %%o0, 0x02, %%o0\n"
913 " subcc %%g0, %%o1, %%g0\n"
914 " addx %%g0, 7, %%o1\n"
915 " and %%o1, 0x04, %%o1\n"
916 " or %%o0, %%o1, %%o0\n"
917 " stb %%o0, [%0]\n"
918 : /* no outputs */
919 : "r" (flags), "r" (val)
920 : "cc", "o0", "o1"
921 );
922 }
923
924 static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
925 {
926 __asm__ ("\n"
927 " sll %1, 16, %%o0\n"
928 " subcc %%o0, %%g0, %%o1\n"
929 " srl %%o1, 31, %%o0\n"
930 " sll %%o0, 3, %%o0\n"
931 " addx %%o0, %%g0, %%o0\n"
932 " bvs,a .+8\n"
933 " or %%o0, 0x02, %%o0\n"
934 " subcc %%g0, %%o1, %%g0\n"
935 " addx %%g0, 7, %%o1\n"
936 " and %%o1, 0x04, %%o1\n"
937 " or %%o0, %%o1, %%o0\n"
938 " stb %%o0, [%0]\n"
939 : /* no outputs */
940 : "r" (flags), "r" (val)
941 : "cc", "o0", "o1"
942 );
943 }
944
945 static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
946 {
947 __asm__ ("\n"
948 " subcc %1, %%g0, %%o1\n"
949 " srl %%o1, 31, %%o0\n"
950 " sll %%o0, 3, %%o0\n"
951 " addx %%o0, %%g0, %%o0\n"
952 " bvs,a .+8\n"
953 " or %%o0, 0x02, %%o0\n"
954 " subcc %%g0, %%o1, %%g0\n"
955 " addx %%g0, 7, %%o1\n"
956 " and %%o1, 0x04, %%o1\n"
957 " or %%o0, %%o1, %%o0\n"
958 " stb %%o0, [%0]\n"
959 : /* no outputs */
960 : "r" (flags), "r" (val)
961 : "cc", "o0", "o1"
962 );
963 }
964 #endif
965
966 static inline uae_u32 sparc_v9_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
967 {
968 uae_u32 value;
969 __asm__ ("\n"
970 " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
971 " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
972 " addxcc %2, %3, %0\n"
973 : "=&r" (value)
974 : "r" (flags), "r" (dst), "r" (src)
975 : "cc", "o0", "o1"
976 );
977 return value;
978 }
979
980 static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
981 {
982 uae_u32 value;
983 __asm__ ("\n"
984 " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
985 " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
986 " addxcc %2, %3, %0\n"
987 " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
988 " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
989 " addx %%o0, %%g0, %%o0 ! X,C flags\n"
990 " bl,a .+8\n"
991 " or %%o0, 0x08, %%o0 ! N flag\n"
992 " bvs,a .+8\n"
993 " or %%o0, 0x02, %%o0 ! V flag\n"
994 " bnz,a .+8\n"
995 " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
996 " stb %%o0, [%1]\n"
997 " stb %%o0, [%1 + 1]\n"
998 : "=&r" (value)
999 : "r" (flags), "r" (dst), "r" (src)
1000 : "cc", "o0"
1001 );
1002 return value;
1003 }
1004
1005 #endif /* SPARC_V9_ASSEMBLY */
1006
1007 #endif
1008
1009 #else
1010
1011 struct flag_struct {
1012 unsigned int c;
1013 unsigned int z;
1014 unsigned int n;
1015 unsigned int v;
1016 unsigned int x;
1017 };
1018
1019 extern struct flag_struct regflags;
1020
1021 #define ZFLG (regflags.z)
1022 #define NFLG (regflags.n)
1023 #define CFLG (regflags.c)
1024 #define VFLG (regflags.v)
1025 #define XFLG (regflags.x)
1026
1027 #define SET_CFLG(x) (CFLG = (x))
1028 #define SET_NFLG(x) (NFLG = (x))
1029 #define SET_VFLG(x) (VFLG = (x))
1030 #define SET_ZFLG(x) (ZFLG = (x))
1031 #define SET_XFLG(x) (XFLG = (x))
1032
1033 #define GET_CFLG CFLG
1034 #define GET_NFLG NFLG
1035 #define GET_VFLG VFLG
1036 #define GET_ZFLG ZFLG
1037 #define GET_XFLG XFLG
1038
1039 #define CLEAR_CZNV do { \
1040 SET_CFLG (0); \
1041 SET_ZFLG (0); \
1042 SET_NFLG (0); \
1043 SET_VFLG (0); \
1044 } while (0)
1045
1046 #define COPY_CARRY (SET_XFLG (GET_CFLG))
1047
1048 static __inline__ int cctrue(const int cc)
1049 {
1050 switch(cc){
1051 case 0: return 1; /* T */
1052 case 1: return 0; /* F */
1053 case 2: return !CFLG && !ZFLG; /* HI */
1054 case 3: return CFLG || ZFLG; /* LS */
1055 case 4: return !CFLG; /* CC */
1056 case 5: return CFLG; /* CS */
1057 case 6: return !ZFLG; /* NE */
1058 case 7: return ZFLG; /* EQ */
1059 case 8: return !VFLG; /* VC */
1060 case 9: return VFLG; /* VS */
1061 case 10:return !NFLG; /* PL */
1062 case 11:return NFLG; /* MI */
1063 case 12:return NFLG == VFLG; /* GE */
1064 case 13:return NFLG != VFLG; /* LT */
1065 case 14:return !ZFLG && (NFLG == VFLG); /* GT */
1066 case 15:return ZFLG || (NFLG != VFLG); /* LE */
1067 }
1068 return 0;
1069 }
1070
1071 #endif /* OPTIMIZED_FLAGS */
1072
1073 #endif /* M68K_FLAGS_H */