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 (23 years, 4 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

# User Rev Content
1 cebix 1.1 /*
2     * UAE - The Un*x Amiga Emulator
3     *
4     * MC68000 emulation - machine dependent bits
5     *
6     * Copyright 1996 Bernd Schmidt
7     */
8    
9 gbeauche 1.5 #ifndef M68K_FLAGS_H
10     #define M68K_FLAGS_H
11    
12     #ifdef OPTIMIZED_FLAGS
13    
14 cebix 1.2 #if defined(__i386__) && defined(X86_ASSEMBLY)
15 cebix 1.1
16 gbeauche 1.5 #ifndef SAHF_SETO_PROFITABLE
17    
18 cebix 1.1 struct flag_struct {
19 gbeauche 1.5 uae_u32 cznv;
20     uae_u32 x;
21 cebix 1.1 };
22    
23 gbeauche 1.5 #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 cebix 1.1
43 gbeauche 1.5 #define COPY_CARRY (regflags.x = regflags.cznv)
44 cebix 1.1
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 gbeauche 1.5 #define optflag_testl(v) \
76     __asm__ __volatile__ ("andl %1,%1\n\t" \
77 cebix 1.1 "pushfl\n\t" \
78     "popl %0\n\t" \
79     : "=r" (regflags.cznv) : "r" (v) : "cc")
80    
81 gbeauche 1.5 #define optflag_testw(v) \
82     __asm__ __volatile__ ("andw %w1,%w1\n\t" \
83 cebix 1.1 "pushfl\n\t" \
84     "popl %0\n\t" \
85     : "=r" (regflags.cznv) : "r" (v) : "cc")
86    
87 gbeauche 1.5 #define optflag_testb(v) \
88     __asm__ __volatile__ ("andb %b1,%b1\n\t" \
89 cebix 1.1 "pushfl\n\t" \
90     "popl %0\n\t" \
91     : "=r" (regflags.cznv) : "q" (v) : "cc")
92    
93 gbeauche 1.5 #define optflag_addl(v, s, d) do { \
94 cebix 1.1 __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 gbeauche 1.5 #define optflag_addw(v, s, d) do { \
102 cebix 1.1 __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 gbeauche 1.5 #define optflag_addb(v, s, d) do { \
110 cebix 1.1 __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 gbeauche 1.5 #define optflag_subl(v, s, d) do { \
118 cebix 1.1 __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 gbeauche 1.5 #define optflag_subw(v, s, d) do { \
126 cebix 1.1 __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 gbeauche 1.5 #define optflag_subb(v, s, d) do { \
134 cebix 1.1 __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 gbeauche 1.5 #define optflag_cmpl(s, d) \
142 cebix 1.1 __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 gbeauche 1.5 #define optflag_cmpw(s, d) \
148 cebix 1.1 __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 gbeauche 1.5 #define optflag_cmpb(s, d) \
154 cebix 1.1 __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 cebix 1.2
159 gbeauche 1.5 #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 cebix 1.2 #elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
332    
333     struct flag_struct {
334 cebix 1.4 unsigned char nzvc;
335     unsigned char x;
336 cebix 1.2 };
337    
338 cebix 1.4 extern struct flag_struct regflags;
339 cebix 1.2
340 gbeauche 1.5 #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 cebix 1.2
360 cebix 1.4 #define COPY_CARRY (regflags.x = regflags.nzvc)
361 cebix 1.2
362     static __inline__ int cctrue(int cc)
363     {
364 cebix 1.4 uae_u32 nzvc = regflags.nzvc;
365 cebix 1.2 switch(cc){
366 cebix 1.4 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 cebix 1.2 case 14:
381 cebix 1.4 nzvc &= 0x0e;
382     return (((nzvc << 2) ^ nzvc) & 0x0c) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
383 cebix 1.2 case 15:
384 cebix 1.4 nzvc &= 0x0e;
385     return (((nzvc << 2) ^ nzvc) & 0x0c) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
386 cebix 1.2 }
387     return 0;
388     }
389    
390     #ifdef SPARC_V8_ASSEMBLY
391    
392 cebix 1.4 static inline uae_u32 sparc_v8_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
393 cebix 1.2 {
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 cebix 1.4 " 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 cebix 1.2 " bvs,a .+8\n"
407 cebix 1.4 " or %%o1, 0x02, %%o1 ! V flag\n"
408     " stb %%o1, [%1]\n"
409 cebix 1.2 : "=&r" (value)
410 cebix 1.4 : "r" (flags), "r" (dst), "r" (src)
411 cebix 1.2 : "cc", "o0", "o1"
412     );
413     return value;
414     }
415    
416 cebix 1.4 static inline uae_u32 sparc_v8_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
417 cebix 1.2 {
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 cebix 1.4 " 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 cebix 1.2 " bvs,a .+8\n"
431 cebix 1.4 " or %%o1, 0x02, %%o1 ! V flag\n"
432     " stb %%o1, [%1]\n"
433 cebix 1.2 : "=&r" (value)
434 cebix 1.4 : "r" (flags), "r" (dst), "r" (src)
435 cebix 1.2 : "cc", "o0", "o1"
436     );
437     return value;
438     }
439    
440 cebix 1.4 static inline uae_u32 sparc_v8_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
441 cebix 1.2 {
442     uae_u32 value;
443     __asm__ ("\n"
444     " addcc %2, %3, %0\n"
445 cebix 1.4 " 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 cebix 1.2 " bvs,a .+8\n"
452 cebix 1.4 " or %%o0, 0x02, %%o0 ! V flag\n"
453     " stb %%o0, [%1]\n"
454 cebix 1.2 : "=&r" (value)
455 cebix 1.4 : "r" (flags), "r" (dst), "r" (src)
456     : "cc", "o0"
457 cebix 1.2 );
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 cebix 1.4 }
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 cebix 1.2 }
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 cebix 1.1
983 gbeauche 1.5 #endif
984    
985 cebix 1.1 #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 gbeauche 1.5 #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 cebix 1.1 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 gbeauche 1.5 #endif /* OPTIMIZED_FLAGS */
1048    
1049     #endif /* M68K_FLAGS_H */