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:
Benjamin Herrenschmidt 2012-02-22 10:33:18 +11:00
parent 0dfcbc1336
commit 7add7a0a9f
4 changed files with 115 additions and 55 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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: