ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/m68k.h
Revision: 1.7
Committed: 2006-02-06T22:55:44Z (18 years, 4 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: nigel-build-19
Changes since 1.6: +19 -12 lines
Log Message:
Manually emit LAHF instructions so that 64-bit assemblers can grok it

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