ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/m68k.h
Revision: 1.5
Committed: 2001-07-13T10:13:58Z (22 years, 11 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: snapshot-15012002
Changes since 1.4: +261 -43 lines
Log Message:
- merged some code from uae-0.8.16

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