--- BasiliskII/src/uae_cpu/m68k.h 1999/10/28 16:52:32 1.4 +++ BasiliskII/src/uae_cpu/m68k.h 2001/07/13 10:13:58 1.5 @@ -6,27 +6,41 @@ * Copyright 1996 Bernd Schmidt */ +#ifndef M68K_FLAGS_H +#define M68K_FLAGS_H + +#ifdef OPTIMIZED_FLAGS + #if defined(__i386__) && defined(X86_ASSEMBLY) +#ifndef SAHF_SETO_PROFITABLE + struct flag_struct { - unsigned int cznv; - unsigned int x; + uae_u32 cznv; + uae_u32 x; }; -#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6)) -#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11)) -#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7)) -#define SET_XFLG(y) (regflags.x = (y)) - -#define GET_ZFLG ((regflags.cznv >> 6) & 1) -#define GET_CFLG (regflags.cznv & 1) -#define GET_VFLG ((regflags.cznv >> 11) & 1) -#define GET_NFLG ((regflags.cznv >> 7) & 1) -#define GET_XFLG (regflags.x & 1) +#define FLAGVAL_Z 0x40 +#define FLAGVAL_N 0x80 + +#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6)) +#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1)) +#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11)) +#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7)) +#define SET_XFLG(y) (regflags.x = (y)) + +#define GET_ZFLG ((regflags.cznv >> 6) & 1) +#define GET_CFLG (regflags.cznv & 1) +#define GET_VFLG ((regflags.cznv >> 11) & 1) +#define GET_NFLG ((regflags.cznv >> 7) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.cznv = 0) +#define GET_CZNV (regflags.cznv) +#define IOR_CZNV(X) (regflags.cznv |= (X)) +#define SET_CZNV(X) (regflags.cznv = (X)) -#define CLEAR_CZNV (regflags.cznv = 0) -#define COPY_CARRY (regflags.x = regflags.cznv) +#define COPY_CARRY (regflags.x = regflags.cznv) extern struct flag_struct regflags __asm__ ("regflags"); @@ -58,25 +72,25 @@ static __inline__ int cctrue(int cc) return 0; } -#define x86_flag_testl(v) \ - __asm__ __volatile__ ("testl %1,%1\n\t" \ +#define optflag_testl(v) \ + __asm__ __volatile__ ("andl %1,%1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ : "=r" (regflags.cznv) : "r" (v) : "cc") -#define x86_flag_testw(v) \ - __asm__ __volatile__ ("testw %w1,%w1\n\t" \ +#define optflag_testw(v) \ + __asm__ __volatile__ ("andw %w1,%w1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ : "=r" (regflags.cznv) : "r" (v) : "cc") -#define x86_flag_testb(v) \ - __asm__ __volatile__ ("testb %b1,%b1\n\t" \ +#define optflag_testb(v) \ + __asm__ __volatile__ ("andb %b1,%b1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ : "=r" (regflags.cznv) : "q" (v) : "cc") -#define x86_flag_addl(v, s, d) do { \ +#define optflag_addl(v, s, d) do { \ __asm__ __volatile__ ("addl %k2,%k1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ @@ -84,7 +98,7 @@ static __inline__ int cctrue(int cc) COPY_CARRY; \ } while (0) -#define x86_flag_addw(v, s, d) do { \ +#define optflag_addw(v, s, d) do { \ __asm__ __volatile__ ("addw %w2,%w1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ @@ -92,7 +106,7 @@ static __inline__ int cctrue(int cc) COPY_CARRY; \ } while (0) -#define x86_flag_addb(v, s, d) do { \ +#define optflag_addb(v, s, d) do { \ __asm__ __volatile__ ("addb %b2,%b1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ @@ -100,7 +114,7 @@ static __inline__ int cctrue(int cc) COPY_CARRY; \ } while (0) -#define x86_flag_subl(v, s, d) do { \ +#define optflag_subl(v, s, d) do { \ __asm__ __volatile__ ("subl %k2,%k1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ @@ -108,7 +122,7 @@ static __inline__ int cctrue(int cc) COPY_CARRY; \ } while (0) -#define x86_flag_subw(v, s, d) do { \ +#define optflag_subw(v, s, d) do { \ __asm__ __volatile__ ("subw %w2,%w1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ @@ -116,7 +130,7 @@ static __inline__ int cctrue(int cc) COPY_CARRY; \ } while (0) -#define x86_flag_subb(v, s, d) do { \ +#define optflag_subb(v, s, d) do { \ __asm__ __volatile__ ("subb %b2,%b1\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ @@ -124,24 +138,196 @@ static __inline__ int cctrue(int cc) COPY_CARRY; \ } while (0) -#define x86_flag_cmpl(s, d) \ +#define optflag_cmpl(s, d) \ __asm__ __volatile__ ("cmpl %k1,%k2\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") -#define x86_flag_cmpw(s, d) \ +#define optflag_cmpw(s, d) \ __asm__ __volatile__ ("cmpw %w1,%w2\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ : "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc") -#define x86_flag_cmpb(s, d) \ +#define optflag_cmpb(s, d) \ __asm__ __volatile__ ("cmpb %b1,%b2\n\t" \ "pushfl\n\t" \ "popl %0\n\t" \ : "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc") +#else + +struct flag_struct { + uae_u32 cznv; + uae_u32 x; +}; + +#define FLAGVAL_Z 0x4000 +#define FLAGVAL_N 0x8000 + +#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14)) +#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8)) +#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1))) +#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15)) +#define SET_XFLG(y) (regflags.x = (y)) + +#define GET_ZFLG ((regflags.cznv >> 14) & 1) +#define GET_CFLG ((regflags.cznv >> 8) & 1) +#define GET_VFLG ((regflags.cznv >> 0) & 1) +#define GET_NFLG ((regflags.cznv >> 15) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.cznv = 0) +#define GET_CZNV (regflags.cznv) +#define IOR_CZNV(X) (regflags.cznv |= (X)) +#define SET_CZNV(X) (regflags.cznv = (X)) + +#define COPY_CARRY (regflags.x = (regflags.cznv)>>8) + +extern struct flag_struct regflags __asm__ ("regflags"); + +static __inline__ int cctrue(int cc) +{ + uae_u32 cznv = regflags.cznv; + switch(cc){ + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */ + case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */ + case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */ + case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */ + case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */ + case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */ + case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */ + case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */ + case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */ + case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */ + case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */ + case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */ + case 14: + cznv &= 0xc001; + return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ + case 15: + cznv &= 0xc001; + return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + } + abort(); + return 0; +} + +/* Is there any way to do this without declaring *all* memory clobbered? + I.e. any way to tell gcc that some byte-sized value is in %al? */ +#define optflag_testl(v) \ + __asm__ __volatile__ ("andl %0,%0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "r" (v) : "%eax","cc","memory") + +#define optflag_testw(v) \ + __asm__ __volatile__ ("andw %w0,%w0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "r" (v) : "%eax","cc","memory") + +#define optflag_testb(v) \ + __asm__ __volatile__ ("andb %b0,%b0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "q" (v) : "%eax","cc","memory") + +#define optflag_addl(v, s, d) do { \ + __asm__ __volatile__ ("addl %k1,%k0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_addw(v, s, d) do { \ + __asm__ __volatile__ ("addw %w1,%w0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_addb(v, s, d) do { \ + __asm__ __volatile__ ("addb %b1,%b0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_subl(v, s, d) do { \ + __asm__ __volatile__ ("subl %k1,%k0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_subw(v, s, d) do { \ + __asm__ __volatile__ ("subw %w1,%w0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_subb(v, s, d) do { \ + __asm__ __volatile__ ("subb %b1,%b0\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \ + COPY_CARRY; \ + } while (0) + +#define optflag_cmpl(s, d) \ + __asm__ __volatile__ ("cmpl %k0,%k1\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "rmi" (s), "r" (d) : "%eax","cc","memory") + +#define optflag_cmpw(s, d) \ + __asm__ __volatile__ ("cmpw %w0,%w1\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "rmi" (s), "r" (d) : "%eax","cc","memory"); + +#define optflag_cmpb(s, d) \ + __asm__ __volatile__ ("cmpb %b0,%b1\n\t" \ + "lahf\n\t" \ + "seto %%al\n\t" \ + "movb %%al,regflags\n\t" \ + "movb %%ah,regflags+1\n\t" \ + : : "qmi" (s), "q" (d) : "%eax","cc","memory") + +#endif + #elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)) struct flag_struct { @@ -151,19 +337,26 @@ struct flag_struct { extern struct flag_struct regflags; -#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) -#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) -#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) -#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) -#define SET_XFLG(y) (regflags.x = (y)) - -#define GET_ZFLG ((regflags.nzvc >> 2) & 1) -#define GET_CFLG (regflags.nzvc & 1) -#define GET_VFLG ((regflags.nzvc >> 1) & 1) -#define GET_NFLG ((regflags.nzvc >> 3) & 1) -#define GET_XFLG (regflags.x & 1) +#define FLAGVAL_Z 0x04 +#define FLAGVAL_N 0x08 + +#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2)) +#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1)) +#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1)) +#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3)) +#define SET_XFLG(y) (regflags.x = (y)) + +#define GET_ZFLG ((regflags.nzvc >> 2) & 1) +#define GET_CFLG (regflags.nzvc & 1) +#define GET_VFLG ((regflags.nzvc >> 1) & 1) +#define GET_NFLG ((regflags.nzvc >> 3) & 1) +#define GET_XFLG (regflags.x & 1) + +#define CLEAR_CZNV (regflags.nzvc = 0) +#define GET_CZNV (reflags.nzvc) +#define IOR_CZNV(X) (refglags.nzvc |= (X)) +#define SET_CZNV(X) (regflags.nzvc = (X)) -#define CLEAR_CZNV (regflags.nzvc = 0) #define COPY_CARRY (regflags.x = regflags.nzvc) static __inline__ int cctrue(int cc) @@ -787,6 +980,8 @@ static inline uae_u32 sparc_v9_flag_addx #endif /* SPARC_V9_ASSEMBLY */ +#endif + #else struct flag_struct { @@ -805,6 +1000,27 @@ extern struct flag_struct regflags; #define VFLG (regflags.v) #define XFLG (regflags.x) +#define SET_CFLG(x) (CFLG = (x)) +#define SET_NFLG(x) (NFLG = (x)) +#define SET_VFLG(x) (VFLG = (x)) +#define SET_ZFLG(x) (ZFLG = (x)) +#define SET_XFLG(x) (XFLG = (x)) + +#define GET_CFLG CFLG +#define GET_NFLG NFLG +#define GET_VFLG VFLG +#define GET_ZFLG ZFLG +#define GET_XFLG XFLG + +#define CLEAR_CZNV do { \ + SET_CFLG (0); \ + SET_ZFLG (0); \ + SET_NFLG (0); \ + SET_VFLG (0); \ +} while (0) + +#define COPY_CARRY (SET_XFLG (GET_CFLG)) + static __inline__ int cctrue(const int cc) { switch(cc){ @@ -828,4 +1044,6 @@ static __inline__ int cctrue(const int c return 0; } -#endif +#endif /* OPTIMIZED_FLAGS */ + +#endif /* M68K_FLAGS_H */