ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/m68k.h
Revision: 1.2
Committed: 1999-10-21T15:27:11Z (25 years, 1 month ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: snapshot-21101999
Changes since 1.1: +646 -1 lines
Log Message:
- integrated SPARC assembly optimizations

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 #if defined(__i386__) && defined(X86_ASSEMBLY)
10
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
145 #elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
146
147 struct flag_struct {
148 unsigned char nzvc;
149 unsigned char x;
150 };
151
152 extern struct flag_struct regflags;
153
154 #define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2))
155 #define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1))
156 #define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1))
157 #define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3))
158 #define SET_XFLG(y) (regflags.x = (y))
159
160 #define GET_ZFLG ((regflags.nzvc >> 2) & 1)
161 #define GET_CFLG (regflags.nzvc & 1)
162 #define GET_VFLG ((regflags.nzvc >> 1) & 1)
163 #define GET_NFLG ((regflags.nzvc >> 3) & 1)
164 #define GET_XFLG (regflags.x & 1)
165
166 #define CLEAR_CZNV (regflags.nzvc = 0)
167 #define COPY_CARRY (regflags.x = regflags.nzvc)
168
169 static __inline__ int cctrue(int cc)
170 {
171 uae_u32 nzvc = regflags.nzvc;
172 switch(cc){
173 case 0: return 1; /* T */
174 case 1: return 0; /* F */
175 case 2: return (nzvc & 0x05) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
176 case 3: return (nzvc & 0x05) != 0; /* GET_CFLG || GET_ZFLG; LS */
177 case 4: return (nzvc & 1) == 0; /* !GET_CFLG; CC */
178 case 5: return (nzvc & 1) != 0; /* GET_CFLG; CS */
179 case 6: return (nzvc & 0x04) == 0; /* !GET_ZFLG; NE */
180 case 7: return (nzvc & 0x04) != 0; /* GET_ZFLG; EQ */
181 case 8: return (nzvc & 0x02) == 0;/* !GET_VFLG; VC */
182 case 9: return (nzvc & 0x02) != 0;/* GET_VFLG; VS */
183 case 10:return (nzvc & 0x08) == 0; /* !GET_NFLG; PL */
184 case 11:return (nzvc & 0x08) != 0; /* GET_NFLG; MI */
185 case 12:return (((nzvc << 2) ^ nzvc) & 0x08) == 0; /* GET_NFLG == GET_VFLG; GE */
186 case 13:return (((nzvc << 2) ^ nzvc) & 0x08) != 0;/* GET_NFLG != GET_VFLG; LT */
187 case 14:
188 nzvc &= 0x0e;
189 return (((nzvc << 2) ^ nzvc) & 0x0c) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
190 case 15:
191 nzvc &= 0x0e;
192 return (((nzvc << 2) ^ nzvc) & 0x0c) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
193 }
194 return 0;
195 }
196
197 #ifdef SPARC_V8_ASSEMBLY
198
199 static inline uae_u32 sparc_v8_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
200 {
201 uae_u32 value;
202 __asm__ ("\n"
203 " sll %2, 24, %%o0\n"
204 " sll %3, 24, %%o1\n"
205 " addcc %%o0, %%o1, %%o0\n"
206 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
207 " srl %%o0, 24, %0\n"
208 " stb %%o1, [%1 + 1]\n"
209 " bl,a .+8\n"
210 " or %%o1, 0x08, %%o1 ! N flag\n"
211 " bz,a .+8\n"
212 " or %%o1, 0x04, %%o1 ! Z flag\n"
213 " bvs,a .+8\n"
214 " or %%o1, 0x02, %%o1 ! V flag\n"
215 " stb %%o1, [%1]\n"
216 : "=&r" (value)
217 : "r" (flags), "r" (dst), "r" (src)
218 : "cc", "o0", "o1"
219 );
220 return value;
221 }
222
223 static inline uae_u32 sparc_v8_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
224 {
225 uae_u32 value;
226 __asm__ ("\n"
227 " sll %2, 16, %%o0\n"
228 " sll %3, 16, %%o1\n"
229 " addcc %%o0, %%o1, %%o0\n"
230 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
231 " srl %%o0, 16, %0\n"
232 " stb %%o1, [%1 + 1]\n"
233 " bl,a .+8\n"
234 " or %%o1, 0x08, %%o1 ! N flag\n"
235 " bz,a .+8\n"
236 " or %%o1, 0x04, %%o1 ! Z flag\n"
237 " bvs,a .+8\n"
238 " or %%o1, 0x02, %%o1 ! V flag\n"
239 " stb %%o1, [%1]\n"
240 : "=&r" (value)
241 : "r" (flags), "r" (dst), "r" (src)
242 : "cc", "o0", "o1"
243 );
244 return value;
245 }
246
247 static inline uae_u32 sparc_v8_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
248 {
249 uae_u32 value;
250 __asm__ ("\n"
251 " addcc %2, %3, %0\n"
252 " addx %%g0, %%g0, %%o0 ! X,C flags\n"
253 " stb %%o0, [%1 + 1]\n"
254 " bl,a .+8\n"
255 " or %%o0, 0x08, %%o0 ! N flag\n"
256 " bz,a .+8\n"
257 " or %%o0, 0x04, %%o0 ! Z flag\n"
258 " bvs,a .+8\n"
259 " or %%o0, 0x02, %%o0 ! V flag\n"
260 " stb %%o0, [%1]\n"
261 : "=&r" (value)
262 : "r" (flags), "r" (dst), "r" (src)
263 : "cc", "o0"
264 );
265 return value;
266 }
267
268 static inline uae_u32 sparc_v8_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
269 {
270 uae_u32 value;
271 __asm__ ("\n"
272 " sll %2, 24, %%o0\n"
273 " sll %3, 24, %%o1\n"
274 " subcc %%o0, %%o1, %%o0\n"
275 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
276 " srl %%o0, 24, %0\n"
277 " stb %%o1, [%1 + 1]\n"
278 " bl,a .+8\n"
279 " or %%o1, 0x08, %%o1 ! N flag\n"
280 " bz,a .+8\n"
281 " or %%o1, 0x04, %%o1 ! Z flag\n"
282 " bvs,a .+8\n"
283 " or %%o1, 0x02, %%o1 ! V flag\n"
284 " stb %%o1, [%1]\n"
285 : "=&r" (value)
286 : "r" (flags), "r" (dst), "r" (src)
287 : "cc", "o0", "o1"
288 );
289 return value;
290 }
291
292 static inline uae_u32 sparc_v8_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
293 {
294 uae_u32 value;
295 __asm__ ("\n"
296 " sll %2, 16, %%o0\n"
297 " sll %3, 16, %%o1\n"
298 " subcc %%o0, %%o1, %%o0\n"
299 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
300 " srl %%o0, 16, %0\n"
301 " stb %%o1, [%1 + 1]\n"
302 " bl,a .+8\n"
303 " or %%o1, 0x08, %%o1 ! N flag\n"
304 " bz,a .+8\n"
305 " or %%o1, 0x04, %%o1 ! Z flag\n"
306 " bvs,a .+8\n"
307 " or %%o1, 0x02, %%o1 ! V flag\n"
308 " stb %%o1, [%1]\n"
309 : "=&r" (value)
310 : "r" (flags), "r" (dst), "r" (src)
311 : "cc", "o0", "o1"
312 );
313 return value;
314 }
315
316 static inline uae_u32 sparc_v8_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
317 {
318 uae_u32 value;
319 __asm__ ("\n"
320 " subcc %2, %3, %0\n"
321 " addx %%g0, %%g0, %%o0 ! X,C flags\n"
322 " stb %%o0, [%1 + 1]\n"
323 " bl,a .+8\n"
324 " or %%o0, 0x08, %%o0 ! N flag\n"
325 " bz,a .+8\n"
326 " or %%o0, 0x04, %%o0 ! Z flag\n"
327 " bvs,a .+8\n"
328 " or %%o0, 0x02, %%o0 ! V flag\n"
329 " stb %%o0, [%1]\n"
330 : "=&r" (value)
331 : "r" (flags), "r" (dst), "r" (src)
332 : "cc", "o0"
333 );
334 return value;
335 }
336
337 static inline void sparc_v8_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
338 {
339 __asm__ ("\n"
340 " sll %1, 24, %%o0\n"
341 " sll %2, 24, %%o1\n"
342 " subcc %%o0, %%o1, %%g0\n"
343 " addx %%g0, %%g0, %%o0 ! C flag\n"
344 " bl,a .+8\n"
345 " or %%o0, 0x08, %%o0 ! N flag\n"
346 " bz,a .+8\n"
347 " or %%o0, 0x04, %%o0 ! Z flag\n"
348 " bvs,a .+8\n"
349 " or %%o0, 0x02, %%o0 ! V flag\n"
350 " stb %%o0, [%0]\n"
351 : /* no outputs */
352 : "r" (flags), "r" (dst), "r" (src)
353 : "cc", "o0", "o1"
354 );
355 }
356
357 static inline void sparc_v8_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
358 {
359 __asm__ ("\n"
360 " sll %1, 16, %%o0\n"
361 " sll %2, 16, %%o1\n"
362 " subcc %%o0, %%o1, %%g0\n"
363 " addx %%g0, %%g0, %%o0 ! C flag\n"
364 " bl,a .+8\n"
365 " or %%o0, 0x08, %%o0 ! N flag\n"
366 " bz,a .+8\n"
367 " or %%o0, 0x04, %%o0 ! Z flag\n"
368 " bvs,a .+8\n"
369 " or %%o0, 0x02, %%o0 ! V flag\n"
370 " stb %%o0, [%0]\n"
371 : /* no outputs */
372 : "r" (flags), "r" (dst), "r" (src)
373 : "cc", "o0", "o1"
374 );
375 }
376
377 static inline void sparc_v8_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
378 {
379 __asm__ ("\n"
380 " subcc %1, %2, %%o1\n"
381 " srl %%o1, 31, %%o0\n"
382 " sll %%o0, 3, %%o0\n"
383 " addx %%o0, %%g0, %%o0\n"
384 " bvs,a .+8\n"
385 " or %%o0, 0x02, %%o0\n"
386 " subcc %%g0, %%o1, %%g0\n"
387 " addx %%g0, 7, %%o1\n"
388 " and %%o1, 0x04, %%o1\n"
389 " or %%o0, %%o1, %%o0\n"
390 " stb %%o0, [%0]\n"
391 : /* no outputs */
392 : "r" (flags), "r" (dst), "r" (src)
393 : "cc", "o0", "o1"
394 );
395 }
396
397 static inline uae_u32 sparc_v8_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
398 {
399 uae_u32 value;
400 __asm__ ("\n"
401 " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
402 " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
403 " addxcc %2, %3, %0\n"
404 : "=&r" (value)
405 : "r" (flags), "r" (dst), "r" (src)
406 : "cc", "o0", "o1"
407 );
408 return value;
409 }
410
411 #if 0
412 VERY SLOW...
413 static inline uae_u32 sparc_v8_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
414 {
415 uae_u32 value;
416 __asm__ ("\n"
417 " sll %2, 24, %%o0\n"
418 " sll %3, 24, %%o1\n"
419 " addcc %%o0, %%o1, %%o0\n"
420 " addx %%g0, %%g0, %%o1 ! X,C flags\n"
421 " bvs,a .+8\n"
422 " or %%o1, 0x02, %%o1 ! V flag\n"
423 " ldub [%1 + 1], %%o2\n"
424 " subcc %%g0, %%o2, %%g0\n"
425 " addx %%g0, %%g0, %%o2\n"
426 " sll %%o2, 24, %%o2\n"
427 " addcc %%o0, %%o2, %%o0\n"
428 " srl %%o0, 24, %0\n"
429 " addx %%g0, %%g0, %%o2\n"
430 " or %%o1, %%o2, %%o1 ! update X,C flags\n"
431 " bl,a .+8\n"
432 " or %%o1, 0x08, %%o1 ! N flag\n"
433 " ldub [%1], %%o0 ! retreive the old NZVC flags (XXX)\n"
434 " bvs,a .+8\n"
435 " or %%o1, 0x02, %%o1 ! update V flag\n"
436 " and %%o0, 0x04, %%o0 ! (XXX) but keep only Z flag\n"
437 " and %%o1, 1, %%o2 ! keep C flag in %%o2\n"
438 " bnz,a .+8\n"
439 " or %%g0, %%g0, %%o0 ! Z flag cleared if non-zero result\n"
440 " stb %%o2, [%1 + 1] ! store the X flag\n"
441 " or %%o1, %%o0, %%o1\n"
442 " stb %%o1, [%1]\n"
443 : "=&r" (value)
444 : "r" (flags), "r" (dst), "r" (src)
445 : "cc", "o0", "o1", "o2"
446 );
447 return value;
448 }
449 #endif
450
451 static inline uae_u32 sparc_v8_flag_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
452 {
453 uae_u32 value;
454 __asm__ ("\n"
455 " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
456 " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
457 " addxcc %2, %3, %0\n"
458 " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
459 " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
460 " addx %%o0, %%g0, %%o0 ! X,C flags\n"
461 " bl,a .+8\n"
462 " or %%o0, 0x08, %%o0 ! N flag\n"
463 " bvs,a .+8\n"
464 " or %%o0, 0x02, %%o0 ! V flag\n"
465 " bnz,a .+8\n"
466 " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
467 " stb %%o0, [%1]\n"
468 " stb %%o0, [%1 + 1]\n"
469 : "=&r" (value)
470 : "r" (flags), "r" (dst), "r" (src)
471 : "cc", "o0"
472 );
473 return value;
474 }
475
476 #endif /* SPARC_V8_ASSEMBLY */
477
478 #ifdef SPARC_V9_ASSEMBLY
479
480 static inline uae_u32 sparc_v9_flag_add_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
481 {
482 uae_u32 value;
483 __asm__ ("\n"
484 " sll %2, 24, %%o0\n"
485 " sll %3, 24, %%o1\n"
486 " addcc %%o0, %%o1, %%o0\n"
487 " rd %%ccr, %%o1\n"
488 " srl %%o0, 24, %0\n"
489 " stb %%o1, [%1]\n"
490 " stb %%o1, [%1+1]\n"
491 : "=&r" (value)
492 : "r" (flags), "r" (dst), "r" (src)
493 : "cc", "o0", "o1"
494 );
495 return value;
496 }
497
498 static inline uae_u32 sparc_v9_flag_add_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
499 {
500 uae_u32 value;
501 __asm__ ("\n"
502 " sll %2, 16, %%o0\n"
503 " sll %3, 16, %%o1\n"
504 " addcc %%o0, %%o1, %%o0\n"
505 " rd %%ccr, %%o1\n"
506 " srl %%o0, 16, %0\n"
507 " stb %%o1, [%1]\n"
508 " stb %%o1, [%1+1]\n"
509 : "=&r" (value)
510 : "r" (flags), "r" (dst), "r" (src)
511 : "cc", "o0", "o1"
512 );
513 return value;
514 }
515
516 static inline uae_u32 sparc_v9_flag_add_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
517 {
518 uae_u32 value;
519 __asm__ ("\n"
520 " addcc %2, %3, %0\n"
521 " rd %%ccr, %%o0\n"
522 " stb %%o0, [%1]\n"
523 " stb %%o0, [%1+1]\n"
524 : "=&r" (value)
525 : "r" (flags), "r" (dst), "r" (src)
526 : "cc", "o0"
527 );
528 return value;
529 }
530
531 static inline uae_u32 sparc_v9_flag_sub_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
532 {
533 uae_u32 value;
534 __asm__ ("\n"
535 " sll %2, 24, %%o0\n"
536 " sll %3, 24, %%o1\n"
537 " subcc %%o0, %%o1, %%o0\n"
538 " rd %%ccr, %%o1\n"
539 " srl %%o0, 24, %0\n"
540 " stb %%o1, [%1]\n"
541 " stb %%o1, [%1+1]\n"
542 : "=&r" (value)
543 : "r" (flags), "r" (dst), "r" (src)
544 : "cc", "o0", "o1"
545 );
546 return value;
547 }
548
549 static inline uae_u32 sparc_v9_flag_sub_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
550 {
551 uae_u32 value;
552 __asm__ ("\n"
553 " sll %2, 16, %%o0\n"
554 " sll %3, 16, %%o1\n"
555 " subcc %%o0, %%o1, %%o0\n"
556 " rd %%ccr, %%o1\n"
557 " srl %%o0, 16, %0\n"
558 " stb %%o1, [%1]\n"
559 " stb %%o1, [%1+1]\n"
560 : "=&r" (value)
561 : "r" (flags), "r" (dst), "r" (src)
562 : "cc", "o0", "o1"
563 );
564 return value;
565 }
566
567 static inline uae_u32 sparc_v9_flag_sub_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
568 {
569 uae_u32 value;
570 __asm__ ("\n"
571 " subcc %2, %3, %0\n"
572 " rd %%ccr, %%o0\n"
573 " stb %%o0, [%1]\n"
574 " stb %%o0, [%1+1]\n"
575 : "=&r" (value)
576 : "r" (flags), "r" (dst), "r" (src)
577 : "cc", "o0"
578 );
579 return value;
580 }
581
582 static inline void sparc_v9_flag_cmp_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
583 {
584 __asm__ ("\n"
585 " sll %1, 24, %%o0\n"
586 " sll %2, 24, %%o1\n"
587 " subcc %%o0, %%o1, %%g0\n"
588 " rd %%ccr, %%o0\n"
589 " stb %%o0, [%0]\n"
590 : /* no outputs */
591 : "r" (flags), "r" (dst), "r" (src)
592 : "cc", "o0", "o1"
593 );
594 }
595
596 static inline void sparc_v9_flag_cmp_16(flag_struct *flags, uae_u32 src, uae_u32 dst)
597 {
598 __asm__ ("\n"
599 " sll %1, 16, %%o0\n"
600 " sll %2, 16, %%o1\n"
601 " subcc %%o0, %%o1, %%g0\n"
602 " rd %%ccr, %%o0\n"
603 " stb %%o0, [%0]\n"
604 : /* no outputs */
605 : "r" (flags), "r" (dst), "r" (src)
606 : "cc", "o0", "o1"
607 );
608 }
609
610 static inline void sparc_v9_flag_cmp_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
611 {
612 __asm__ ("\n"
613 " subcc %1, %2, %%g0\n"
614 #if 0
615 " subcc %1, %2, %%o1\n"
616 " srl %%o1, 31, %%o0\n"
617 " sll %%o0, 3, %%o0\n"
618 " addx %%o0, %%g0, %%o0\n"
619 " bvs,a .+8\n"
620 " or %%o0, 0x02, %%o0\n"
621 " subcc %%g0, %%o1, %%g0\n"
622 " addx %%g0, 7, %%o1\n"
623 " and %%o1, 0x04, %%o1\n"
624 " or %%o0, %%o1, %%o0\n"
625 #endif
626 #if 0
627 " subcc %1, %2, %%o1\n"
628 " srl %%o1, 31, %%o0\n"
629 " sll %%o0, 3, %%o0\n"
630 " addx %%o0, %%g0, %%o0\n"
631 " bvs,pt,a .+8\n"
632 " or %%o0, 0x02, %%o0\n"
633 " subcc %%g0, %%o1, %%g0\n"
634 " addx %%g0, 7, %%o1\n"
635 " and %%o1, 0x04, %%o1\n"
636 " or %%o0, %%o1, %%o0\n"
637 " stb %%o0, [%0]\n"
638 #endif
639 " rd %%ccr, %%o0\n"
640 " stb %%o0, [%0]\n"
641 : /* no outputs */
642 : "r" (flags), "r" (dst), "r" (src)
643 : "cc", "o0", "o1"
644 );
645 }
646
647 #if 1
648 static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
649 {
650 __asm__ ("\n"
651 " sll %1, 24, %%o0\n"
652 " subcc %%o0, %%g0, %%g0\n"
653 " rd %%ccr, %%o0\n"
654 " stb %%o0, [%0]\n"
655 : /* no outputs */
656 : "r" (flags), "r" (val)
657 : "cc", "o0"
658 );
659 }
660
661 static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
662 {
663 __asm__ ("\n"
664 " sll %1, 16, %%o0\n"
665 " subcc %%o0, %%g0, %%g0\n"
666 " rd %%ccr, %%o0\n"
667 " stb %%o0, [%0]\n"
668 : /* no outputs */
669 : "r" (flags), "r" (val)
670 : "cc", "o0"
671 );
672 }
673
674 static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
675 {
676 __asm__ ("\n"
677 " subcc %1, %%g0, %%g0\n"
678 " rd %%ccr, %%o0\n"
679 " stb %%o0, [%0]\n"
680 : /* no outputs */
681 : "r" (flags), "r" (val)
682 : "cc", "o0"
683 );
684 }
685 #else
686 static inline void sparc_v9_flag_test_8(flag_struct *flags, uae_u32 val)
687 {
688 __asm__ ("\n"
689 " sll %1, 24, %%o0\n"
690 " subcc %%o0, %%g0, %%o1\n"
691 " srl %%o1, 31, %%o0\n"
692 " sll %%o0, 3, %%o0\n"
693 " addx %%o0, %%g0, %%o0\n"
694 " bvs,a .+8\n"
695 " or %%o0, 0x02, %%o0\n"
696 " subcc %%g0, %%o1, %%g0\n"
697 " addx %%g0, 7, %%o1\n"
698 " and %%o1, 0x04, %%o1\n"
699 " or %%o0, %%o1, %%o0\n"
700 " stb %%o0, [%0]\n"
701 : /* no outputs */
702 : "r" (flags), "r" (val)
703 : "cc", "o0", "o1"
704 );
705 }
706
707 static inline void sparc_v9_flag_test_16(flag_struct *flags, uae_u32 val)
708 {
709 __asm__ ("\n"
710 " sll %1, 16, %%o0\n"
711 " subcc %%o0, %%g0, %%o1\n"
712 " srl %%o1, 31, %%o0\n"
713 " sll %%o0, 3, %%o0\n"
714 " addx %%o0, %%g0, %%o0\n"
715 " bvs,a .+8\n"
716 " or %%o0, 0x02, %%o0\n"
717 " subcc %%g0, %%o1, %%g0\n"
718 " addx %%g0, 7, %%o1\n"
719 " and %%o1, 0x04, %%o1\n"
720 " or %%o0, %%o1, %%o0\n"
721 " stb %%o0, [%0]\n"
722 : /* no outputs */
723 : "r" (flags), "r" (val)
724 : "cc", "o0", "o1"
725 );
726 }
727
728 static inline void sparc_v9_flag_test_32(flag_struct *flags, uae_u32 val)
729 {
730 __asm__ ("\n"
731 " subcc %1, %%g0, %%o1\n"
732 " srl %%o1, 31, %%o0\n"
733 " sll %%o0, 3, %%o0\n"
734 " addx %%o0, %%g0, %%o0\n"
735 " bvs,a .+8\n"
736 " or %%o0, 0x02, %%o0\n"
737 " subcc %%g0, %%o1, %%g0\n"
738 " addx %%g0, 7, %%o1\n"
739 " and %%o1, 0x04, %%o1\n"
740 " or %%o0, %%o1, %%o0\n"
741 " stb %%o0, [%0]\n"
742 : /* no outputs */
743 : "r" (flags), "r" (val)
744 : "cc", "o0", "o1"
745 );
746 }
747 #endif
748
749 static inline uae_u32 sparc_v9_flag_addx_8(flag_struct *flags, uae_u32 src, uae_u32 dst)
750 {
751 uae_u32 value;
752 __asm__ ("\n"
753 " ldub [%1 + 1], %%o1 ! Get the X Flag\n"
754 " subcc %%g0, %%o1, %%g0 ! Set the SPARC carry flag, if X set\n"
755 " addxcc %2, %3, %0\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_addx_32(flag_struct *flags, uae_u32 src, uae_u32 dst)
764 {
765 uae_u32 value;
766 __asm__ ("\n"
767 " ldub [%1 + 1], %%o0 ! Get the X Flag\n"
768 " subcc %%g0, %%o0, %%g0 ! Set the SPARC carry flag, if X set\n"
769 " addxcc %2, %3, %0\n"
770 " ldub [%1], %%o0 ! retreive the old NZVC flags\n"
771 " and %%o0, 0x04, %%o0 ! but keep only Z flag\n"
772 " addx %%o0, %%g0, %%o0 ! X,C flags\n"
773 " bl,a .+8\n"
774 " or %%o0, 0x08, %%o0 ! N flag\n"
775 " bvs,a .+8\n"
776 " or %%o0, 0x02, %%o0 ! V flag\n"
777 " bnz,a .+8\n"
778 " and %%o0, 0x0B, %%o0 ! Z flag cleared if result is non-zero\n"
779 " stb %%o0, [%1]\n"
780 " stb %%o0, [%1 + 1]\n"
781 : "=&r" (value)
782 : "r" (flags), "r" (dst), "r" (src)
783 : "cc", "o0"
784 );
785 return value;
786 }
787
788 #endif /* SPARC_V9_ASSEMBLY */
789
790 #else
791
792 struct flag_struct {
793 unsigned int c;
794 unsigned int z;
795 unsigned int n;
796 unsigned int v;
797 unsigned int x;
798 };
799
800 extern struct flag_struct regflags;
801
802 #define ZFLG (regflags.z)
803 #define NFLG (regflags.n)
804 #define CFLG (regflags.c)
805 #define VFLG (regflags.v)
806 #define XFLG (regflags.x)
807
808 static __inline__ int cctrue(const int cc)
809 {
810 switch(cc){
811 case 0: return 1; /* T */
812 case 1: return 0; /* F */
813 case 2: return !CFLG && !ZFLG; /* HI */
814 case 3: return CFLG || ZFLG; /* LS */
815 case 4: return !CFLG; /* CC */
816 case 5: return CFLG; /* CS */
817 case 6: return !ZFLG; /* NE */
818 case 7: return ZFLG; /* EQ */
819 case 8: return !VFLG; /* VC */
820 case 9: return VFLG; /* VS */
821 case 10:return !NFLG; /* PL */
822 case 11:return NFLG; /* MI */
823 case 12:return NFLG == VFLG; /* GE */
824 case 13:return NFLG != VFLG; /* LT */
825 case 14:return !ZFLG && (NFLG == VFLG); /* GT */
826 case 15:return ZFLG || (NFLG != VFLG); /* LE */
827 }
828 return 0;
829 }
830
831 #endif