ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/m68k.h
Revision: 1.3
Committed: 1999-10-28T16:00:26Z (25 years ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.2: +113 -147 lines
Log Message:
- new SPARC optimizations from Gwenole

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 cebix 1.2 #if defined(__i386__) && defined(X86_ASSEMBLY)
10 cebix 1.1
11     struct flag_struct {
12     unsigned int cznv;
13     unsigned int x;
14     };
15    
16     #define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6))
17     #define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1))
18     #define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11))
19     #define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7))
20     #define SET_XFLG(y) (regflags.x = (y))
21    
22     #define GET_ZFLG ((regflags.cznv >> 6) & 1)
23     #define GET_CFLG (regflags.cznv & 1)
24     #define GET_VFLG ((regflags.cznv >> 11) & 1)
25     #define GET_NFLG ((regflags.cznv >> 7) & 1)
26     #define GET_XFLG (regflags.x & 1)
27    
28     #define CLEAR_CZNV (regflags.cznv = 0)
29     #define COPY_CARRY (regflags.x = regflags.cznv)
30    
31     extern struct flag_struct regflags __asm__ ("regflags");
32    
33     static __inline__ int cctrue(int cc)
34     {
35     uae_u32 cznv = regflags.cznv;
36     switch(cc){
37     case 0: return 1; /* T */
38     case 1: return 0; /* F */
39     case 2: return (cznv & 0x41) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
40     case 3: return (cznv & 0x41) != 0; /* GET_CFLG || GET_ZFLG; LS */
41     case 4: return (cznv & 1) == 0; /* !GET_CFLG; CC */
42     case 5: return (cznv & 1) != 0; /* GET_CFLG; CS */
43     case 6: return (cznv & 0x40) == 0; /* !GET_ZFLG; NE */
44     case 7: return (cznv & 0x40) != 0; /* GET_ZFLG; EQ */
45     case 8: return (cznv & 0x800) == 0;/* !GET_VFLG; VC */
46     case 9: return (cznv & 0x800) != 0;/* GET_VFLG; VS */
47     case 10:return (cznv & 0x80) == 0; /* !GET_NFLG; PL */
48     case 11:return (cznv & 0x80) != 0; /* GET_NFLG; MI */
49     case 12:return (((cznv << 4) ^ cznv) & 0x800) == 0; /* GET_NFLG == GET_VFLG; GE */
50     case 13:return (((cznv << 4) ^ cznv) & 0x800) != 0;/* GET_NFLG != GET_VFLG; LT */
51     case 14:
52     cznv &= 0x8c0;
53     return (((cznv << 4) ^ cznv) & 0x840) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
54     case 15:
55     cznv &= 0x8c0;
56     return (((cznv << 4) ^ cznv) & 0x840) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
57     }
58     return 0;
59     }
60    
61     #define x86_flag_testl(v) \
62     __asm__ __volatile__ ("testl %1,%1\n\t" \
63     "pushfl\n\t" \
64     "popl %0\n\t" \
65     : "=r" (regflags.cznv) : "r" (v) : "cc")
66    
67     #define x86_flag_testw(v) \
68     __asm__ __volatile__ ("testw %w1,%w1\n\t" \
69     "pushfl\n\t" \
70     "popl %0\n\t" \
71     : "=r" (regflags.cznv) : "r" (v) : "cc")
72    
73     #define x86_flag_testb(v) \
74     __asm__ __volatile__ ("testb %b1,%b1\n\t" \
75     "pushfl\n\t" \
76     "popl %0\n\t" \
77     : "=r" (regflags.cznv) : "q" (v) : "cc")
78    
79     #define x86_flag_addl(v, s, d) do { \
80     __asm__ __volatile__ ("addl %k2,%k1\n\t" \
81     "pushfl\n\t" \
82     "popl %0\n\t" \
83     : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
84     COPY_CARRY; \
85     } while (0)
86    
87     #define x86_flag_addw(v, s, d) do { \
88     __asm__ __volatile__ ("addw %w2,%w1\n\t" \
89     "pushfl\n\t" \
90     "popl %0\n\t" \
91     : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
92     COPY_CARRY; \
93     } while (0)
94    
95     #define x86_flag_addb(v, s, d) do { \
96     __asm__ __volatile__ ("addb %b2,%b1\n\t" \
97     "pushfl\n\t" \
98     "popl %0\n\t" \
99     : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
100     COPY_CARRY; \
101     } while (0)
102    
103     #define x86_flag_subl(v, s, d) do { \
104     __asm__ __volatile__ ("subl %k2,%k1\n\t" \
105     "pushfl\n\t" \
106     "popl %0\n\t" \
107     : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
108     COPY_CARRY; \
109     } while (0)
110    
111     #define x86_flag_subw(v, s, d) do { \
112     __asm__ __volatile__ ("subw %w2,%w1\n\t" \
113     "pushfl\n\t" \
114     "popl %0\n\t" \
115     : "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
116     COPY_CARRY; \
117     } while (0)
118    
119     #define x86_flag_subb(v, s, d) do { \
120     __asm__ __volatile__ ("subb %b2,%b1\n\t" \
121     "pushfl\n\t" \
122     "popl %0\n\t" \
123     : "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
124     COPY_CARRY; \
125     } while (0)
126    
127     #define x86_flag_cmpl(s, d) \
128     __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \
129     "pushfl\n\t" \
130     "popl %0\n\t" \
131     : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
132    
133     #define x86_flag_cmpw(s, d) \
134     __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \
135     "pushfl\n\t" \
136     "popl %0\n\t" \
137     : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
138    
139     #define x86_flag_cmpb(s, d) \
140     __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \
141     "pushfl\n\t" \
142     "popl %0\n\t" \
143     : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc")
144 cebix 1.2
145     #elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
146    
147     struct flag_struct {
148 cebix 1.3 union {
149     unsigned short all;
150     unsigned char bytes[2];
151     };
152 cebix 1.2 };
153    
154 cebix 1.3 typedef unsigned short * flags_addr;
155     extern struct flag_struct regflags;
156     #define M68K_FLAGS_ADDR ((flags_addr)(&regflags.all))
157     #define M68K_FLAGS_NZVC regflags.bytes[1]
158     #define M68K_FLAGS_X regflags.bytes[0]
159 cebix 1.2
160 cebix 1.3 #if 0
161    
162     #define SET_ZFLG(y) (M68K_FLAGS_NZVC = (M68K_FLAGS_NZVC & ~0x01) | ((y) & 1))
163     #define SET_CFLG(y) (M68K_FLAGS_NZVC = (M68K_FLAGS_NZVC & ~0x02) | (((y) & 1) << 1))
164     #define SET_XFLG(y) (M68K_FLAGS_X = ((y) & 1) << 1)
165     #define SET_VFLG(y) (M68K_FLAGS_NZVC = (M68K_FLAGS_NZVC & ~0x10) | (((y) & 1) << 4))
166     #define SET_NFLG(y) (M68K_FLAGS_NZVC = (M68K_FLAGS_NZVC & ~0x80) | (((y) & 1) << 7))
167    
168     #define GET_ZFLG (M68K_FLAGS_NZVC & 1)
169     #define GET_CFLG ((M68K_FLAGS_NZVC >> 1) & 1)
170     #define GET_XFLG ((M68K_FLAGS_X >> 1) & 1)
171     #define GET_VFLG ((M68K_FLAGS_NZVC >> 4) & 1)
172     #define GET_NFLG ((M68K_FLAGS_NZVC >> 7) & 1)
173    
174     #define CLEAR_CZNV (M68K_FLAGS_NZVC = 0)
175     #define COPY_CARRY (M68K_FLAGS_X = M68K_FLAGS_NZVC)
176    
177     #else
178    
179     #define M68K_FLAGS_ALL regflags.all
180    
181     #define SET_ZFLG(y) (M68K_FLAGS_ALL = (M68K_FLAGS_ALL & ~0x01) | ((y) & 1))
182     #define SET_CFLG(y) (M68K_FLAGS_ALL = (M68K_FLAGS_ALL & ~0x02) | (((y) & 1) << 1))
183     #define SET_XFLG(y) (M68K_FLAGS_ALL = (M68K_FLAGS_ALL & ~0x200)| (((y) & 1) << 9))
184     #define SET_VFLG(y) (M68K_FLAGS_ALL = (M68K_FLAGS_ALL & ~0x10) | (((y) & 1) << 4))
185     #define SET_NFLG(y) (M68K_FLAGS_ALL = (M68K_FLAGS_ALL & ~0x80) | (((y) & 1) << 7))
186    
187     #define GET_ZFLG (M68K_FLAGS_ALL & 1)
188     #define GET_CFLG ((M68K_FLAGS_ALL >> 1) & 1)
189     #define GET_XFLG ((M68K_FLAGS_ALL >> 9) & 1)
190     #define GET_VFLG ((M68K_FLAGS_ALL >> 4) & 1)
191     #define GET_NFLG ((M68K_FLAGS_ALL >> 7) & 1)
192    
193     #define CLEAR_CZNV (M68K_FLAGS_NZVC = 0)
194     #define COPY_CARRY (M68K_FLAGS_X = M68K_FLAGS_NZVC)
195 cebix 1.2
196 cebix 1.3 #endif
197 cebix 1.2
198     static __inline__ int cctrue(int cc)
199     {
200 cebix 1.3 uae_u32 nzvc = M68K_FLAGS_NZVC;
201 cebix 1.2 switch(cc){
202 cebix 1.3 case 0: return 1; /* T */
203     case 1: return 0; /* F */
204     case 2: return (nzvc & 0x03) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
205     case 3: return (nzvc & 0x03) != 0; /* GET_CFLG || GET_ZFLG; LS */
206     case 4: return (nzvc & 0x02) == 0; /* !GET_CFLG; CC */
207     case 5: return (nzvc & 0x02) != 0; /* GET_CFLG; CS */
208     case 6: return (nzvc & 0x01) == 0; /* !GET_ZFLG; NE */
209     case 7: return (nzvc & 0x01) != 0; /* GET_ZFLG; EQ */
210     case 8: return (nzvc & 0x10) == 0; /* !GET_VFLG; VC */
211     case 9: return (nzvc & 0x10) != 0; /* GET_VFLG; VS */
212     case 10:return (nzvc & 0x80) == 0; /* !GET_NFLG; PL */
213     case 11:return (nzvc & 0x80) != 0; /* GET_NFLG; MI */
214     case 12:return (((nzvc << 3) ^ nzvc) & 0x80) == 0; /* GET_NFLG == GET_VFLG; GE */
215     case 13:return (((nzvc << 3) ^ nzvc) & 0x80) != 0; /* GET_NFLG != GET_VFLG; LT */
216 cebix 1.2 case 14:
217 cebix 1.3 /* N--V--CZ shifted by 3 leads to V--CZ--- */
218     return (((nzvc << 3) ^ nzvc) & 0x88) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
219 cebix 1.2 case 15:
220 cebix 1.3 return (((nzvc << 3) ^ nzvc) & 0x88) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
221 cebix 1.2 }
222     return 0;
223     }
224    
225     #ifdef SPARC_V8_ASSEMBLY
226    
227 cebix 1.3 static inline char *str_flags(void)
228     {
229     static char str[8];
230     sprintf(str, "%c%c%c%c%c",
231     GET_XFLG ? 'X' : '-',
232     GET_NFLG ? 'N' : '-',
233     GET_ZFLG ? 'Z' : '-',
234     GET_VFLG ? 'V' : '-',
235     GET_CFLG ? 'C' : '-'
236     );
237     return str;
238     }
239    
240     static inline uae_u32 sparc_v8_flag_add_8(flags_addr pflags, uae_u32 src, uae_u32 dst)
241 cebix 1.2 {
242     uae_u32 value;
243     __asm__ ("\n"
244     " sll %2, 24, %%o0\n"
245     " sll %3, 24, %%o1\n"
246     " addcc %%o0, %%o1, %%o0\n"
247 cebix 1.3 " subx %%g0, %%g0, %%o1\n"
248     " srl %%o0, 24, %0 ! 8-bit result\n"
249     " and %%o1, 0x202, %%o1 ! X, C flags\n"
250     " and %0, 0x80, %%o0\n"
251     " or %%o1, %%o0, %%o1 ! N flag\n"
252     " subcc %%g0, %0, %%g0\n"
253     " subx %%o1, -1, %%o1 ! Z flag\n"
254 cebix 1.2 " bvs,a .+8\n"
255 cebix 1.3 " or %%o1, 0x10, %%o1 ! V flag\n"
256     " sth %%o1, [%1]\n"
257 cebix 1.2 : "=&r" (value)
258 cebix 1.3 : "r" (pflags), "r" (dst), "r" (src), "0" (value)
259 cebix 1.2 : "cc", "o0", "o1"
260     );
261 cebix 1.3
262     // printf("%d + %d = %d (flags = %s)\n", dst, src, value, str_flags());
263 cebix 1.2 return value;
264     }
265    
266 cebix 1.3 static inline uae_u32 sparc_v8_flag_add_16(flags_addr pflags, uae_u32 src, uae_u32 dst)
267 cebix 1.2 {
268     uae_u32 value;
269     __asm__ ("\n"
270     " sll %2, 16, %%o0\n"
271     " sll %3, 16, %%o1\n"
272     " addcc %%o0, %%o1, %%o0\n"
273 cebix 1.3 " subx %%g0, %%g0, %%o1\n"
274     " srl %%o0, 16, %0 ! 16-bit result\n"
275     " and %%o1, 0x202, %%o1 ! X, C flags\n"
276     " sra %%o0, 24, %%o0\n"
277     " and %%o0, 0x80, %%o0\n"
278     " or %%o1, %%o0, %%o1 ! N flag\n"
279     " subcc %%g0, %0, %%g0\n"
280     " subx %%o1, -1, %%o1 ! Z flag\n"
281 cebix 1.2 " bvs,a .+8\n"
282 cebix 1.3 " or %%o1, 0x10, %%o1 ! V flag\n"
283     " sth %%o1, [%1]\n"
284 cebix 1.2 : "=&r" (value)
285 cebix 1.3 : "r" (pflags), "r" (dst), "r" (src), "0" (value)
286 cebix 1.2 : "cc", "o0", "o1"
287     );
288     return value;
289     }
290    
291 cebix 1.3 static inline uae_u32 sparc_v8_flag_add_32(flags_addr pflags, uae_u32 src, uae_u32 dst)
292 cebix 1.2 {
293     uae_u32 value;
294     __asm__ ("\n"
295     " addcc %2, %3, %0\n"
296 cebix 1.3 " subx %%g0, %%g0, %%o0\n"
297     " sra %0, 24, %%o1\n"
298     " and %%o0, 0x202, %%o0 ! X, C flags\n"
299     " and %%o1, 0x80, %%o1\n"
300     " or %%o0, %%o1, %%o0 ! N flag\n"
301     " subcc %%g0, %0, %%g0\n"
302     " subx %%o0, -1, %%o0 ! Z flag\n"
303 cebix 1.2 " bvs,a .+8\n"
304 cebix 1.3 " or %%o0, 0x10, %%o0 ! V flag\n"
305     " sth %%o0, [%1]\n"
306 cebix 1.2 : "=&r" (value)
307 cebix 1.3 : "r" (pflags), "r" (dst), "r" (src), "0" (value)
308     : "cc", "o0", "o1"
309 cebix 1.2 );
310     return value;
311     }
312    
313     static inline uae_u32 sparc_v8_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
314     {
315     uae_u32 value;
316     __asm__ ("\n"
317     " sll %2, 24, %%o0\n"
318     " sll %3, 24, %%o1\n"
319     " subcc %%o0, %%o1, %%o0\n"
320     " addx %%g0, %%g0, %%o1 ! X,C flags\n"
321     " srl %%o0, 24, %0\n"
322     " stb %%o1, [%1 + 1]\n"
323     " bl,a .+8\n"
324     " or %%o1, 0x08, %%o1 ! N flag\n"
325     " bz,a .+8\n"
326     " or %%o1, 0x04, %%o1 ! Z flag\n"
327     " bvs,a .+8\n"
328     " or %%o1, 0x02, %%o1 ! V flag\n"
329     " stb %%o1, [%1]\n"
330     : "=&r" (value)
331     : "r" (flags), "r" (dst), "r" (src)
332     : "cc", "o0", "o1"
333     );
334     return value;
335     }
336    
337     static inline uae_u32 sparc_v8_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
338     {
339     uae_u32 value;
340     __asm__ ("\n"
341     " sll %2, 16, %%o0\n"
342     " sll %3, 16, %%o1\n"
343     " subcc %%o0, %%o1, %%o0\n"
344     " addx %%g0, %%g0, %%o1 ! X,C flags\n"
345     " srl %%o0, 16, %0\n"
346     " stb %%o1, [%1 + 1]\n"
347     " bl,a .+8\n"
348     " or %%o1, 0x08, %%o1 ! N flag\n"
349     " bz,a .+8\n"
350     " or %%o1, 0x04, %%o1 ! Z flag\n"
351     " bvs,a .+8\n"
352     " or %%o1, 0x02, %%o1 ! V flag\n"
353     " stb %%o1, [%1]\n"
354     : "=&r" (value)
355     : "r" (flags), "r" (dst), "r" (src)
356     : "cc", "o0", "o1"
357     );
358     return value;
359     }
360    
361     static inline uae_u32 sparc_v8_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
362     {
363     uae_u32 value;
364     __asm__ ("\n"
365     " subcc %2, %3, %0\n"
366     " addx %%g0, %%g0, %%o0 ! X,C flags\n"
367     " stb %%o0, [%1 + 1]\n"
368     " bl,a .+8\n"
369     " or %%o0, 0x08, %%o0 ! N flag\n"
370     " bz,a .+8\n"
371     " or %%o0, 0x04, %%o0 ! Z flag\n"
372     " bvs,a .+8\n"
373     " or %%o0, 0x02, %%o0 ! V flag\n"
374     " stb %%o0, [%1]\n"
375     : "=&r" (value)
376     : "r" (flags), "r" (dst), "r" (src)
377     : "cc", "o0"
378     );
379     return value;
380     }
381    
382     static inline void sparc_v8_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
383     {
384     __asm__ ("\n"
385     " sll %1, 24, %%o0\n"
386     " sll %2, 24, %%o1\n"
387     " subcc %%o0, %%o1, %%g0\n"
388     " addx %%g0, %%g0, %%o0 ! C flag\n"
389     " bl,a .+8\n"
390     " or %%o0, 0x08, %%o0 ! N flag\n"
391     " bz,a .+8\n"
392     " or %%o0, 0x04, %%o0 ! Z flag\n"
393     " bvs,a .+8\n"
394     " or %%o0, 0x02, %%o0 ! V flag\n"
395     " stb %%o0, [%0]\n"
396     : /* no outputs */
397     : "r" (flags), "r" (dst), "r" (src)
398     : "cc", "o0", "o1"
399     );
400     }
401    
402     static inline void sparc_v8_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
403     {
404     __asm__ ("\n"
405     " sll %1, 16, %%o0\n"
406     " sll %2, 16, %%o1\n"
407     " subcc %%o0, %%o1, %%g0\n"
408     " addx %%g0, %%g0, %%o0 ! C flag\n"
409     " bl,a .+8\n"
410     " or %%o0, 0x08, %%o0 ! N flag\n"
411     " bz,a .+8\n"
412     " or %%o0, 0x04, %%o0 ! Z flag\n"
413     " bvs,a .+8\n"
414     " or %%o0, 0x02, %%o0 ! V flag\n"
415     " stb %%o0, [%0]\n"
416     : /* no outputs */
417     : "r" (flags), "r" (dst), "r" (src)
418     : "cc", "o0", "o1"
419     );
420     }
421    
422     static inline void sparc_v8_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
423     {
424     __asm__ ("\n"
425     " subcc %1, %2, %%o1\n"
426     " srl %%o1, 31, %%o0\n"
427     " sll %%o0, 3, %%o0\n"
428     " addx %%o0, %%g0, %%o0\n"
429     " bvs,a .+8\n"
430     " or %%o0, 0x02, %%o0\n"
431     " subcc %%g0, %%o1, %%g0\n"
432     " addx %%g0, 7, %%o1\n"
433     " and %%o1, 0x04, %%o1\n"
434     " or %%o0, %%o1, %%o0\n"
435     " stb %%o0, [%0]\n"
436     : /* no outputs */
437     : "r" (flags), "r" (dst), "r" (src)
438     : "cc", "o0", "o1"
439     );
440     }
441    
442     #endif /* SPARC_V8_ASSEMBLY */
443    
444     #ifdef SPARC_V9_ASSEMBLY
445    
446     static inline uae_u32 sparc_v9_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
447     {
448     uae_u32 value;
449     __asm__ ("\n"
450     " sll %2, 24, %%o0\n"
451     " sll %3, 24, %%o1\n"
452     " addcc %%o0, %%o1, %%o0\n"
453     " rd %%ccr, %%o1\n"
454     " srl %%o0, 24, %0\n"
455     " stb %%o1, [%1]\n"
456     " stb %%o1, [%1+1]\n"
457     : "=&r" (value)
458     : "r" (flags), "r" (dst), "r" (src)
459     : "cc", "o0", "o1"
460     );
461     return value;
462     }
463    
464     static inline uae_u32 sparc_v9_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
465     {
466     uae_u32 value;
467     __asm__ ("\n"
468     " sll %2, 16, %%o0\n"
469     " sll %3, 16, %%o1\n"
470     " addcc %%o0, %%o1, %%o0\n"
471     " rd %%ccr, %%o1\n"
472     " srl %%o0, 16, %0\n"
473     " stb %%o1, [%1]\n"
474     " stb %%o1, [%1+1]\n"
475     : "=&r" (value)
476     : "r" (flags), "r" (dst), "r" (src)
477     : "cc", "o0", "o1"
478     );
479     return value;
480     }
481    
482     static inline uae_u32 sparc_v9_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
483     {
484     uae_u32 value;
485     __asm__ ("\n"
486     " addcc %2, %3, %0\n"
487     " rd %%ccr, %%o0\n"
488     " stb %%o0, [%1]\n"
489     " stb %%o0, [%1+1]\n"
490     : "=&r" (value)
491     : "r" (flags), "r" (dst), "r" (src)
492     : "cc", "o0"
493     );
494     return value;
495     }
496    
497     static inline uae_u32 sparc_v9_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
498     {
499     uae_u32 value;
500     __asm__ ("\n"
501     " sll %2, 24, %%o0\n"
502     " sll %3, 24, %%o1\n"
503     " subcc %%o0, %%o1, %%o0\n"
504     " rd %%ccr, %%o1\n"
505     " srl %%o0, 24, %0\n"
506     " stb %%o1, [%1]\n"
507     " stb %%o1, [%1+1]\n"
508     : "=&r" (value)
509     : "r" (flags), "r" (dst), "r" (src)
510     : "cc", "o0", "o1"
511     );
512     return value;
513     }
514    
515     static inline uae_u32 sparc_v9_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
516     {
517     uae_u32 value;
518     __asm__ ("\n"
519     " sll %2, 16, %%o0\n"
520     " sll %3, 16, %%o1\n"
521     " subcc %%o0, %%o1, %%o0\n"
522     " rd %%ccr, %%o1\n"
523     " srl %%o0, 16, %0\n"
524     " stb %%o1, [%1]\n"
525     " stb %%o1, [%1+1]\n"
526     : "=&r" (value)
527     : "r" (flags), "r" (dst), "r" (src)
528     : "cc", "o0", "o1"
529     );
530     return value;
531     }
532    
533     static inline uae_u32 sparc_v9_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
534     {
535     uae_u32 value;
536     __asm__ ("\n"
537     " subcc %2, %3, %0\n"
538     " rd %%ccr, %%o0\n"
539     " stb %%o0, [%1]\n"
540     " stb %%o0, [%1+1]\n"
541     : "=&r" (value)
542     : "r" (flags), "r" (dst), "r" (src)
543     : "cc", "o0"
544     );
545     return value;
546     }
547    
548     static inline void sparc_v9_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
549     {
550     __asm__ ("\n"
551     " sll %1, 24, %%o0\n"
552     " sll %2, 24, %%o1\n"
553     " subcc %%o0, %%o1, %%g0\n"
554     " rd %%ccr, %%o0\n"
555     " stb %%o0, [%0]\n"
556     : /* no outputs */
557     : "r" (flags), "r" (dst), "r" (src)
558     : "cc", "o0", "o1"
559     );
560     }
561    
562     static inline void sparc_v9_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
563     {
564     __asm__ ("\n"
565     " sll %1, 16, %%o0\n"
566     " sll %2, 16, %%o1\n"
567     " subcc %%o0, %%o1, %%g0\n"
568     " rd %%ccr, %%o0\n"
569     " stb %%o0, [%0]\n"
570     : /* no outputs */
571     : "r" (flags), "r" (dst), "r" (src)
572     : "cc", "o0", "o1"
573     );
574     }
575    
576     static inline void sparc_v9_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
577     {
578     __asm__ ("\n"
579     " subcc %1, %2, %%g0\n"
580     #if 0
581     " subcc %1, %2, %%o1\n"
582     " srl %%o1, 31, %%o0\n"
583     " sll %%o0, 3, %%o0\n"
584     " addx %%o0, %%g0, %%o0\n"
585     " bvs,a .+8\n"
586     " or %%o0, 0x02, %%o0\n"
587     " subcc %%g0, %%o1, %%g0\n"
588     " addx %%g0, 7, %%o1\n"
589     " and %%o1, 0x04, %%o1\n"
590     " or %%o0, %%o1, %%o0\n"
591     #endif
592     #if 0
593     " subcc %1, %2, %%o1\n"
594     " srl %%o1, 31, %%o0\n"
595     " sll %%o0, 3, %%o0\n"
596     " addx %%o0, %%g0, %%o0\n"
597     " bvs,pt,a .+8\n"
598     " or %%o0, 0x02, %%o0\n"
599     " subcc %%g0, %%o1, %%g0\n"
600     " addx %%g0, 7, %%o1\n"
601     " and %%o1, 0x04, %%o1\n"
602     " or %%o0, %%o1, %%o0\n"
603     " stb %%o0, [%0]\n"
604     #endif
605     " rd %%ccr, %%o0\n"
606     " stb %%o0, [%0]\n"
607     : /* no outputs */
608     : "r" (flags), "r" (dst), "r" (src)
609     : "cc", "o0", "o1"
610     );
611     }
612    
613     #if 1
614     static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
615     {
616     __asm__ ("\n"
617     " sll %1, 24, %%o0\n"
618     " subcc %%o0, %%g0, %%g0\n"
619     " rd %%ccr, %%o0\n"
620     " stb %%o0, [%0]\n"
621     : /* no outputs */
622     : "r" (flags), "r" (val)
623     : "cc", "o0"
624     );
625     }
626    
627     static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
628     {
629     __asm__ ("\n"
630     " sll %1, 16, %%o0\n"
631     " subcc %%o0, %%g0, %%g0\n"
632     " rd %%ccr, %%o0\n"
633     " stb %%o0, [%0]\n"
634     : /* no outputs */
635     : "r" (flags), "r" (val)
636     : "cc", "o0"
637     );
638     }
639    
640     static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
641     {
642     __asm__ ("\n"
643     " subcc %1, %%g0, %%g0\n"
644     " rd %%ccr, %%o0\n"
645     " stb %%o0, [%0]\n"
646     : /* no outputs */
647     : "r" (flags), "r" (val)
648     : "cc", "o0"
649     );
650     }
651     #else
652     static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
653     {
654     __asm__ ("\n"
655     " sll %1, 24, %%o0\n"
656     " subcc %%o0, %%g0, %%o1\n"
657     " srl %%o1, 31, %%o0\n"
658     " sll %%o0, 3, %%o0\n"
659     " addx %%o0, %%g0, %%o0\n"
660     " bvs,a .+8\n"
661     " or %%o0, 0x02, %%o0\n"
662     " subcc %%g0, %%o1, %%g0\n"
663     " addx %%g0, 7, %%o1\n"
664     " and %%o1, 0x04, %%o1\n"
665     " or %%o0, %%o1, %%o0\n"
666     " stb %%o0, [%0]\n"
667     : /* no outputs */
668     : "r" (flags), "r" (val)
669     : "cc", "o0", "o1"
670     );
671     }
672    
673     static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
674     {
675     __asm__ ("\n"
676     " sll %1, 16, %%o0\n"
677     " subcc %%o0, %%g0, %%o1\n"
678     " srl %%o1, 31, %%o0\n"
679     " sll %%o0, 3, %%o0\n"
680     " addx %%o0, %%g0, %%o0\n"
681     " bvs,a .+8\n"
682     " or %%o0, 0x02, %%o0\n"
683     " subcc %%g0, %%o1, %%g0\n"
684     " addx %%g0, 7, %%o1\n"
685     " and %%o1, 0x04, %%o1\n"
686     " or %%o0, %%o1, %%o0\n"
687     " stb %%o0, [%0]\n"
688     : /* no outputs */
689     : "r" (flags), "r" (val)
690     : "cc", "o0", "o1"
691     );
692     }
693    
694     static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
695     {
696     __asm__ ("\n"
697     " subcc %1, %%g0, %%o1\n"
698     " srl %%o1, 31, %%o0\n"
699     " sll %%o0, 3, %%o0\n"
700     " addx %%o0, %%g0, %%o0\n"
701     " bvs,a .+8\n"
702     " or %%o0, 0x02, %%o0\n"
703     " subcc %%g0, %%o1, %%g0\n"
704     " addx %%g0, 7, %%o1\n"
705     " and %%o1, 0x04, %%o1\n"
706     " or %%o0, %%o1, %%o0\n"
707     " stb %%o0, [%0]\n"
708     : /* no outputs */
709     : "r" (flags), "r" (val)
710     : "cc", "o0", "o1"
711     );
712     }
713     #endif
714    
715     static inline uae_u32 sparc_v9_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
716     {
717     uae_u32 value;
718     __asm__ ("\n"
719     " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
720     " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
721     " addxcc %2, %3, %0\n"
722     : "=&r" (value)
723     : "r" (flags), "r" (dst), "r" (src)
724     : "cc", "o0", "o1"
725     );
726     return value;
727     }
728    
729     static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
730     {
731     uae_u32 value;
732     __asm__ ("\n"
733     " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
734     " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
735     " addxcc %2, %3, %0\n"
736     " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
737     " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
738     " addx %%o0, %%g0, %%o0 ! X,C flags\n"
739     " bl,a .+8\n"
740     " or %%o0, 0x08, %%o0 ! N flag\n"
741     " bvs,a .+8\n"
742     " or %%o0, 0x02, %%o0 ! V flag\n"
743     " bnz,a .+8\n"
744     " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
745     " stb %%o0, [%1]\n"
746     " stb %%o0, [%1 + 1]\n"
747     : "=&r" (value)
748     : "r" (flags), "r" (dst), "r" (src)
749     : "cc", "o0"
750     );
751     return value;
752     }
753    
754     #endif /* SPARC_V9_ASSEMBLY */
755 cebix 1.1
756     #else
757    
758     struct flag_struct {
759     unsigned int c;
760     unsigned int z;
761     unsigned int n;
762     unsigned int v;
763     unsigned int x;
764     };
765    
766     extern struct flag_struct regflags;
767    
768     #define ZFLG (regflags.z)
769     #define NFLG (regflags.n)
770     #define CFLG (regflags.c)
771     #define VFLG (regflags.v)
772     #define XFLG (regflags.x)
773    
774     static __inline__ int cctrue(const int cc)
775     {
776     switch(cc){
777     case 0: return 1; /* T */
778     case 1: return 0; /* F */
779     case 2: return !CFLG && !ZFLG; /* HI */
780     case 3: return CFLG || ZFLG; /* LS */
781     case 4: return !CFLG; /* CC */
782     case 5: return CFLG; /* CS */
783     case 6: return !ZFLG; /* NE */
784     case 7: return ZFLG; /* EQ */
785     case 8: return !VFLG; /* VC */
786     case 9: return VFLG; /* VS */
787     case 10:return !NFLG; /* PL */
788     case 11:return NFLG; /* MI */
789     case 12:return NFLG == VFLG; /* GE */
790     case 13:return NFLG != VFLG; /* LT */
791     case 14:return !ZFLG && (NFLG == VFLG); /* GT */
792     case 15:return ZFLG || (NFLG != VFLG); /* LE */
793     }
794     return 0;
795     }
796    
797     #endif