Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / include / ppcp7 / cache.h
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #ifndef __CACHE_H
14 #define __CACHE_H
15
16 #include <cpu.h>
17 #include <stdint.h>
18
19 // XXX FIXME: Use proper CI load/store */
20 #define cache_inhibited_access(type,size)                               \
21         static inline type ci_read_##size(type * addr)                  \
22         {                                                               \
23                 register uint64_t arg0 asm ("r3");                      \
24                 register uint64_t arg1 asm ("r4");                      \
25                 register uint64_t arg2 asm ("r5");                      \
26                                                                         \
27                 arg0 = 0x3c; /* H_LOGICAL_CI_LOAD*/                     \
28                 arg1 = size / 8;                                        \
29                 arg2 = (uint64_t)addr;                                  \
30                                                                         \
31                 asm volatile(                                           \
32                         ".long  0x44000022 \n"  /* HVCALL */            \
33                         : "=&r" (arg0), "=&r"(arg1), "=&r"(arg2)        \
34                         : "0"(arg0), "1"(arg1), "2"(arg2)               \
35                         : "r0", "r6", "r7", "r8", "r9", "r10", "r11",   \
36                           "r12", "memory", "cr0", "cr1", "cr5",         \
37                           "cr6", "cr7", "ctr", "xer");                  \
38                 return arg0 ? (type)-1 : arg1;                          \
39         }                                                               \
40         static inline void ci_write_##size(type * addr, type data)      \
41         {                                                               \
42                 register uint64_t arg0 asm ("r3");                      \
43                 register uint64_t arg1 asm ("r4");                      \
44                 register uint64_t arg2 asm ("r5");                      \
45                 register uint64_t arg3 asm ("r6");                      \
46                                                                         \
47                 arg0 = 0x40; /* H_LOGICAL_CI_STORE*/                    \
48                 arg1 = size / 8;                                        \
49                 arg2 = (uint64_t)addr;                                  \
50                 arg3 = (uint64_t)data;                                  \
51                                                                         \
52                 asm volatile(                                           \
53                         ".long  0x44000022 \n"  /* HVCALL */            \
54                         : "=&r"(arg0),"=&r"(arg1),"=&r"(arg2),"=&r"(arg3) \
55                         : "0"(arg0),"1"(arg1),"2"(arg2),"3"(arg3)       \
56                         : "r0", "r7", "r8", "r9", "r10", "r11",         \
57                           "r12", "memory", "cr0", "cr1", "cr5",         \
58                           "cr6", "cr7", "ctr", "xer");                  \
59         }
60
61 cache_inhibited_access(uint8_t,  8)
62 cache_inhibited_access(uint16_t, 16)
63 cache_inhibited_access(uint32_t, 32)
64 cache_inhibited_access(uint64_t, 64)
65
66 #define _FWOVERLAP(s, d, size) ((d >= s) && ((type_u)d < ((type_u)s + size)))
67
68 // 3.1
69 #define _FWMOVE(s, d, size, t)  \
70         { t *s1=(t *)s, *d1=(t *)d; \
71                 while (size > 0) { *d1++ = *s1++; size -= sizeof(t); } }
72
73 #define _BWMOVE(s, d, size, t)  { \
74         t *s1=(t *)((char *)s+size), *d1=(t *)((char *)d+size); \
75         while (size > 0) { *--d1 = *--s1; size -= sizeof(t); } \
76 }
77
78
79 #define _MOVE(s, d, size, t) if _FWOVERLAP(s, d, size) _BWMOVE(s, d, size, t) else  _FWMOVE(s, d, size, t)
80
81 #define _FASTMOVE(s, d, size) \
82         switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) { \
83         case 0:                 _MOVE(s, d, size, type_u); break;       \
84         case sizeof(type_l):    _MOVE(s, d, size, type_l); break;       \
85         case sizeof(type_w):    _MOVE(s, d, size, type_w); break;       \
86         default:                _MOVE(s, d, size, type_c); break;       \
87         }
88
89 static inline void ci_rmove(void *dst, void *src, unsigned long esize,
90                             unsigned long count)
91 {
92         register uint64_t arg0 asm ("r3");
93         register uint64_t arg1 asm ("r4");
94         register uint64_t arg2 asm ("r5");
95         register uint64_t arg3 asm ("r6");
96         register uint64_t arg4 asm ("r7");
97         register uint64_t arg5 asm ("r8");
98
99         arg0 = 0xf001; /* KVMPPC_H_LOGICAL_MEMOP */
100         arg1 = (uint64_t)dst;
101         arg2 = (uint64_t)src;
102         arg3 = esize;
103         arg4 = count;
104         arg5 = 0; /* 0 = copy */
105
106         asm volatile(".long     0x44000022 \n"  /* HVCALL */
107                      : "=&r"(arg0),"=&r"(arg1),"=&r"(arg2),
108                        "=&r"(arg3),"=&r"(arg4),"=&r"(arg5)
109                      : "0"(arg0),"1"(arg1),"2"(arg2),
110                        "3"(arg3),"4"(arg4),"5"(arg5)
111                      : "r0", "r9", "r10", "r11",
112                        "r12", "memory", "cr0", "cr1", "cr5",
113                        "cr6", "cr7", "ctr", "xer");
114 }
115
116 #define _FASTRMOVE(s, d, size) do {                                           \
117                 switch (((type_u)s | (type_u)d | size) & (sizeof(type_u)-1)) {\
118                 case 0:                 ci_rmove(d,s,3,size>>3); break;       \
119                 case sizeof(type_l):    ci_rmove(d,s,2,size>>2); break;       \
120                 case sizeof(type_w):    ci_rmove(d,s,1,size>>1); break;       \
121                 default:                ci_rmove(d,s,0,size); break;          \
122                 }                                                             \
123         } while(0)
124
125 static inline uint16_t bswap16_load(uint64_t addr)
126 {
127         unsigned int val;
128         asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
129         return val;
130 }
131
132 static inline uint32_t bswap32_load(uint64_t addr)
133 {
134         unsigned int val;
135         asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
136         return val;
137 }
138
139 static inline void bswap16_store(uint64_t addr, uint16_t val)
140 {
141         asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
142 }
143
144 static inline void bswap32_store(uint64_t addr, uint32_t val)
145 {
146         asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
147 }
148
149 #endif /* __CACHE_H */
150