Move _FASTRMOVE implementation into headers & support new hcall
This moves _FASTREMOVE to the cache.h header, 970 uses the existing code, p7 now uses the new memop hcall. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
0dfcbc1336
commit
7add7a0a9f
|
@ -37,4 +37,50 @@ cache_inhibited_access(uint16_t, 16)
|
|||
cache_inhibited_access(uint32_t, 32)
|
||||
cache_inhibited_access(uint64_t, 64)
|
||||
|
||||
#define _FWOVERLAP(s, d, size) ((d >= s) && ((type_u)d < ((type_u)s + size)))
|
||||
|
||||
// 3.1
|
||||
#define _FWMOVE(s, d, size, t) \
|
||||
{ t *s1=(t *)s, *d1=(t *)d; \
|
||||
while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } }
|
||||
|
||||
#define _BWMOVE(s, d, size, t) { \
|
||||
t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); \
|
||||
while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
|
||||
}
|
||||
|
||||
|
||||
#define _MOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWMOVE(s, d, size, t) else _FWMOVE(s, d, size, t)
|
||||
|
||||
#define _FASTMOVE(s, d, size) \
|
||||
switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
|
||||
case 0: _MOVE(s, d, size, type_u); break; \
|
||||
case sizeof(type_l): _MOVE(s, d, size, type_l); break; \
|
||||
case sizeof(type_w): _MOVE(s, d, size, type_w); break; \
|
||||
default: _MOVE(s, d, size, type_c); break; \
|
||||
}
|
||||
|
||||
// Device IO block data helpers
|
||||
#define _FWRMOVE(s, d, size, t) \
|
||||
{ t *s1=(t *)s, *d1=(t *)d; SET_CI; \
|
||||
while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } \
|
||||
CLR_CI; \
|
||||
}
|
||||
|
||||
#define _BWRMOVE(s, d, size, t) { \
|
||||
t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); SET_CI; \
|
||||
while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
|
||||
CLR_CI; \
|
||||
}
|
||||
|
||||
#define _RMOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWRMOVE(s, d, size, t) else _FWRMOVE(s, d, size, t)
|
||||
|
||||
#define _FASTRMOVE(s, d, size) \
|
||||
switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
|
||||
case 0: _RMOVE(s, d, size, type_u); break; \
|
||||
case sizeof(type_l): _RMOVE(s, d, size, type_l); break; \
|
||||
case sizeof(type_w): _RMOVE(s, d, size, type_w); break; \
|
||||
default: _RMOVE(s, d, size, type_c); break; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
: "r0", "r6", "r7", "r8", "r9", "r10", "r11", \
|
||||
"r12", "memory", "cr0", "cr1", "cr5", \
|
||||
"cr6", "cr7", "ctr", "xer"); \
|
||||
return arg0 ? -1 : arg1; \
|
||||
return arg0 ? (type)-1 : arg1; \
|
||||
} \
|
||||
static inline void ci_write_##size(type * addr, type data) \
|
||||
{ \
|
||||
|
@ -63,6 +63,65 @@ cache_inhibited_access(uint16_t, 16)
|
|||
cache_inhibited_access(uint32_t, 32)
|
||||
cache_inhibited_access(uint64_t, 64)
|
||||
|
||||
#define _FWOVERLAP(s, d, size) ((d >= s) && ((type_u)d < ((type_u)s + size)))
|
||||
|
||||
// 3.1
|
||||
#define _FWMOVE(s, d, size, t) \
|
||||
{ t *s1=(t *)s, *d1=(t *)d; \
|
||||
while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } }
|
||||
|
||||
#define _BWMOVE(s, d, size, t) { \
|
||||
t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); \
|
||||
while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
|
||||
}
|
||||
|
||||
|
||||
#define _MOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWMOVE(s, d, size, t) else _FWMOVE(s, d, size, t)
|
||||
|
||||
#define _FASTMOVE(s, d, size) \
|
||||
switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
|
||||
case 0: _MOVE(s, d, size, type_u); break; \
|
||||
case sizeof(type_l): _MOVE(s, d, size, type_l); break; \
|
||||
case sizeof(type_w): _MOVE(s, d, size, type_w); break; \
|
||||
default: _MOVE(s, d, size, type_c); break; \
|
||||
}
|
||||
|
||||
static inline void ci_rmove(void *dst, void *src, unsigned long esize,
|
||||
unsigned long count)
|
||||
{
|
||||
register uint64_t arg0 asm ("r3");
|
||||
register uint64_t arg1 asm ("r4");
|
||||
register uint64_t arg2 asm ("r5");
|
||||
register uint64_t arg3 asm ("r6");
|
||||
register uint64_t arg4 asm ("r7");
|
||||
register uint64_t arg5 asm ("r8");
|
||||
|
||||
arg0 = 0xf001; /* KVMPPC_H_LOGICAL_MEMOP */
|
||||
arg1 = (uint64_t)dst;
|
||||
arg2 = (uint64_t)src;
|
||||
arg3 = esize;
|
||||
arg4 = count;
|
||||
arg5 = 0; /* 0 = copy */
|
||||
|
||||
asm volatile(".long 0x44000022 \n" /* HVCALL */
|
||||
: "=&r"(arg0),"=&r"(arg1),"=&r"(arg2),
|
||||
"=&r"(arg3),"=&r"(arg4),"=&r"(arg5)
|
||||
: "0"(arg0),"1"(arg1),"2"(arg2),
|
||||
"3"(arg3),"4"(arg4),"5"(arg5)
|
||||
: "r0", "r9", "r10", "r11",
|
||||
"r12", "memory", "cr0", "cr1", "cr5",
|
||||
"cr6", "cr7", "ctr", "xer");
|
||||
}
|
||||
|
||||
#define _FASTRMOVE(s, d, size) do { \
|
||||
switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) {\
|
||||
case 0: ci_rmove(d,s,3,size>>3); break; \
|
||||
case sizeof(type_l): ci_rmove(d,s,2,size>>2); break; \
|
||||
case sizeof(type_w): ci_rmove(d,s,1,size>>1); break; \
|
||||
default: ci_rmove(d,s,0,size); break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static inline uint16_t bswap16_load(uint64_t addr)
|
||||
{
|
||||
unsigned int val;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <cache.h>
|
||||
|
||||
#include ISTR(TARG,h)
|
||||
|
||||
#define LAST_ELEMENT(x) x[sizeof x / sizeof x[0] - 1]
|
||||
|
@ -29,6 +31,7 @@
|
|||
/* Hack to get around static inline issues */
|
||||
#include "../lib/libhvcall/libhvcall.h"
|
||||
|
||||
|
||||
extern char _start_OF[];
|
||||
|
||||
unsigned long fdt_start;
|
||||
|
|
|
@ -445,30 +445,6 @@ code_EXECUTE: // don't need this as prim
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 3.1
|
||||
#define _FWMOVE(s, d, size, t) \
|
||||
{ t *s1=(t *)s, *d1=(t *)d; \
|
||||
while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } }
|
||||
|
||||
#define _BWMOVE(s, d, size, t) { \
|
||||
t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); \
|
||||
while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
|
||||
}
|
||||
|
||||
#define _FWOVERLAP(s, d, size) ((d >= s) && ((type_u)d < ((type_u)s + size)))
|
||||
|
||||
#define _MOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWMOVE(s, d, size, t) else _FWMOVE(s, d, size, t)
|
||||
|
||||
#define _FASTMOVE(s, d, size) \
|
||||
switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
|
||||
case 0: _MOVE(s, d, size, type_u); break; \
|
||||
case sizeof(type_l): _MOVE(s, d, size, type_l); break; \
|
||||
case sizeof(type_w): _MOVE(s, d, size, type_w); break; \
|
||||
default: _MOVE(s, d, size, type_c); break; \
|
||||
}
|
||||
|
||||
PRIM(MOVE)
|
||||
type_u n = TOS.u; POP;
|
||||
unsigned char *q = TOS.a; POP;
|
||||
|
@ -535,38 +511,14 @@ code_COMP:
|
|||
NEXT;
|
||||
}
|
||||
|
||||
// Device IO block data helpers
|
||||
#define _FWRMOVE(s, d, size, t) \
|
||||
{ t *s1=(t *)s, *d1=(t *)d; SET_CI; \
|
||||
while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } \
|
||||
CLR_CI; \
|
||||
}
|
||||
|
||||
#define _BWRMOVE(s, d, size, t) { \
|
||||
t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); SET_CI; \
|
||||
while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
|
||||
CLR_CI; \
|
||||
}
|
||||
PRIM(RMOVE)
|
||||
type_u size = ((dp--)->u);
|
||||
type_u *d = (type_u *)((dp--)->u);
|
||||
type_u *s = (type_u *)((dp--)->u);
|
||||
_FASTRMOVE(s, d, size);
|
||||
|
||||
#define _RMOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWRMOVE(s, d, size, t) else _FWRMOVE(s, d, size, t)
|
||||
|
||||
#define _FASTRMOVE(s, d, size) \
|
||||
switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
|
||||
case 0: _RMOVE(s, d, size, type_u); break; \
|
||||
case sizeof(type_l): _RMOVE(s, d, size, type_l); break; \
|
||||
case sizeof(type_w): _RMOVE(s, d, size, type_w); break; \
|
||||
default: _RMOVE(s, d, size, type_c); break; \
|
||||
}
|
||||
|
||||
code_RMOVE:
|
||||
{
|
||||
type_u size = ((dp--)->u);
|
||||
type_u *d = (type_u *)((dp--)->u);
|
||||
type_u *s = (type_u *)((dp--)->u);
|
||||
|
||||
_FASTRMOVE(s, d, size);
|
||||
NEXT;
|
||||
}
|
||||
MIRP
|
||||
|
||||
|
||||
// String compare, case insensitive:
|
||||
|
|
Loading…
Reference in New Issue