1 /*
2  * E-UAE - The portable Amiga Emulator
3  *
4  * MC68000 emulation - machine-dependent optimized operations
5  *
6  * (c) 2004-2007 Richard Drummond
7  */
8 
9 #ifndef EUAE_MACHDEP_M68KOPS_H
10 #define EUAE_MACHDEP_M68KOPS_H
11 
12 #ifndef ANDROID
13 
14 #if defined(__CELLOS_LV2__) || defined(_WIN32) || defined(__x86_64__) || defined(ARM) || defined(WIIU) || defined(__powerpc__)
15 
16 #ifdef WIIU
17 #define FLAGBIT_N	31
18 #define FLAGBIT_Z	29
19 #define FLAGBIT_V	22
20 #define FLAGBIT_C	21
21 #define FLAGBIT_X	21
22 #else
23 #define FLAGBIT_N	15
24 #define FLAGBIT_Z	14
25 #define FLAGBIT_C	8
26 #define FLAGBIT_V	0
27 #define FLAGBIT_X	8
28 #endif
29 
30 #define FLAGVAL_N	(1 << FLAGBIT_N)
31 #define FLAGVAL_Z 	(1 << FLAGBIT_Z)
32 #define FLAGVAL_C	(1 << FLAGBIT_C)
33 #define FLAGVAL_V	(1 << FLAGBIT_V)
34 #define FLAGVAL_X	(1 << FLAGBIT_X)
35 
36 #define SET_ZFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_Z) | (((y) ? 1 : 0) << FLAGBIT_Z))
37 #define SET_CFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_C) | (((y) ? 1 : 0) << FLAGBIT_C))
38 #define SET_VFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_V) | (((y) ? 1 : 0) << FLAGBIT_V))
39 #define SET_NFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_N) | (((y) ? 1 : 0) << FLAGBIT_N))
40 #define SET_XFLG(y)	(regflags.x    = ((y) ? 1 : 0) << FLAGBIT_X)
41 
42 #define GET_ZFLG()	((regflags.cznv >> FLAGBIT_Z) & 1)
43 #define GET_CFLG()	((regflags.cznv >> FLAGBIT_C) & 1)
44 #define GET_VFLG()	((regflags.cznv >> FLAGBIT_V) & 1)
45 #define GET_NFLG()	((regflags.cznv >> FLAGBIT_N) & 1)
46 #define GET_XFLG()	((regflags.x    >> FLAGBIT_X) & 1)
47 
48 #define CLEAR_CZNV()	(regflags.cznv  = 0)
49 #define GET_CZNV	(regflags.cznv)
50 #define IOR_CZNV(X)	(regflags.cznv |= (X))
51 #define SET_CZNV(X)	(regflags.cznv  = (X))
52 
53 #define COPY_CARRY() (regflags.x = regflags.cznv)
54 
55 /*
56  * Test operations
57  *
58  * Evaluate operand and set Z and N flags. Always clear C and V.
59  */
60 
61 
62 #define optflag_testl(v) \
63     do { \
64 		CLEAR_CZNV ();\
65 		SET_ZFLG   ( (((uae_s32)(v)) == 0) ? 1 : 0);\
66 		SET_NFLG   ( (((uae_s32)(v)) < 0) ? 1 : 0); \
67     } while (0)
68 
69 #define optflag_testw(v) \
70     do { \
71 		CLEAR_CZNV ();\
72 		SET_ZFLG   ( (((uae_s16)(v)) == 0) ? 1 : 0);\
73 		SET_NFLG   ( (((uae_s16)(v)) < 0) ? 1 : 0); \
74     } while (0)
75 
76 #define optflag_testb(v) \
77     do { \
78 		CLEAR_CZNV ();\
79 		SET_ZFLG   ( (((uae_s8)(v)) == 0) ? 1 : 0);\
80 		SET_NFLG   ( (((uae_s8)(v)) < 0) ? 1 : 0); \
81     } while (0)
82 
83 
84 
85 /*
86  * Add operations
87  *
88  * Perform v = s + d and set ZNCV accordingly
89  */
90 
91 #define optflag_addl(v, s, d) \
92  do {\
93 	v = ((uae_s32)(d)) + ((uae_s32)(s)); \
94 	int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \
95 	int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \
96 	int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \
97 	SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \
98 	SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \
99 	SET_CFLG ( (((uae_u32)(~d)) < ((uae_u32)(s))) ? 1 : 0); \
100 	COPY_CARRY (); \
101 	SET_NFLG ( flgn); \
102 } while (0)
103 
104 #define optflag_addw(v, s, d) \
105  do {\
106 	v = ((uae_s16)(d)) + ((uae_s16)(s)); \
107 	int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \
108 	int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \
109 	int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \
110 	SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \
111 	SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \
112 	SET_CFLG ( (((uae_u16)(~d)) < ((uae_u16)(s))) ? 1 : 0); \
113 	COPY_CARRY (); \
114 	SET_NFLG ( flgn); \
115 } while (0)
116 
117 #define optflag_addb(v, s, d) \
118  do {\
119 	v = ((uae_s8)(d)) + ((uae_s8)(s)); \
120 	int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \
121 	int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \
122 	int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \
123 	SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \
124 	SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \
125 	SET_CFLG ( (((uae_u8)(~d)) < ((uae_u8)(s))) ? 1 : 0); \
126 	COPY_CARRY (); \
127 	SET_NFLG ( flgn); \
128 } while (0)
129 
130 /*
131  * Subtraction operations
132  *
133  * Perform v = d - s and set ZNCV accordingly
134  */
135 
136 #define optflag_subb(v, s, d) \
137 do {\
138 	v = ((uae_s8)(d)) - ((uae_s8)(s)); \
139 	int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \
140 	int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \
141 	int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \
142 	SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \
143 	SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \
144 	SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \
145 	COPY_CARRY (); \
146 	SET_NFLG ( flgn); \
147 } while (0)
148 
149 #define optflag_subw(v, s, d) \
150 do {\
151 	v = ((uae_s16)(d)) - ((uae_s16)(s)); \
152 	int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \
153 	int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \
154 	int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \
155 	SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \
156 	SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \
157 	SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \
158 	COPY_CARRY (); \
159 	SET_NFLG ( flgn); \
160 } while (0)
161 
162 #define optflag_subl(v, s, d) \
163 do {\
164 	v = ((uae_s32)(d)) - ((uae_s32)(s)); \
165 	int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \
166 	int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \
167 	int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \
168 	SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \
169 	SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \
170 	SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \
171 	COPY_CARRY (); \
172 	SET_NFLG ( flgn); \
173 } while (0)
174 
175 
176 /*
177  * Compare operations
178  */
179 
180 #define optflag_cmpb(s, d) \
181 do {\
182 uae_u32 	v = ((uae_s8)(d)) - ((uae_s8)(s)); \
183 	int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \
184 	int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \
185 	int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \
186 	SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \
187 	SET_VFLG ( (flgs != flgo) && (flgn != flgo));\
188 	SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \
189 	SET_NFLG ( flgn); \
190 }while (0)
191 
192 
193 #define optflag_cmpw(s, d) \
194 do {\
195 uae_u32 	v = ((uae_s16)(d)) - ((uae_s16)(s)); \
196 	int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \
197 	int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \
198 	int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \
199 	SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \
200 	SET_VFLG ( (flgs != flgo) && (flgn != flgo));\
201 	SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \
202 	SET_NFLG ( flgn); \
203 }while (0)
204 
205 #define optflag_cmpl(s, d) \
206 do {\
207 uae_u32 	v = ((uae_s32)(d)) - ((uae_s32)(s)); \
208 	int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \
209 	int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \
210 	int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \
211 	SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \
212 	SET_VFLG ( (flgs != flgo) && (flgn != flgo));\
213 	SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \
214 	SET_NFLG ( flgn); \
215 }while (0)
216 
217 #else
218 
219 #warning "OPT TESTFLAG"
220 /*
221  * Optimized code which uses the host CPU's condition flags to evaluate
222  * 68K CCR flags for certain operations.
223  *
224  * These are used by various opcode handlers when
225  * gencpu has been built with OPTIMIZED_FLAGS defined
226  */
227 
228 /*
229  * Test operations
230  *
231  * Evaluate operand and set Z and N flags. Always clear C and V.
232  */
233 /* Is there any way to do this without declaring *all* memory clobbered?
234    I.e. any way to tell gcc that some byte-sized value is in %al? */
235 #ifdef __APPLE__
236 #define optflag_testl(v) \
237   __asm__ __volatile__ ("andl %0,%0\n\t" \
238 			"lahf\n\t" \
239 			"seto %%al\n\t" \
240 			"movb %%al,_regflags\n\t" \
241 			"movb %%ah,_regflags+1\n\t" \
242 			:: "r" (v) : "%eax","cc","memory")
243 #define optflag_testw(v) \
244   __asm__ __volatile__ ("andw %w0,%w0\n\t" \
245 			"lahf\n\t" \
246 			"seto %%al\n\t" \
247 			"movb %%al,_regflags\n\t" \
248 			"movb %%ah,_regflags+1\n\t" \
249 			:: "r" (v) : "%eax","cc","memory")
250 
251 #define optflag_testb(v) \
252   __asm__ __volatile__ ("andb %b0,%b0\n\t" \
253 			"lahf\n\t" \
254 			"seto %%al\n\t" \
255 			"movb %%al,_regflags\n\t" \
256 			"movb %%ah,_regflags+1\n\t" \
257 			:: "q" (v) : "%eax","cc","memory")
258 
259 #define optflag_addl(v, s, d) do { \
260   __asm__ __volatile__ ("addl %k1,%k0\n\t" \
261 			"lahf\n\t" \
262 			"seto %%al\n\t" \
263 			"movb %%al,_regflags\n\t" \
264 			"movb %%ah,_regflags+1\n\t" \
265 			:"=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
266 	regflags.x = regflags.cznv; \
267     } while (0)
268 #define optflag_addw(v, s, d) do { \
269   __asm__ __volatile__ ("addw %w1,%w0\n\t" \
270 			"lahf\n\t" \
271 			"seto %%al\n\t" \
272 			"movb %%al,_regflags\n\t" \
273 			"movb %%ah,_regflags+1\n\t" \
274 			: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
275 	regflags.x = regflags.cznv; \
276     } while (0)
277 
278 #define optflag_addb(v, s, d) do { \
279   __asm__ __volatile__ ("addb %b1,%b0\n\t" \
280 			"lahf\n\t" \
281 			"seto %%al\n\t" \
282 			"movb %%al,_regflags\n\t" \
283 			"movb %%ah,_regflags+1\n\t" \
284 			:"=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
285 	regflags.x = regflags.cznv; \
286     } while (0)
287 
288 #define optflag_subl(v, s, d) do { \
289   __asm__ __volatile__ ("subl %k1,%k0\n\t" \
290 			"lahf\n\t" \
291 			"seto %%al\n\t" \
292 			"movb %%al,_regflags\n\t" \
293 			"movb %%ah,_regflags+1\n\t" \
294 			: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
295 	regflags.x = regflags.cznv; \
296     } while (0)
297 
298 #define optflag_subw(v, s, d) do { \
299   __asm__ __volatile__ ("subw %w1,%w0\n\t" \
300 			"lahf\n\t" \
301 			"seto %%al\n\t" \
302 			"movb %%al,_regflags\n\t" \
303 			"movb %%ah,_regflags+1\n\t" \
304 			: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
305 	regflags.x = regflags.cznv; \
306     } while (0)
307 
308 #define optflag_subb(v, s, d) do { \
309    __asm__ __volatile__ ("subb %b1,%b0\n\t" \
310 			"lahf\n\t" \
311 			"seto %%al\n\t" \
312 			"movb %%al,_regflags\n\t" \
313 			"movb %%ah,_regflags+1\n\t" \
314 			: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
315 	regflags.x = regflags.cznv; \
316     } while (0)
317 
318 #define optflag_cmpl(s, d) \
319   __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
320 			"lahf\n\t" \
321 			"seto %%al\n\t" \
322 			"movb %%al,_regflags\n\t" \
323 			"movb %%ah,_regflags+1\n\t" \
324 			:: "rmi" (s), "r" (d) : "%eax","cc","memory")
325 
326 #define optflag_cmpw(s, d) \
327   __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
328 			"lahf\n\t" \
329 			"seto %%al\n\t" \
330 			"movb %%al,_regflags\n\t" \
331 			"movb %%ah,_regflags+1\n\t" \
332 			:: "rmi" (s), "r" (d) : "%eax","cc","memory");
333 
334 #define optflag_cmpb(s, d) \
335   __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
336 			"lahf\n\t" \
337 			"seto %%al\n\t" \
338 			"movb %%al,_regflags\n\t" \
339 			"movb %%ah,_regflags+1\n\t" \
340 			:: "qmi" (s), "q" (d) : "%eax","cc","memory")
341 #else /*ifdef apple*/
342 #define optflag_testl(v) \
343   __asm__ __volatile__ ("andl %0,%0\n\t" \
344 			"lahf\n\t" \
345 			"seto %%al\n\t" \
346 			"movb %%al,regflags\n\t" \
347 			"movb %%ah,regflags+1\n\t" \
348 			:: "r" (v) : "%eax","cc","memory")
349 #define optflag_testw(v) \
350   __asm__ __volatile__ ("andw %w0,%w0\n\t" \
351 			"lahf\n\t" \
352 			"seto %%al\n\t" \
353 			"movb %%al,regflags\n\t" \
354 			"movb %%ah,regflags+1\n\t" \
355 			:: "r" (v) : "%eax","cc","memory")
356 
357 #define optflag_testb(v) \
358   __asm__ __volatile__ ("andb %b0,%b0\n\t" \
359 			"lahf\n\t" \
360 			"seto %%al\n\t" \
361 			"movb %%al,regflags\n\t" \
362 			"movb %%ah,regflags+1\n\t" \
363 			:: "q" (v) : "%eax","cc","memory")
364 
365 #define optflag_addl(v, s, d) do { \
366   __asm__ __volatile__ ("addl %k1,%k0\n\t" \
367 			"lahf\n\t" \
368 			"seto %%al\n\t" \
369 			"movb %%al,regflags\n\t" \
370 			"movb %%ah,regflags+1\n\t" \
371 			:"=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
372 	regflags.x = regflags.cznv; \
373     } while (0)
374 #define optflag_addw(v, s, d) do { \
375   __asm__ __volatile__ ("addw %w1,%w0\n\t" \
376 			"lahf\n\t" \
377 			"seto %%al\n\t" \
378 			"movb %%al,regflags\n\t" \
379 			"movb %%ah,regflags+1\n\t" \
380 			: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
381 	regflags.x = regflags.cznv; \
382     } while (0)
383 
384 #define optflag_addb(v, s, d) do { \
385   __asm__ __volatile__ ("addb %b1,%b0\n\t" \
386 			"lahf\n\t" \
387 			"seto %%al\n\t" \
388 			"movb %%al,regflags\n\t" \
389 			"movb %%ah,regflags+1\n\t" \
390 			:"=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
391 	regflags.x = regflags.cznv; \
392     } while (0)
393 
394 #define optflag_subl(v, s, d) do { \
395   __asm__ __volatile__ ("subl %k1,%k0\n\t" \
396 			"lahf\n\t" \
397 			"seto %%al\n\t" \
398 			"movb %%al,regflags\n\t" \
399 			"movb %%ah,regflags+1\n\t" \
400 			: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
401 	regflags.x = regflags.cznv; \
402     } while (0)
403 
404 #define optflag_subw(v, s, d) do { \
405   __asm__ __volatile__ ("subw %w1,%w0\n\t" \
406 			"lahf\n\t" \
407 			"seto %%al\n\t" \
408 			"movb %%al,regflags\n\t" \
409 			"movb %%ah,regflags+1\n\t" \
410 			: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
411 	regflags.x = regflags.cznv; \
412     } while (0)
413 
414 #define optflag_subb(v, s, d) do { \
415    __asm__ __volatile__ ("subb %b1,%b0\n\t" \
416 			"lahf\n\t" \
417 			"seto %%al\n\t" \
418 			"movb %%al,regflags\n\t" \
419 			"movb %%ah,regflags+1\n\t" \
420 			: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
421 	regflags.x = regflags.cznv; \
422     } while (0)
423 
424 #define optflag_cmpl(s, d) \
425   __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
426 			"lahf\n\t" \
427 			"seto %%al\n\t" \
428 			"movb %%al,regflags\n\t" \
429 			"movb %%ah,regflags+1\n\t" \
430 			:: "rmi" (s), "r" (d) : "%eax","cc","memory")
431 
432 #define optflag_cmpw(s, d) \
433   __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
434 			"lahf\n\t" \
435 			"seto %%al\n\t" \
436 			"movb %%al,regflags\n\t" \
437 			"movb %%ah,regflags+1\n\t" \
438 			:: "rmi" (s), "r" (d) : "%eax","cc","memory");
439 
440 #define optflag_cmpb(s, d) \
441   __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
442 			"lahf\n\t" \
443 			"seto %%al\n\t" \
444 			"movb %%al,regflags\n\t" \
445 			"movb %%ah,regflags+1\n\t" \
446 			:: "qmi" (s), "q" (d) : "%eax","cc","memory")
447 #endif /*ifdef apple*/
448 
449 #endif
450 
451 #else
452 /*
453 #define FLAGBIT_N	31
454 #define FLAGBIT_Z	30
455 #define FLAGBIT_C	29
456 #define FLAGBIT_V	28
457 #define FLAGBIT_X	29
458 */
459 /* ARM COND
460 31 30 29 28
461 N  Z  C  V
462 */
463 #if ARM_OPT_TEST
464 
465 #define optflag_testl(v) \
466          __asm__ __volatile__ (  \
467 		"adds %1,%1,#0 \n"\
468   		"mrs   %0, cpsr  \n"\
469 		: "=r" (regflags.cznv) \
470 		: "r" (v)\
471 		: "cc"\
472 		);
473 
474 #define optflag_testw(v) optflag_testl((uae_s32)(v))
475 #define optflag_testb(v) optflag_testl((uae_s32)(v))
476 
477 #define optflag_addlong(v, s, d) \
478          __asm__ __volatile__ ( \
479         	"adds %1,%2,%3 \n"\
480   		"mrs   %0, cpsr  \n"\
481 		: "=r" (regflags.cznv), "=r" (v) \
482 		: "r" (s), "r" (d) \
483 		: "cc"\
484 		);
485 
486 #define optflag_addl(v, s, d) do { optflag_addlong(v, s, d); regflags.x = regflags.cznv; } while (0)
487 #define optflag_addw(v, s, d) do { optflag_addlong(v, (s) << 16, (d) << 16); v = v >> 16; regflags.x = regflags.cznv; } while (0)
488 #define optflag_addb(v, s, d) do { optflag_addlong(v, (s) << 24, (d) << 24); v = v >> 24; regflags.x = regflags.cznv; } while (0)
489 
490 #define optflag_sublong(v, s, d) \
491 	__asm__ __volatile__ (\
492 		"rsbs  %1, %2, %3\n\t" \
493   		"mrs   %0, cpsr   \n"\
494 		"eor %0,%0,#0x20000000 \n"\
495 		: "=r" (regflags.cznv), "=r" (v) \
496 		: "r" (s), "r" (d) \
497 		: "cc"\
498 	);
499 
500 #define optflag_subl(v, s, d) do { optflag_sublong(v, s, d); regflags.x = regflags.cznv; } while (0)
501 #define optflag_subw(v, s, d) do { optflag_sublong(v, (s) << 16, (d) << 16); v = v >> 16; regflags.x = regflags.cznv; } while (0)
502 #define optflag_subb(v, s, d) do { optflag_sublong(v, (s) << 24, (d) << 24); v = v >> 24; regflags.x = regflags.cznv; } while (0)
503 
504 #define  optflag_cmplong(s,d) \
505 	register int tmp;\
506     	__asm__ __volatile__ (  \
507 	       "rsbs   	%1, %2,%3		\n"\
508                "mrs     %0, cpsr 	 	\n"\
509 	       "eor %0,%0,#0x20000000 \n"\
510  		:"=r"(regflags.cznv) ,"=r"(tmp)	\
511        		:"r" (s), "r" (d)\
512              	:"cc"      	\
513          );
514 
515 #define optflag_cmpl(s, d) optflag_cmplong(s, d)
516 #define optflag_cmpw(s, d) optflag_cmplong((s) << 16, (d) << 16)
517 #define optflag_cmpb(s, d) optflag_cmplong((s) << 24, (d) << 24)
518 
519 
520 #else
521 
522 #define FLAGBIT_N	15
523 #define FLAGBIT_Z	14
524 #define FLAGBIT_C	8
525 #define FLAGBIT_V	0
526 #define FLAGBIT_X	8
527 
528 #define FLAGVAL_N	(1 << FLAGBIT_N)
529 #define FLAGVAL_Z 	(1 << FLAGBIT_Z)
530 #define FLAGVAL_C	(1 << FLAGBIT_C)
531 #define FLAGVAL_V	(1 << FLAGBIT_V)
532 #define FLAGVAL_X	(1 << FLAGBIT_X)
533 
534 #define SET_ZFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_Z) | (((y) ? 1 : 0) << FLAGBIT_Z))
535 #define SET_CFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_C) | (((y) ? 1 : 0) << FLAGBIT_C))
536 #define SET_VFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_V) | (((y) ? 1 : 0) << FLAGBIT_V))
537 #define SET_NFLG(y)	(regflags.cznv = (regflags.cznv & ~FLAGVAL_N) | (((y) ? 1 : 0) << FLAGBIT_N))
538 #define SET_XFLG(y)	(regflags.x    = ((y) ? 1 : 0) << FLAGBIT_X)
539 
540 #define GET_ZFLG()	((regflags.cznv >> FLAGBIT_Z) & 1)
541 #define GET_CFLG()	((regflags.cznv >> FLAGBIT_C) & 1)
542 #define GET_VFLG()	((regflags.cznv >> FLAGBIT_V) & 1)
543 #define GET_NFLG()	((regflags.cznv >> FLAGBIT_N) & 1)
544 #define GET_XFLG()	((regflags.x    >> FLAGBIT_X) & 1)
545 
546 #define CLEAR_CZNV()	(regflags.cznv  = 0)
547 #define GET_CZNV	(regflags.cznv)
548 #define IOR_CZNV(X)	(regflags.cznv |= (X))
549 #define SET_CZNV(X)	(regflags.cznv  = (X))
550 
551 #define COPY_CARRY() (regflags.x = regflags.cznv)
552 
553 /*
554  * Test operations
555  *
556  * Evaluate operand and set Z and N flags. Always clear C and V.
557  */
558 
559 
560 #define optflag_testl(v) \
561     do { \
562 		CLEAR_CZNV ();\
563 		SET_ZFLG   ( (((uae_s32)(v)) == 0) ? 1 : 0);\
564 		SET_NFLG   ( (((uae_s32)(v)) < 0) ? 1 : 0); \
565     } while (0)
566 
567 #define optflag_testw(v) \
568     do { \
569 		CLEAR_CZNV ();\
570 		SET_ZFLG   ( (((uae_s16)(v)) == 0) ? 1 : 0);\
571 		SET_NFLG   ( (((uae_s16)(v)) < 0) ? 1 : 0); \
572     } while (0)
573 
574 #define optflag_testb(v) \
575     do { \
576 		CLEAR_CZNV ();\
577 		SET_ZFLG   ( (((uae_s8)(v)) == 0) ? 1 : 0);\
578 		SET_NFLG   ( (((uae_s8)(v)) < 0) ? 1 : 0); \
579     } while (0)
580 
581 
582 
583 /*
584  * Add operations
585  *
586  * Perform v = s + d and set ZNCV accordingly
587  */
588 
589 #define optflag_addl(v, s, d) \
590  do {\
591 	v = ((uae_s32)(d)) + ((uae_s32)(s)); \
592 	int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \
593 	int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \
594 	int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \
595 	SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \
596 	SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \
597 	SET_CFLG ( (((uae_u32)(~d)) < ((uae_u32)(s))) ? 1 : 0); \
598 	COPY_CARRY (); \
599 	SET_NFLG ( flgn); \
600 } while (0)
601 
602 #define optflag_addw(v, s, d) \
603  do {\
604 	v = ((uae_s16)(d)) + ((uae_s16)(s)); \
605 	int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \
606 	int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \
607 	int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \
608 	SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \
609 	SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \
610 	SET_CFLG ( (((uae_u16)(~d)) < ((uae_u16)(s))) ? 1 : 0); \
611 	COPY_CARRY (); \
612 	SET_NFLG ( flgn); \
613 } while (0)
614 
615 #define optflag_addb(v, s, d) \
616  do {\
617 	v = ((uae_s8)(d)) + ((uae_s8)(s)); \
618 	int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \
619 	int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \
620 	int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \
621 	SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \
622 	SET_VFLG ( (flgs ^ flgn) & (flgo ^ flgn)); \
623 	SET_CFLG ( (((uae_u8)(~d)) < ((uae_u8)(s))) ? 1 : 0); \
624 	COPY_CARRY (); \
625 	SET_NFLG ( flgn); \
626 } while (0)
627 
628 /*
629  * Subtraction operations
630  *
631  * Perform v = d - s and set ZNCV accordingly
632  */
633 
634 #define optflag_subb(v, s, d) \
635 do {\
636 	v = ((uae_s8)(d)) - ((uae_s8)(s)); \
637 	int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \
638 	int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \
639 	int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \
640 	SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \
641 	SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \
642 	SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \
643 	COPY_CARRY (); \
644 	SET_NFLG ( flgn); \
645 } while (0)
646 
647 #define optflag_subw(v, s, d) \
648 do {\
649 	v = ((uae_s16)(d)) - ((uae_s16)(s)); \
650 	int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \
651 	int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \
652 	int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \
653 	SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \
654 	SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \
655 	SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \
656 	COPY_CARRY (); \
657 	SET_NFLG ( flgn); \
658 } while (0)
659 
660 #define optflag_subl(v, s, d) \
661 do {\
662 	v = ((uae_s32)(d)) - ((uae_s32)(s)); \
663 	int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \
664 	int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \
665 	int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \
666 	SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \
667 	SET_VFLG ( (flgs ^ flgo) & (flgn ^ flgo)); \
668 	SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \
669 	COPY_CARRY (); \
670 	SET_NFLG ( flgn); \
671 } while (0)
672 
673 
674 /*
675  * Compare operations
676  */
677 
678 #define optflag_cmpb(s, d) \
679 do {\
680 uae_u32 	v = ((uae_s8)(d)) - ((uae_s8)(s)); \
681 	int flgs = (((uae_s8)(s)) < 0) ? 1 : 0; \
682 	int flgo = (((uae_s8)(d)) < 0) ? 1 : 0; \
683 	int flgn = (((uae_s8)(v)) < 0) ? 1 : 0; \
684 	SET_ZFLG ( (((uae_s8)(v)) == 0) ? 1 : 0); \
685 	SET_VFLG ( (flgs != flgo) && (flgn != flgo));\
686 	SET_CFLG ( (((uae_u8)(s)) > ((uae_u8)(d))) ? 1 : 0); \
687 	SET_NFLG ( flgn); \
688 }while (0)
689 
690 
691 #define optflag_cmpw(s, d) \
692 do {\
693 uae_u32 	v = ((uae_s16)(d)) - ((uae_s16)(s)); \
694 	int flgs = (((uae_s16)(s)) < 0) ? 1 : 0; \
695 	int flgo = (((uae_s16)(d)) < 0) ? 1 : 0; \
696 	int flgn = (((uae_s16)(v)) < 0) ? 1 : 0; \
697 	SET_ZFLG ( (((uae_s16)(v)) == 0) ? 1 : 0); \
698 	SET_VFLG ( (flgs != flgo) && (flgn != flgo));\
699 	SET_CFLG ( (((uae_u16)(s)) > ((uae_u16)(d))) ? 1 : 0); \
700 	SET_NFLG ( flgn); \
701 }while (0)
702 
703 #define optflag_cmpl(s, d) \
704 do {\
705 uae_u32 	v = ((uae_s32)(d)) - ((uae_s32)(s)); \
706 	int flgs = (((uae_s32)(s)) < 0) ? 1 : 0; \
707 	int flgo = (((uae_s32)(d)) < 0) ? 1 : 0; \
708 	int flgn = (((uae_s32)(v)) < 0) ? 1 : 0; \
709 	SET_ZFLG ( (((uae_s32)(v)) == 0) ? 1 : 0); \
710 	SET_VFLG ( (flgs != flgo) && (flgn != flgo));\
711 	SET_CFLG ( (((uae_u32)(s)) > ((uae_u32)(d))) ? 1 : 0); \
712 	SET_NFLG ( flgn); \
713 }while (0)
714 
715 #endif
716 
717 #endif
718 
719 #endif /* EUAE_MACHDEP_M68KOPS_H */
720