ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/m68k.h
Revision: 1.6
Committed: 2002-11-05T11:59:12Z (21 years, 8 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13, nigel-build-16, nigel-build-17, nigel-build-15
Changes since 1.5: +34 -31 lines
Log Message:
OPTIMIZED_FLAGS for x86-64 with the pushf/pop method since sahf/lahf are
invalid in long mode.

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 /* Is there any way to do this without declaring *all* memory clobbered?
223 I.e. any way to tell gcc that some byte-sized value is in %al? */
224 #define optflag_testl(v) \
225 __asm__ __volatile__ ("andl %0,%0\n\t" \
226 "lahf\n\t" \
227 "seto %%al\n\t" \
228 "movb %%al,regflags\n\t" \
229 "movb %%ah,regflags+1\n\t" \
230 : : "r" (v) : "%eax","cc","memory")
231
232 #define optflag_testw(v) \
233 __asm__ __volatile__ ("andw %w0,%w0\n\t" \
234 "lahf\n\t" \
235 "seto %%al\n\t" \
236 "movb %%al,regflags\n\t" \
237 "movb %%ah,regflags+1\n\t" \
238 : : "r" (v) : "%eax","cc","memory")
239
240 #define optflag_testb(v) \
241 __asm__ __volatile__ ("andb %b0,%b0\n\t" \
242 "lahf\n\t" \
243 "seto %%al\n\t" \
244 "movb %%al,regflags\n\t" \
245 "movb %%ah,regflags+1\n\t" \
246 : : "q" (v) : "%eax","cc","memory")
247
248 #define optflag_addl(v, s, d) do { \
249 __asm__ __volatile__ ("addl %k1,%k0\n\t" \
250 "lahf\n\t" \
251 "seto %%al\n\t" \
252 "movb %%al,regflags\n\t" \
253 "movb %%ah,regflags+1\n\t" \
254 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
255 COPY_CARRY; \
256 } while (0)
257
258 #define optflag_addw(v, s, d) do { \
259 __asm__ __volatile__ ("addw %w1,%w0\n\t" \
260 "lahf\n\t" \
261 "seto %%al\n\t" \
262 "movb %%al,regflags\n\t" \
263 "movb %%ah,regflags+1\n\t" \
264 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
265 COPY_CARRY; \
266 } while (0)
267
268 #define optflag_addb(v, s, d) do { \
269 __asm__ __volatile__ ("addb %b1,%b0\n\t" \
270 "lahf\n\t" \
271 "seto %%al\n\t" \
272 "movb %%al,regflags\n\t" \
273 "movb %%ah,regflags+1\n\t" \
274 : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
275 COPY_CARRY; \
276 } while (0)
277
278 #define optflag_subl(v, s, d) do { \
279 __asm__ __volatile__ ("subl %k1,%k0\n\t" \
280 "lahf\n\t" \
281 "seto %%al\n\t" \
282 "movb %%al,regflags\n\t" \
283 "movb %%ah,regflags+1\n\t" \
284 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
285 COPY_CARRY; \
286 } while (0)
287
288 #define optflag_subw(v, s, d) do { \
289 __asm__ __volatile__ ("subw %w1,%w0\n\t" \
290 "lahf\n\t" \
291 "seto %%al\n\t" \
292 "movb %%al,regflags\n\t" \
293 "movb %%ah,regflags+1\n\t" \
294 : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
295 COPY_CARRY; \
296 } while (0)
297
298 #define optflag_subb(v, s, d) do { \
299 __asm__ __volatile__ ("subb %b1,%b0\n\t" \
300 "lahf\n\t" \
301 "seto %%al\n\t" \
302 "movb %%al,regflags\n\t" \
303 "movb %%ah,regflags+1\n\t" \
304 : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
305 COPY_CARRY; \
306 } while (0)
307
308 #define optflag_cmpl(s, d) \
309 __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
310 "lahf\n\t" \
311 "seto %%al\n\t" \
312 "movb %%al,regflags\n\t" \
313 "movb %%ah,regflags+1\n\t" \
314 : : "rmi" (s), "r" (d) : "%eax","cc","memory")
315
316 #define optflag_cmpw(s, d) \
317 __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
318 "lahf\n\t" \
319 "seto %%al\n\t" \
320 "movb %%al,regflags\n\t" \
321 "movb %%ah,regflags+1\n\t" \
322 : : "rmi" (s), "r" (d) : "%eax","cc","memory");
323
324 #define optflag_cmpb(s, d) \
325 __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
326 "lahf\n\t" \
327 "seto %%al\n\t" \
328 "movb %%al,regflags\n\t" \
329 "movb %%ah,regflags+1\n\t" \
330 : : "qmi" (s), "q" (d) : "%eax","cc","memory")
331
332 #endif
333
334 #elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
335
336 struct flag_struct {
337 unsigned char nzvc;
338 unsigned char x;
339 };
340
341 extern struct flag_struct regflags;
342
343 #define FLAGVAL_Z 0x04
344 #define FLAGVAL_N 0x08
345
346 #define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2))
347 #define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1))
348 #define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1))
349 #define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3))
350 #define SET_XFLG(y) (regflags.x = (y))
351
352 #define GET_ZFLG ((regflags.nzvc >> 2) & 1)
353 #define GET_CFLG (regflags.nzvc & 1)
354 #define GET_VFLG ((regflags.nzvc >> 1) & 1)
355 #define GET_NFLG ((regflags.nzvc >> 3) & 1)
356 #define GET_XFLG (regflags.x & 1)
357
358 #define CLEAR_CZNV (regflags.nzvc = 0)
359 #define GET_CZNV (reflags.nzvc)
360 #define IOR_CZNV(X) (refglags.nzvc |= (X))
361 #define SET_CZNV(X) (regflags.nzvc = (X))
362
363 #define COPY_CARRY (regflags.x = regflags.nzvc)
364
365 static __inline__ int cctrue(int cc)
366 {
367 uae_u32 nzvc = regflags.nzvc;
368 switch(cc){
369 case 0: return 1; /* T */
370 case 1: return 0; /* F */
371 case 2: return (nzvc & 0x05) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
372 case 3: return (nzvc & 0x05) != 0; /* GET_CFLG || GET_ZFLG; LS */
373 case 4: return (nzvc & 1) == 0; /* !GET_CFLG; CC */
374 case 5: return (nzvc & 1) != 0; /* GET_CFLG; CS */
375 case 6: return (nzvc & 0x04) == 0; /* !GET_ZFLG; NE */
376 case 7: return (nzvc & 0x04) != 0; /* GET_ZFLG; EQ */
377 case 8: return (nzvc & 0x02) == 0;/* !GET_VFLG; VC */
378 case 9: return (nzvc & 0x02) != 0;/* GET_VFLG; VS */
379 case 10:return (nzvc & 0x08) == 0; /* !GET_NFLG; PL */
380 case 11:return (nzvc & 0x08) != 0; /* GET_NFLG; MI */
381 case 12:return (((nzvc << 2) ^ nzvc) & 0x08) == 0; /* GET_NFLG == GET_VFLG; GE */
382 case 13:return (((nzvc << 2) ^ nzvc) & 0x08) != 0;/* GET_NFLG != GET_VFLG; LT */
383 case 14:
384 nzvc &= 0x0e;
385 return (((nzvc << 2) ^ nzvc) & 0x0c) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
386 case 15:
387 nzvc &= 0x0e;
388 return (((nzvc << 2) ^ nzvc) & 0x0c) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
389 }
390 return 0;
391 }
392
393 #ifdef SPARC_V8_ASSEMBLY
394
395 static inline uae_u32 sparc_v8_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
396 {
397 uae_u32 value;
398 __asm__ ("\n"
399 " sll %2, 24, %%o0\n"
400 " sll %3, 24, %%o1\n"
401 " addcc %%o0, %%o1, %%o0\n"
402 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
403 " srl %%o0, 24, %0\n"
404 " stb %%o1, [%1 + 1]\n"
405 " bl,a .+8\n"
406 " or %%o1, 0x08, %%o1 ! N flag\n"
407 " bz,a .+8\n"
408 " or %%o1, 0x04, %%o1 ! Z flag\n"
409 " bvs,a .+8\n"
410 " or %%o1, 0x02, %%o1 ! V flag\n"
411 " stb %%o1, [%1]\n"
412 : "=&r" (value)
413 : "r" (flags), "r" (dst), "r" (src)
414 : "cc", "o0", "o1"
415 );
416 return value;
417 }
418
419 static inline uae_u32 sparc_v8_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
420 {
421 uae_u32 value;
422 __asm__ ("\n"
423 " sll %2, 16, %%o0\n"
424 " sll %3, 16, %%o1\n"
425 " addcc %%o0, %%o1, %%o0\n"
426 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
427 " srl %%o0, 16, %0\n"
428 " stb %%o1, [%1 + 1]\n"
429 " bl,a .+8\n"
430 " or %%o1, 0x08, %%o1 ! N flag\n"
431 " bz,a .+8\n"
432 " or %%o1, 0x04, %%o1 ! Z flag\n"
433 " bvs,a .+8\n"
434 " or %%o1, 0x02, %%o1 ! V flag\n"
435 " stb %%o1, [%1]\n"
436 : "=&r" (value)
437 : "r" (flags), "r" (dst), "r" (src)
438 : "cc", "o0", "o1"
439 );
440 return value;
441 }
442
443 static inline uae_u32 sparc_v8_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
444 {
445 uae_u32 value;
446 __asm__ ("\n"
447 " addcc %2, %3, %0\n"
448 " addx %%g0, %%g0, %%o0 ! X,C flags\n"
449 " stb %%o0, [%1 + 1]\n"
450 " bl,a .+8\n"
451 " or %%o0, 0x08, %%o0 ! N flag\n"
452 " bz,a .+8\n"
453 " or %%o0, 0x04, %%o0 ! Z flag\n"
454 " bvs,a .+8\n"
455 " or %%o0, 0x02, %%o0 ! V flag\n"
456 " stb %%o0, [%1]\n"
457 : "=&r" (value)
458 : "r" (flags), "r" (dst), "r" (src)
459 : "cc", "o0"
460 );
461 return value;
462 }
463
464 static inline uae_u32 sparc_v8_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
465 {
466 uae_u32 value;
467 __asm__ ("\n"
468 " sll %2, 24, %%o0\n"
469 " sll %3, 24, %%o1\n"
470 " subcc %%o0, %%o1, %%o0\n"
471 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
472 " srl %%o0, 24, %0\n"
473 " stb %%o1, [%1 + 1]\n"
474 " bl,a .+8\n"
475 " or %%o1, 0x08, %%o1 ! N flag\n"
476 " bz,a .+8\n"
477 " or %%o1, 0x04, %%o1 ! Z flag\n"
478 " bvs,a .+8\n"
479 " or %%o1, 0x02, %%o1 ! V flag\n"
480 " stb %%o1, [%1]\n"
481 : "=&r" (value)
482 : "r" (flags), "r" (dst), "r" (src)
483 : "cc", "o0", "o1"
484 );
485 return value;
486 }
487
488 static inline uae_u32 sparc_v8_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
489 {
490 uae_u32 value;
491 __asm__ ("\n"
492 " sll %2, 16, %%o0\n"
493 " sll %3, 16, %%o1\n"
494 " subcc %%o0, %%o1, %%o0\n"
495 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
496 " srl %%o0, 16, %0\n"
497 " stb %%o1, [%1 + 1]\n"
498 " bl,a .+8\n"
499 " or %%o1, 0x08, %%o1 ! N flag\n"
500 " bz,a .+8\n"
501 " or %%o1, 0x04, %%o1 ! Z flag\n"
502 " bvs,a .+8\n"
503 " or %%o1, 0x02, %%o1 ! V flag\n"
504 " stb %%o1, [%1]\n"
505 : "=&r" (value)
506 : "r" (flags), "r" (dst), "r" (src)
507 : "cc", "o0", "o1"
508 );
509 return value;
510 }
511
512 static inline uae_u32 sparc_v8_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
513 {
514 uae_u32 value;
515 __asm__ ("\n"
516 " subcc %2, %3, %0\n"
517 " addx %%g0, %%g0, %%o0 ! X,C flags\n"
518 " stb %%o0, [%1 + 1]\n"
519 " bl,a .+8\n"
520 " or %%o0, 0x08, %%o0 ! N flag\n"
521 " bz,a .+8\n"
522 " or %%o0, 0x04, %%o0 ! Z flag\n"
523 " bvs,a .+8\n"
524 " or %%o0, 0x02, %%o0 ! V flag\n"
525 " stb %%o0, [%1]\n"
526 : "=&r" (value)
527 : "r" (flags), "r" (dst), "r" (src)
528 : "cc", "o0"
529 );
530 return value;
531 }
532
533 static inline void sparc_v8_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
534 {
535 __asm__ ("\n"
536 " sll %1, 24, %%o0\n"
537 " sll %2, 24, %%o1\n"
538 " subcc %%o0, %%o1, %%g0\n"
539 " addx %%g0, %%g0, %%o0 ! C flag\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, [%0]\n"
547 : /* no outputs */
548 : "r" (flags), "r" (dst), "r" (src)
549 : "cc", "o0", "o1"
550 );
551 }
552
553 static inline void sparc_v8_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
554 {
555 __asm__ ("\n"
556 " sll %1, 16, %%o0\n"
557 " sll %2, 16, %%o1\n"
558 " subcc %%o0, %%o1, %%g0\n"
559 " addx %%g0, %%g0, %%o0 ! C flag\n"
560 " bl,a .+8\n"
561 " or %%o0, 0x08, %%o0 ! N flag\n"
562 " bz,a .+8\n"
563 " or %%o0, 0x04, %%o0 ! Z flag\n"
564 " bvs,a .+8\n"
565 " or %%o0, 0x02, %%o0 ! V flag\n"
566 " stb %%o0, [%0]\n"
567 : /* no outputs */
568 : "r" (flags), "r" (dst), "r" (src)
569 : "cc", "o0", "o1"
570 );
571 }
572
573 static inline void sparc_v8_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
574 {
575 __asm__ ("\n"
576 " subcc %1, %2, %%o1\n"
577 " srl %%o1, 31, %%o0\n"
578 " sll %%o0, 3, %%o0\n"
579 " addx %%o0, %%g0, %%o0\n"
580 " bvs,a .+8\n"
581 " or %%o0, 0x02, %%o0\n"
582 " subcc %%g0, %%o1, %%g0\n"
583 " addx %%g0, 7, %%o1\n"
584 " and %%o1, 0x04, %%o1\n"
585 " or %%o0, %%o1, %%o0\n"
586 " stb %%o0, [%0]\n"
587 : /* no outputs */
588 : "r" (flags), "r" (dst), "r" (src)
589 : "cc", "o0", "o1"
590 );
591 }
592
593 static inline uae_u32 sparc_v8_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
594 {
595 uae_u32 value;
596 __asm__ ("\n"
597 " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
598 " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
599 " addxcc %2, %3, %0\n"
600 : "=&r" (value)
601 : "r" (flags), "r" (dst), "r" (src)
602 : "cc", "o0", "o1"
603 );
604 return value;
605 }
606
607 #if 0
608 VERY SLOW...
609 static inline uae_u32 sparc_v8_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
610 {
611 uae_u32 value;
612 __asm__ ("\n"
613 " sll %2, 24, %%o0\n"
614 " sll %3, 24, %%o1\n"
615 " addcc %%o0, %%o1, %%o0\n"
616 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
617 " bvs,a .+8\n"
618 " or %%o1, 0x02, %%o1 ! V flag\n"
619 " ldub [%1 + 1], %%o2\n"
620 " subcc %%g0, %%o2, %%g0\n"
621 " addx %%g0, %%g0, %%o2\n"
622 " sll %%o2, 24, %%o2\n"
623 " addcc %%o0, %%o2, %%o0\n"
624 " srl %%o0, 24, %0\n"
625 " addx %%g0, %%g0, %%o2\n"
626 " or %%o1, %%o2, %%o1 ! update X,C flags\n"
627 " bl,a .+8\n"
628 " or %%o1, 0x08, %%o1 ! N flag\n"
629 " ldub [%1], %%o0 ! retreive the old NZVC flags (XXX)\n"
630 " bvs,a .+8\n"
631 " or %%o1, 0x02, %%o1 ! update V flag\n"
632 " and %%o0, 0x04, %%o0 ! (XXX) but keep only Z flag\n"
633 " and %%o1, 1, %%o2 ! keep C flag in %%o2\n"
634 " bnz,a .+8\n"
635 " or %%g0, %%g0, %%o0 ! Z flag cleared if non-zero result\n"
636 " stb %%o2, [%1 + 1] ! store the X flag\n"
637 " or %%o1, %%o0, %%o1\n"
638 " stb %%o1, [%1]\n"
639 : "=&r" (value)
640 : "r" (flags), "r" (dst), "r" (src)
641 : "cc", "o0", "o1", "o2"
642 );
643 return value;
644 }
645 #endif
646
647 static inline uae_u32 sparc_v8_flag_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
648 {
649 uae_u32 value;
650 __asm__ ("\n"
651 " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
652 " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
653 " addxcc %2, %3, %0\n"
654 " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
655 " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
656 " addx %%o0, %%g0, %%o0 ! X,C flags\n"
657 " bl,a .+8\n"
658 " or %%o0, 0x08, %%o0 ! N flag\n"
659 " bvs,a .+8\n"
660 " or %%o0, 0x02, %%o0 ! V flag\n"
661 " bnz,a .+8\n"
662 " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
663 " stb %%o0, [%1]\n"
664 " stb %%o0, [%1 + 1]\n"
665 : "=&r" (value)
666 : "r" (flags), "r" (dst), "r" (src)
667 : "cc", "o0"
668 );
669 return value;
670 }
671
672 #endif /* SPARC_V8_ASSEMBLY */
673
674 #ifdef SPARC_V9_ASSEMBLY
675
676 static inline uae_u32 sparc_v9_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
677 {
678 uae_u32 value;
679 __asm__ ("\n"
680 " sll %2, 24, %%o0\n"
681 " sll %3, 24, %%o1\n"
682 " addcc %%o0, %%o1, %%o0\n"
683 " rd %%ccr, %%o1\n"
684 " srl %%o0, 24, %0\n"
685 " stb %%o1, [%1]\n"
686 " stb %%o1, [%1+1]\n"
687 : "=&r" (value)
688 : "r" (flags), "r" (dst), "r" (src)
689 : "cc", "o0", "o1"
690 );
691 return value;
692 }
693
694 static inline uae_u32 sparc_v9_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
695 {
696 uae_u32 value;
697 __asm__ ("\n"
698 " sll %2, 16, %%o0\n"
699 " sll %3, 16, %%o1\n"
700 " addcc %%o0, %%o1, %%o0\n"
701 " rd %%ccr, %%o1\n"
702 " srl %%o0, 16, %0\n"
703 " stb %%o1, [%1]\n"
704 " stb %%o1, [%1+1]\n"
705 : "=&r" (value)
706 : "r" (flags), "r" (dst), "r" (src)
707 : "cc", "o0", "o1"
708 );
709 return value;
710 }
711
712 static inline uae_u32 sparc_v9_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
713 {
714 uae_u32 value;
715 __asm__ ("\n"
716 " addcc %2, %3, %0\n"
717 " rd %%ccr, %%o0\n"
718 " stb %%o0, [%1]\n"
719 " stb %%o0, [%1+1]\n"
720 : "=&r" (value)
721 : "r" (flags), "r" (dst), "r" (src)
722 : "cc", "o0"
723 );
724 return value;
725 }
726
727 static inline uae_u32 sparc_v9_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
728 {
729 uae_u32 value;
730 __asm__ ("\n"
731 " sll %2, 24, %%o0\n"
732 " sll %3, 24, %%o1\n"
733 " subcc %%o0, %%o1, %%o0\n"
734 " rd %%ccr, %%o1\n"
735 " srl %%o0, 24, %0\n"
736 " stb %%o1, [%1]\n"
737 " stb %%o1, [%1+1]\n"
738 : "=&r" (value)
739 : "r" (flags), "r" (dst), "r" (src)
740 : "cc", "o0", "o1"
741 );
742 return value;
743 }
744
745 static inline uae_u32 sparc_v9_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
746 {
747 uae_u32 value;
748 __asm__ ("\n"
749 " sll %2, 16, %%o0\n"
750 " sll %3, 16, %%o1\n"
751 " subcc %%o0, %%o1, %%o0\n"
752 " rd %%ccr, %%o1\n"
753 " srl %%o0, 16, %0\n"
754 " stb %%o1, [%1]\n"
755 " stb %%o1, [%1+1]\n"
756 : "=&r" (value)
757 : "r" (flags), "r" (dst), "r" (src)
758 : "cc", "o0", "o1"
759 );
760 return value;
761 }
762
763 static inline uae_u32 sparc_v9_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
764 {
765 uae_u32 value;
766 __asm__ ("\n"
767 " subcc %2, %3, %0\n"
768 " rd %%ccr, %%o0\n"
769 " stb %%o0, [%1]\n"
770 " stb %%o0, [%1+1]\n"
771 : "=&r" (value)
772 : "r" (flags), "r" (dst), "r" (src)
773 : "cc", "o0"
774 );
775 return value;
776 }
777
778 static inline void sparc_v9_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
779 {
780 __asm__ ("\n"
781 " sll %1, 24, %%o0\n"
782 " sll %2, 24, %%o1\n"
783 " subcc %%o0, %%o1, %%g0\n"
784 " rd %%ccr, %%o0\n"
785 " stb %%o0, [%0]\n"
786 : /* no outputs */
787 : "r" (flags), "r" (dst), "r" (src)
788 : "cc", "o0", "o1"
789 );
790 }
791
792 static inline void sparc_v9_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
793 {
794 __asm__ ("\n"
795 " sll %1, 16, %%o0\n"
796 " sll %2, 16, %%o1\n"
797 " subcc %%o0, %%o1, %%g0\n"
798 " rd %%ccr, %%o0\n"
799 " stb %%o0, [%0]\n"
800 : /* no outputs */
801 : "r" (flags), "r" (dst), "r" (src)
802 : "cc", "o0", "o1"
803 );
804 }
805
806 static inline void sparc_v9_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
807 {
808 __asm__ ("\n"
809 " subcc %1, %2, %%g0\n"
810 #if 0
811 " subcc %1, %2, %%o1\n"
812 " srl %%o1, 31, %%o0\n"
813 " sll %%o0, 3, %%o0\n"
814 " addx %%o0, %%g0, %%o0\n"
815 " bvs,a .+8\n"
816 " or %%o0, 0x02, %%o0\n"
817 " subcc %%g0, %%o1, %%g0\n"
818 " addx %%g0, 7, %%o1\n"
819 " and %%o1, 0x04, %%o1\n"
820 " or %%o0, %%o1, %%o0\n"
821 #endif
822 #if 0
823 " subcc %1, %2, %%o1\n"
824 " srl %%o1, 31, %%o0\n"
825 " sll %%o0, 3, %%o0\n"
826 " addx %%o0, %%g0, %%o0\n"
827 " bvs,pt,a .+8\n"
828 " or %%o0, 0x02, %%o0\n"
829 " subcc %%g0, %%o1, %%g0\n"
830 " addx %%g0, 7, %%o1\n"
831 " and %%o1, 0x04, %%o1\n"
832 " or %%o0, %%o1, %%o0\n"
833 " stb %%o0, [%0]\n"
834 #endif
835 " rd %%ccr, %%o0\n"
836 " stb %%o0, [%0]\n"
837 : /* no outputs */
838 : "r" (flags), "r" (dst), "r" (src)
839 : "cc", "o0", "o1"
840 );
841 }
842
843 #if 1
844 static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
845 {
846 __asm__ ("\n"
847 " sll %1, 24, %%o0\n"
848 " subcc %%o0, %%g0, %%g0\n"
849 " rd %%ccr, %%o0\n"
850 " stb %%o0, [%0]\n"
851 : /* no outputs */
852 : "r" (flags), "r" (val)
853 : "cc", "o0"
854 );
855 }
856
857 static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
858 {
859 __asm__ ("\n"
860 " sll %1, 16, %%o0\n"
861 " subcc %%o0, %%g0, %%g0\n"
862 " rd %%ccr, %%o0\n"
863 " stb %%o0, [%0]\n"
864 : /* no outputs */
865 : "r" (flags), "r" (val)
866 : "cc", "o0"
867 );
868 }
869
870 static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
871 {
872 __asm__ ("\n"
873 " subcc %1, %%g0, %%g0\n"
874 " rd %%ccr, %%o0\n"
875 " stb %%o0, [%0]\n"
876 : /* no outputs */
877 : "r" (flags), "r" (val)
878 : "cc", "o0"
879 );
880 }
881 #else
882 static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
883 {
884 __asm__ ("\n"
885 " sll %1, 24, %%o0\n"
886 " subcc %%o0, %%g0, %%o1\n"
887 " srl %%o1, 31, %%o0\n"
888 " sll %%o0, 3, %%o0\n"
889 " addx %%o0, %%g0, %%o0\n"
890 " bvs,a .+8\n"
891 " or %%o0, 0x02, %%o0\n"
892 " subcc %%g0, %%o1, %%g0\n"
893 " addx %%g0, 7, %%o1\n"
894 " and %%o1, 0x04, %%o1\n"
895 " or %%o0, %%o1, %%o0\n"
896 " stb %%o0, [%0]\n"
897 : /* no outputs */
898 : "r" (flags), "r" (val)
899 : "cc", "o0", "o1"
900 );
901 }
902
903 static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
904 {
905 __asm__ ("\n"
906 " sll %1, 16, %%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_32(flag_struct *flags, uae_u32 val)
925 {
926 __asm__ ("\n"
927 " subcc %1, %%g0, %%o1\n"
928 " srl %%o1, 31, %%o0\n"
929 " sll %%o0, 3, %%o0\n"
930 " addx %%o0, %%g0, %%o0\n"
931 " bvs,a .+8\n"
932 " or %%o0, 0x02, %%o0\n"
933 " subcc %%g0, %%o1, %%g0\n"
934 " addx %%g0, 7, %%o1\n"
935 " and %%o1, 0x04, %%o1\n"
936 " or %%o0, %%o1, %%o0\n"
937 " stb %%o0, [%0]\n"
938 : /* no outputs */
939 : "r" (flags), "r" (val)
940 : "cc", "o0", "o1"
941 );
942 }
943 #endif
944
945 static inline uae_u32 sparc_v9_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
946 {
947 uae_u32 value;
948 __asm__ ("\n"
949 " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
950 " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
951 " addxcc %2, %3, %0\n"
952 : "=&r" (value)
953 : "r" (flags), "r" (dst), "r" (src)
954 : "cc", "o0", "o1"
955 );
956 return value;
957 }
958
959 static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
960 {
961 uae_u32 value;
962 __asm__ ("\n"
963 " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
964 " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
965 " addxcc %2, %3, %0\n"
966 " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
967 " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
968 " addx %%o0, %%g0, %%o0 ! X,C flags\n"
969 " bl,a .+8\n"
970 " or %%o0, 0x08, %%o0 ! N flag\n"
971 " bvs,a .+8\n"
972 " or %%o0, 0x02, %%o0 ! V flag\n"
973 " bnz,a .+8\n"
974 " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
975 " stb %%o0, [%1]\n"
976 " stb %%o0, [%1 + 1]\n"
977 : "=&r" (value)
978 : "r" (flags), "r" (dst), "r" (src)
979 : "cc", "o0"
980 );
981 return value;
982 }
983
984 #endif /* SPARC_V9_ASSEMBLY */
985
986 #endif
987
988 #else
989
990 struct flag_struct {
991 unsigned int c;
992 unsigned int z;
993 unsigned int n;
994 unsigned int v;
995 unsigned int x;
996 };
997
998 extern struct flag_struct regflags;
999
1000 #define ZFLG (regflags.z)
1001 #define NFLG (regflags.n)
1002 #define CFLG (regflags.c)
1003 #define VFLG (regflags.v)
1004 #define XFLG (regflags.x)
1005
1006 #define SET_CFLG(x) (CFLG = (x))
1007 #define SET_NFLG(x) (NFLG = (x))
1008 #define SET_VFLG(x) (VFLG = (x))
1009 #define SET_ZFLG(x) (ZFLG = (x))
1010 #define SET_XFLG(x) (XFLG = (x))
1011
1012 #define GET_CFLG CFLG
1013 #define GET_NFLG NFLG
1014 #define GET_VFLG VFLG
1015 #define GET_ZFLG ZFLG
1016 #define GET_XFLG XFLG
1017
1018 #define CLEAR_CZNV do { \
1019 SET_CFLG (0); \
1020 SET_ZFLG (0); \
1021 SET_NFLG (0); \
1022 SET_VFLG (0); \
1023 } while (0)
1024
1025 #define COPY_CARRY (SET_XFLG (GET_CFLG))
1026
1027 static __inline__ int cctrue(const int cc)
1028 {
1029 switch(cc){
1030 case 0: return 1; /* T */
1031 case 1: return 0; /* F */
1032 case 2: return !CFLG && !ZFLG; /* HI */
1033 case 3: return CFLG || ZFLG; /* LS */
1034 case 4: return !CFLG; /* CC */
1035 case 5: return CFLG; /* CS */
1036 case 6: return !ZFLG; /* NE */
1037 case 7: return ZFLG; /* EQ */
1038 case 8: return !VFLG; /* VC */
1039 case 9: return VFLG; /* VS */
1040 case 10:return !NFLG; /* PL */
1041 case 11:return NFLG; /* MI */
1042 case 12:return NFLG == VFLG; /* GE */
1043 case 13:return NFLG != VFLG; /* LT */
1044 case 14:return !ZFLG && (NFLG == VFLG); /* GT */
1045 case 15:return ZFLG || (NFLG != VFLG); /* LE */
1046 }
1047 return 0;
1048 }
1049
1050 #endif /* OPTIMIZED_FLAGS */
1051
1052 #endif /* M68K_FLAGS_H */