Workarounds for 68020+ instructions not supported by 68000, 68010, and sometimes CPU32 --- drivers/video/amifb.c | 69 +++++++++++++++++++++---------------------- include/asm-m68k/delay.h | 24 +++++++++++++- include/asm-m68k/div64.h | 10 ++++++ include/asm-m68k/signal.h | 5 +++ include/asm-m68k/unaligned.h | 26 +++++++++++++++- 5 files changed, 97 insertions(+), 37 deletions(-) --- linux-m68k-2.6.8.1+uc0/drivers/video/amifb.c 2004-08-04 12:14:16.000000000 +0200 +++ uClinux-amiga-2.6.8.1/drivers/video/amifb.c 2004-05-03 21:45:14.000000000 +0200 @@ -578,14 +578,14 @@ static u_short maxfmode, chipset; #define modx(x,v) ((v) & ((x)-1)) /* if x1 is not a constant, this macro won't make real sense :-) */ -#ifdef __mc68000__ -#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \ - "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;}) -#else +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) /* We know a bit about the numbers, so we can do it this way */ #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \ ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2)) -#endif +#else /* 68020 or higher */ +#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \ + "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;}) +#endif /* 68020 or higher */ #define highw(x) ((u_long)(x)>>16 & 0xffff) #define loww(x) ((u_long)(x) & 0xffff) @@ -3358,12 +3358,13 @@ static int ami_get_var_cursorinfo(struct for (width = (short)var->width-1; width >= 0; width--) { if (bits == 0) { bits = 16; --words; -#ifdef __mc68000__ +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) + datawords = (*(lspr+delta) << 16) | *lspr; + lspr++; +#else /* 68020 or higher */ asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0" : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta)); -#else - datawords = (*(lspr+delta) << 16) | (*lspr++); -#endif +#endif /* 68020 or higher */ } --bits; #ifdef __mc68000__ @@ -3383,17 +3384,17 @@ static int ami_get_var_cursorinfo(struct } while (--words >= 0) ++lspr; -#ifdef __mc68000__ - asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:" - : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta)); -#else +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) lspr += delta; if (sspr) { u_short *tmp = lspr; lspr = sspr; sspr = tmp; } -#endif +#else /* 68020 or higher */ + asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:" + : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta)); +#endif /* 68020 or higher */ } return 0; } @@ -3462,47 +3463,47 @@ static int ami_set_var_cursorinfo(struct #endif if (--bits == 0) { bits = 16; --words; -#ifdef __mc68000__ - asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+" - : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta)); -#else +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) *(lspr+delta) = (u_short) (datawords >> 16); *lspr++ = (u_short) (datawords & 0xffff); -#endif +#else /* 68020 or higher */ + asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+" + : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta)); +#endif /* 68020 or higher */ } } if (bits < 16) { --words; -#ifdef __mc68000__ +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) + *(lspr+delta) = (u_short) (datawords >> (16+bits)); + *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits); +#else /* 68020 or higher */ asm volatile ( "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; " "swap %2 ; lslw %4,%2 ; movew %2,%0@+" : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits)); -#else - *(lspr+delta) = (u_short) (datawords >> (16+bits)); - *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits); -#endif +#endif /* 68020 or higher */ } while (--words >= 0) { -#ifdef __mc68000__ - asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+" - : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0"); -#else +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) *(lspr+delta) = 0; *lspr++ = 0; -#endif +#else /* 68020 or higher */ + asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+" + : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0"); +#endif /* 68020 or higher */ } -#ifdef __mc68000__ - asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:" - : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta)); -#else +#if !defined(__mc68000__) || defined(CONFIG_M68000) || defined(CONFIG_M68010) lspr += delta; if (sspr) { u_short *tmp = lspr; lspr = sspr; sspr = tmp; } -#endif +#else /* 68020 or higher */ + asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:" + : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta)); +#endif /* 68020 or higher */ } par->crsr.height = var->height; par->crsr.width = var->width; --- linux-m68k-2.6.8.1+uc0/include/asm-m68k/delay.h 2004-05-24 11:13:52.000000000 +0200 +++ uClinux-amiga-2.6.8.1/include/asm-m68k/delay.h 2004-06-26 17:17:49.000000000 +0200 @@ -1,6 +1,8 @@ #ifndef _M68K_DELAY_H #define _M68K_DELAY_H +#include + #include /* @@ -15,8 +17,6 @@ static inline void __delay(unsigned long : "=d" (loops) : "0" (loops)); } -extern void __bad_udelay(void); - /* * Use only for very small delays ( < 1 msec). Should probably use a * lookup table, really, as the multiplications take much too long with @@ -24,6 +24,24 @@ extern void __bad_udelay(void); * first constant multiplications gets optimized away if the delay is * a constant) */ + +#if defined(CONFIG_M68000) || defined(CONFIG_M68010) + +static inline void udelay(unsigned long usecs) +{ + unsigned long full_loops, part_loops; + + full_loops = ((usecs * HZ) / 1000000) * loops_per_jiffy; + usecs %= (1000000 / HZ); + part_loops = (usecs * HZ * loops_per_jiffy) / 1000000; + + __delay(full_loops + part_loops); +} + +#else /* 68020 or higher */ + +extern void __bad_udelay(void); + static inline void __const_udelay(unsigned long xloops) { unsigned long tmp; @@ -69,4 +74,6 @@ static inline unsigned long muldiv(unsig return a; } +#endif /* 68020 or higher */ + #endif /* defined(_M68K_DELAY_H) */ --- linux-m68k-2.6.8.1+uc0/include/asm-m68k/div64.h 2004-04-27 20:50:47.000000000 +0200 +++ uClinux-amiga-2.6.8.1/include/asm-m68k/div64.h 2004-05-03 21:45:14.000000000 +0200 @@ -1,8 +1,16 @@ #ifndef _M68K_DIV64_H #define _M68K_DIV64_H +#include + /* n = n / base; return rem; */ +#if defined(CONFIG_M68000) || defined(CONFIG_M68010) + +#include + +#else /* 68020 or higher */ + #define do_div(n, base) ({ \ union { \ unsigned long n32[2]; \ @@ -26,4 +34,6 @@ __rem; \ }) +#endif /* 68020 or higher */ + #endif /* _M68K_DIV64_H */ --- linux-m68k-2.6.8.1+uc0/include/asm-m68k/signal.h 2004-05-24 11:13:53.000000000 +0200 +++ uClinux-amiga-2.6.8.1/include/asm-m68k/signal.h 2004-06-26 17:17:50.000000000 +0200 @@ -1,6 +1,7 @@ #ifndef _M68K_SIGNAL_H #define _M68K_SIGNAL_H +#include #include /* Avoid too many header ordering problems. */ @@ -174,6 +175,8 @@ typedef struct sigaltstack { #ifdef __KERNEL__ #include +#if !defined(CONFIG_M68000) && !defined(CONFIG_M68010) /* 68020 or higher */ + #define __HAVE_ARCH_SIG_BITOPS static inline void sigaddset(sigset_t *set, int _sig) @@ -213,6 +216,8 @@ static inline int sigfindinword(unsigned return word ^ 31; } +#endif /* 68020 or higher */ + #define HAVE_ARCH_GET_SIGNAL_TO_DELIVER #endif /* __KERNEL__ */ --- linux-m68k-2.6.8.1+uc0/include/asm-m68k/unaligned.h 2004-05-24 11:13:53.000000000 +0200 +++ uClinux-amiga-2.6.8.1/include/asm-m68k/unaligned.h 2004-06-26 17:17:50.000000000 +0200 @@ -1,8 +1,30 @@ #ifndef __M68K_UNALIGNED_H #define __M68K_UNALIGNED_H +#include + +#if defined(CONFIG_M68000) || defined(CONFIG_M68010) || defined(CONFIG_MCPU32) + +/* Use memmove here, so gcc does not insert a __builtin_memcpy. */ + +#define get_unaligned(ptr) \ + ({ \ + __typeof__(*(ptr)) __tmp; \ + memmove(&__tmp, (ptr), sizeof(*(ptr))); \ + __tmp; \ + }) + +#define put_unaligned(val, ptr) \ + ({ \ + __typeof__(*(ptr)) __tmp = (val); \ + memmove((ptr), &__tmp, sizeof(*(ptr))); \ + (void)0; \ + }) + +#else /* 68020 or higher */ + /* - * The m68k can do unaligned accesses itself. + * 68020 or higher can do unaligned accesses theirselves. * * * The strange macros are there to make sure these can't @@ -13,4 +27,6 @@ #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) +#endif /* 68020 or higher */ + #endif