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 (24 years, 8 months 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

# 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 union {
149 unsigned short all;
150 unsigned char bytes[2];
151 };
152 };
153
154 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
160 #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
196 #endif
197
198 static __inline__ int cctrue(int cc)
199 {
200 uae_u32 nzvc = M68K_FLAGS_NZVC;
201 switch(cc){
202 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 case 14:
217 /* 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 case 15:
220 return (((nzvc << 3) ^ nzvc) & 0x88) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
221 }
222 return 0;
223 }
224
225 #ifdef SPARC_V8_ASSEMBLY
226
227 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 {
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 " 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 " bvs,a .+8\n"
255 " or %%o1, 0x10, %%o1 ! V flag\n"
256 " sth %%o1, [%1]\n"
257 : "=&r" (value)
258 : "r" (pflags), "r" (dst), "r" (src), "0" (value)
259 : "cc", "o0", "o1"
260 );
261
262 // printf("%d + %d = %d (flags = %s)\n", dst, src, value, str_flags());
263 return value;
264 }
265
266 static inline uae_u32 sparc_v8_flag_add_16(flags_addr pflags, uae_u32 src, uae_u32 dst)
267 {
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 " 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 " bvs,a .+8\n"
282 " or %%o1, 0x10, %%o1 ! V flag\n"
283 " sth %%o1, [%1]\n"
284 : "=&r" (value)
285 : "r" (pflags), "r" (dst), "r" (src), "0" (value)
286 : "cc", "o0", "o1"
287 );
288 return value;
289 }
290
291 static inline uae_u32 sparc_v8_flag_add_32(flags_addr pflags, uae_u32 src, uae_u32 dst)
292 {
293 uae_u32 value;
294 __asm__ ("\n"
295 " addcc %2, %3, %0\n"
296 " 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 " bvs,a .+8\n"
304 " or %%o0, 0x10, %%o0 ! V flag\n"
305 " sth %%o0, [%1]\n"
306 : "=&r" (value)
307 : "r" (pflags), "r" (dst), "r" (src), "0" (value)
308 : "cc", "o0", "o1"
309 );
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
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