]> git.proxmox.com Git - qemu.git/blame - target-ppc/mem_helper.c
rng-egd: remove redundant free
[qemu.git] / target-ppc / mem_helper.c
CommitLineData
9a64fbe4 1/*
2f5a189c 2 * PowerPC memory access emulation helpers for QEMU.
5fafdf24 3 *
76a66253 4 * Copyright (c) 2003-2007 Jocelyn Mayer
9a64fbe4
FB
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
9a64fbe4 18 */
3e457172 19#include "cpu.h"
1de7afc9 20#include "qemu/host-utils.h"
a7812ae4 21#include "helper.h"
9a64fbe4 22
0411a972 23#include "helper_regs.h"
0487d6a8 24
3e457172 25#if !defined(CONFIG_USER_ONLY)
022c62cb 26#include "exec/softmmu_exec.h"
3e457172
BS
27#endif /* !defined(CONFIG_USER_ONLY) */
28
fdabc366 29//#define DEBUG_OP
d12d51d5 30
ff4a62cd
AJ
31/*****************************************************************************/
32/* Memory load and stores */
33
2f5a189c
BS
34static inline target_ulong addr_add(CPUPPCState *env, target_ulong addr,
35 target_long arg)
ff4a62cd
AJ
36{
37#if defined(TARGET_PPC64)
e42a61f1 38 if (!msr_is_64bit(env, env->msr)) {
b327c654
BS
39 return (uint32_t)(addr + arg);
40 } else
ff4a62cd 41#endif
b327c654
BS
42 {
43 return addr + arg;
44 }
ff4a62cd
AJ
45}
46
2f5a189c 47void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
ff4a62cd 48{
76db3ba4 49 for (; reg < 32; reg++) {
b327c654 50 if (msr_le) {
2f5a189c 51 env->gpr[reg] = bswap32(cpu_ldl_data(env, addr));
b327c654 52 } else {
2f5a189c 53 env->gpr[reg] = cpu_ldl_data(env, addr);
b327c654 54 }
2f5a189c 55 addr = addr_add(env, addr, 4);
ff4a62cd
AJ
56 }
57}
58
2f5a189c 59void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
ff4a62cd 60{
76db3ba4 61 for (; reg < 32; reg++) {
b327c654 62 if (msr_le) {
2f5a189c 63 cpu_stl_data(env, addr, bswap32((uint32_t)env->gpr[reg]));
b327c654 64 } else {
2f5a189c 65 cpu_stl_data(env, addr, (uint32_t)env->gpr[reg]);
b327c654 66 }
2f5a189c 67 addr = addr_add(env, addr, 4);
ff4a62cd
AJ
68 }
69}
70
2f5a189c 71void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
dfbc799d
AJ
72{
73 int sh;
b327c654 74
76db3ba4 75 for (; nb > 3; nb -= 4) {
2f5a189c 76 env->gpr[reg] = cpu_ldl_data(env, addr);
dfbc799d 77 reg = (reg + 1) % 32;
2f5a189c 78 addr = addr_add(env, addr, 4);
dfbc799d
AJ
79 }
80 if (unlikely(nb > 0)) {
81 env->gpr[reg] = 0;
76db3ba4 82 for (sh = 24; nb > 0; nb--, sh -= 8) {
2f5a189c
BS
83 env->gpr[reg] |= cpu_ldub_data(env, addr) << sh;
84 addr = addr_add(env, addr, 1);
dfbc799d
AJ
85 }
86 }
87}
88/* PPC32 specification says we must generate an exception if
89 * rA is in the range of registers to be loaded.
90 * In an other hand, IBM says this is valid, but rA won't be loaded.
91 * For now, I'll follow the spec...
92 */
2f5a189c
BS
93void helper_lswx(CPUPPCState *env, target_ulong addr, uint32_t reg,
94 uint32_t ra, uint32_t rb)
dfbc799d
AJ
95{
96 if (likely(xer_bc != 0)) {
97 if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
98 (reg < rb && (reg + xer_bc) > rb))) {
e5f17ac6 99 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
e06fcd75
AJ
100 POWERPC_EXCP_INVAL |
101 POWERPC_EXCP_INVAL_LSWX);
dfbc799d 102 } else {
2f5a189c 103 helper_lsw(env, addr, xer_bc, reg);
dfbc799d
AJ
104 }
105 }
106}
107
2f5a189c
BS
108void helper_stsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
109 uint32_t reg)
dfbc799d
AJ
110{
111 int sh;
b327c654 112
76db3ba4 113 for (; nb > 3; nb -= 4) {
2f5a189c 114 cpu_stl_data(env, addr, env->gpr[reg]);
dfbc799d 115 reg = (reg + 1) % 32;
2f5a189c 116 addr = addr_add(env, addr, 4);
dfbc799d
AJ
117 }
118 if (unlikely(nb > 0)) {
a16b45e7 119 for (sh = 24; nb > 0; nb--, sh -= 8) {
2f5a189c
BS
120 cpu_stb_data(env, addr, (env->gpr[reg] >> sh) & 0xFF);
121 addr = addr_add(env, addr, 1);
a16b45e7 122 }
dfbc799d
AJ
123 }
124}
125
2f5a189c 126static void do_dcbz(CPUPPCState *env, target_ulong addr, int dcache_line_size)
799a8c8d 127{
799a8c8d 128 int i;
b327c654
BS
129
130 addr &= ~(dcache_line_size - 1);
131 for (i = 0; i < dcache_line_size; i += 4) {
2f5a189c 132 cpu_stl_data(env, addr + i, 0);
799a8c8d 133 }
b327c654 134 if (env->reserve_addr == addr) {
18b21a2f 135 env->reserve_addr = (target_ulong)-1ULL;
b327c654 136 }
799a8c8d
AJ
137}
138
8e33944f 139void helper_dcbz(CPUPPCState *env, target_ulong addr, uint32_t is_dcbzl)
799a8c8d 140{
8e33944f 141 int dcbz_size = env->dcache_line_size;
799a8c8d 142
414f5d14 143#if defined(TARGET_PPC64)
8e33944f
AG
144 if (!is_dcbzl &&
145 (env->excp_model == POWERPC_EXCP_970) &&
146 ((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
147 dcbz_size = 32;
b327c654 148 }
8e33944f
AG
149#endif
150
151 /* XXX add e500mc support */
152
153 do_dcbz(env, addr, dcbz_size);
799a8c8d
AJ
154}
155
2f5a189c 156void helper_icbi(CPUPPCState *env, target_ulong addr)
37d269df 157{
76db3ba4 158 addr &= ~(env->dcache_line_size - 1);
37d269df
AJ
159 /* Invalidate one cache line :
160 * PowerPC specification says this is to be treated like a load
161 * (not a fetch) by the MMU. To be sure it will be so,
162 * do the load "by hand".
163 */
2f5a189c 164 cpu_ldl_data(env, addr);
37d269df
AJ
165}
166
b327c654 167/* XXX: to be tested */
2f5a189c
BS
168target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
169 uint32_t ra, uint32_t rb)
bdb4b689
AJ
170{
171 int i, c, d;
b327c654 172
bdb4b689
AJ
173 d = 24;
174 for (i = 0; i < xer_bc; i++) {
2f5a189c
BS
175 c = cpu_ldub_data(env, addr);
176 addr = addr_add(env, addr, 1);
bdb4b689
AJ
177 /* ra (if not 0) and rb are never modified */
178 if (likely(reg != rb && (ra == 0 || reg != ra))) {
179 env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
180 }
b327c654 181 if (unlikely(c == xer_cmp)) {
bdb4b689 182 break;
b327c654 183 }
bdb4b689
AJ
184 if (likely(d != 0)) {
185 d -= 8;
186 } else {
187 d = 24;
188 reg++;
189 reg = reg & 0x1F;
190 }
191 }
192 return i;
193}
194
d6a46fe8
AJ
195/*****************************************************************************/
196/* Altivec extension helpers */
e2542fe2 197#if defined(HOST_WORDS_BIGENDIAN)
d6a46fe8
AJ
198#define HI_IDX 0
199#define LO_IDX 1
200#else
201#define HI_IDX 1
202#define LO_IDX 0
203#endif
204
cbfb6ae9 205#define LVE(name, access, swap, element) \
2f5a189c
BS
206 void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
207 target_ulong addr) \
cbfb6ae9
AJ
208 { \
209 size_t n_elems = ARRAY_SIZE(r->element); \
b327c654 210 int adjust = HI_IDX*(n_elems - 1); \
cbfb6ae9
AJ
211 int sh = sizeof(r->element[0]) >> 1; \
212 int index = (addr & 0xf) >> sh; \
b327c654
BS
213 \
214 if (msr_le) { \
bbfb6f13 215 index = n_elems - index - 1; \
b327c654 216 r->element[LO_IDX ? index : (adjust - index)] = \
2f5a189c 217 swap(access(env, addr)); \
b327c654
BS
218 } else { \
219 r->element[LO_IDX ? index : (adjust - index)] = \
2f5a189c 220 access(env, addr); \
b327c654 221 } \
cbfb6ae9
AJ
222 }
223#define I(x) (x)
2f5a189c
BS
224LVE(lvebx, cpu_ldub_data, I, u8)
225LVE(lvehx, cpu_lduw_data, bswap16, u16)
226LVE(lvewx, cpu_ldl_data, bswap32, u32)
cbfb6ae9
AJ
227#undef I
228#undef LVE
229
b327c654 230#define STVE(name, access, swap, element) \
2f5a189c
BS
231 void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
232 target_ulong addr) \
b327c654
BS
233 { \
234 size_t n_elems = ARRAY_SIZE(r->element); \
235 int adjust = HI_IDX * (n_elems - 1); \
236 int sh = sizeof(r->element[0]) >> 1; \
237 int index = (addr & 0xf) >> sh; \
238 \
239 if (msr_le) { \
bbfb6f13 240 index = n_elems - index - 1; \
2f5a189c
BS
241 access(env, addr, swap(r->element[LO_IDX ? index : \
242 (adjust - index)])); \
cbfb6ae9 243 } else { \
2f5a189c
BS
244 access(env, addr, r->element[LO_IDX ? index : \
245 (adjust - index)]); \
cbfb6ae9
AJ
246 } \
247 }
248#define I(x) (x)
2f5a189c
BS
249STVE(stvebx, cpu_stb_data, I, u8)
250STVE(stvehx, cpu_stw_data, bswap16, u16)
251STVE(stvewx, cpu_stl_data, bswap32, u32)
cbfb6ae9
AJ
252#undef I
253#undef LVE
254
d6a46fe8
AJ
255#undef HI_IDX
256#undef LO_IDX