cpu_ppc_instr_loadstore.cc Source File

Back to the index.

cpu_ppc_instr_loadstore.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * POWER/PowerPC load/store instructions.
29  *
30  *
31  * Load/store instructions have the following arguments:
32  *
33  * arg[0] = pointer to the register to load to or store from
34  * arg[1] = pointer to the base register
35  *
36  * arg[2] = offset (as an int32_t)
37  * (or, for Indexed load/stores: pointer to index register)
38  */
39 
40 
41 #ifndef LS_IGNOREOFS
42 void LS_GENERIC_N(struct cpu *cpu, struct ppc_instr_call *ic)
43 {
44 #ifdef MODE32
45  uint32_t addr =
46 #else
47  uint64_t addr =
48 #endif
49  reg(ic->arg[1]) +
50 #ifdef LS_INDEXED
51  reg(ic->arg[2]);
52 #else
53  (int32_t)ic->arg[2];
54 #endif
55  unsigned char data[LS_SIZE];
56 
57  /* Synchronize the PC: */
58  int low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
59  / sizeof(struct ppc_instr_call);
61  cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
62 
63 #ifndef LS_B
64  if ((addr & 0xfff) + LS_SIZE-1 > 0xfff) {
65  fatal("PPC LOAD/STORE misalignment across page boundary: TODO"
66  " (addr=0x%08x, LS_SIZE=%i)\n", (int)addr, LS_SIZE);
67  exit(1);
68  }
69 #endif
70 
71 #ifdef LS_LOAD
72  if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
73  MEM_READ, CACHE_DATA)) {
74  /* Exception. */
75  return;
76  }
77 #ifdef LS_B
78  reg(ic->arg[0]) =
79 #ifndef LS_ZERO
80  (int8_t)
81 #endif
82  data[0];
83 #endif
84 #ifdef LS_H
85  reg(ic->arg[0]) =
86 #ifdef LS_BYTEREVERSE
87  ((data[1] << 8) + data[0]);
88 #else
89 #ifndef LS_ZERO
90  (int16_t)
91 #endif
92  ((data[0] << 8) + data[1]);
93 #endif /* !BYTEREVERSE */
94 #endif
95 #ifdef LS_W
96  reg(ic->arg[0]) =
97 #ifdef LS_BYTEREVERSE
98  ((data[3] << 24) + (data[2] << 16) +
99  (data[1] << 8) + data[0]);
100 #else /* !LS_BYTEREVERSE */
101 #ifndef LS_ZERO
102  (int32_t)
103 #else
104  (uint32_t)
105 #endif
106  ((data[0] << 24) + (data[1] << 16) +
107  (data[2] << 8) + data[3]);
108 #endif /* !LS_BYTEREVERSE */
109 #endif
110 #ifdef LS_D
111  (*(uint64_t *)(ic->arg[0])) =
112  ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) +
113  ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) +
114  ((uint64_t)data[4] << 24) + (data[5] << 16) +
115  (data[6] << 8) + data[7];
116 #endif
117 
118 #else /* store: */
119 
120 #ifdef LS_B
121  data[0] = reg(ic->arg[0]);
122 #endif
123 #ifdef LS_H
124 #ifdef LS_BYTEREVERSE
125  data[0] = reg(ic->arg[0]);
126  data[1] = reg(ic->arg[0]) >> 8;
127 #else
128  data[0] = reg(ic->arg[0]) >> 8;
129  data[1] = reg(ic->arg[0]);
130 #endif
131 #endif
132 #ifdef LS_W
133 #ifdef LS_BYTEREVERSE
134  data[0] = reg(ic->arg[0]);
135  data[1] = reg(ic->arg[0]) >> 8;
136  data[2] = reg(ic->arg[0]) >> 16;
137  data[3] = reg(ic->arg[0]) >> 24;
138 #else
139  data[0] = reg(ic->arg[0]) >> 24;
140  data[1] = reg(ic->arg[0]) >> 16;
141  data[2] = reg(ic->arg[0]) >> 8;
142  data[3] = reg(ic->arg[0]);
143 #endif /* !LS_BYTEREVERSE */
144 #endif
145 #ifdef LS_D
146  { uint64_t x = *(uint64_t *)(ic->arg[0]);
147  data[0] = x >> 56;
148  data[1] = x >> 48;
149  data[2] = x >> 40;
150  data[3] = x >> 32;
151  data[4] = x >> 24;
152  data[5] = x >> 16;
153  data[6] = x >> 8;
154  data[7] = x; }
155 #endif
156  if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
157  MEM_WRITE, CACHE_DATA)) {
158  /* Exception. */
159  return;
160  }
161 #endif
162 
163 #ifdef LS_UPDATE
164  reg(ic->arg[1]) = addr;
165 #endif
166 }
167 #endif
168 
169 
170 void LS_N(struct cpu *cpu, struct ppc_instr_call *ic)
171 {
172 #ifndef MODE32
173  /************************************************************/
174  /* For now, 64-bit access is done using the slow fallback. */
175  if (!cpu->is_32bit) {
176  LS_GENERIC_N(cpu, ic);
177  return;
178  }
179 #endif
180 
181 
182 #ifdef MODE32
183  uint32_t addr =
184 #else
185  uint64_t addr =
186 #endif
187  reg(ic->arg[1])
188 #ifdef LS_INDEXED
189  + reg(ic->arg[2])
190 #else
191 #ifndef LS_IGNOREOFS
192  + (int32_t)ic->arg[2]
193 #endif
194 #endif
195  ;
196 
197  unsigned char *page = cpu->cd.ppc.
198 #ifdef LS_LOAD
199  host_load
200 #else
201  host_store
202 #endif
203  [addr >> 12];
204 #ifdef LS_UPDATE
205  uint32_t new_addr = addr;
206 #endif
207 
208 #ifndef LS_B
209  if (addr & (LS_SIZE-1)) {
210  LS_GENERIC_N(cpu, ic);
211  return;
212  }
213 #endif
214 
215  if (page == NULL) {
216  LS_GENERIC_N(cpu, ic);
217  return;
218  } else {
219  addr &= 4095;
220 #ifdef LS_LOAD
221  /* Load: */
222 #ifdef LS_B
223  reg(ic->arg[0]) =
224 #ifndef LS_ZERO
225  (int8_t)
226 #endif
227  page[addr];
228 #endif /* LS_B */
229 #ifdef LS_H
230  reg(ic->arg[0]) =
231 #ifdef LS_BYTEREVERSE
232  ((page[addr+1] << 8) + page[addr]);
233 #else
234 #ifndef LS_ZERO
235  (int16_t)
236 #endif
237  ((page[addr] << 8) + page[addr+1]);
238 #endif /* !BYTEREVERSE */
239 #endif /* LS_H */
240 #ifdef LS_W
241  reg(ic->arg[0]) =
242 #ifdef LS_BYTEREVERSE
243  ((page[addr+3] << 24) + (page[addr+2] << 16) +
244  (page[addr+1] << 8) + page[addr]);
245 #else /* !LS_BYTEREVERSE */
246 #ifndef LS_ZERO
247  (int32_t)
248 #else
249  (uint32_t)
250 #endif
251  ((page[addr] << 24) + (page[addr+1] << 16) +
252  (page[addr+2] << 8) + page[addr+3]);
253 #endif /* !LS_BYTEREVERSE */
254 #endif /* LS_W */
255 #ifdef LS_D
256  (*(uint64_t *)(ic->arg[0])) =
257  ((uint64_t)page[addr+0] << 56) +
258  ((uint64_t)page[addr+1] << 48) +
259  ((uint64_t)page[addr+2] << 40) +
260  ((uint64_t)page[addr+3] << 32) +
261  ((uint64_t)page[addr+4] << 24) + (page[addr+5] << 16) +
262  (page[addr+6] << 8) + page[addr+7];
263 #endif /* LS_D */
264 
265 #else /* !LS_LOAD */
266 
267  /* Store: */
268 #ifdef LS_B
269  page[addr] = reg(ic->arg[0]);
270 #endif
271 #ifdef LS_H
272 #ifdef LS_BYTEREVERSE
273  page[addr] = reg(ic->arg[0]);
274  page[addr+1] = reg(ic->arg[0]) >> 8;
275 #else
276  page[addr] = reg(ic->arg[0]) >> 8;
277  page[addr+1] = reg(ic->arg[0]);
278 #endif /* !BYTEREVERSE */
279 #endif
280 #ifdef LS_W
281 #ifdef LS_BYTEREVERSE
282  page[addr] = reg(ic->arg[0]);
283  page[addr+1] = reg(ic->arg[0]) >> 8;
284  page[addr+2] = reg(ic->arg[0]) >> 16;
285  page[addr+3] = reg(ic->arg[0]) >> 24;
286 #else
287  page[addr] = reg(ic->arg[0]) >> 24;
288  page[addr+1] = reg(ic->arg[0]) >> 16;
289  page[addr+2] = reg(ic->arg[0]) >> 8;
290  page[addr+3] = reg(ic->arg[0]);
291 #endif /* !LS_BYTEREVERSE */
292 #endif
293 #ifdef LS_D
294  { uint64_t x = *(uint64_t *)(ic->arg[0]);
295  page[addr] = x >> 56;
296  page[addr+1] = x >> 48;
297  page[addr+2] = x >> 40;
298  page[addr+3] = x >> 32;
299  page[addr+4] = x >> 24;
300  page[addr+5] = x >> 16;
301  page[addr+6] = x >> 8;
302  page[addr+7] = x; }
303 #endif
304 #endif /* !LS_LOAD */
305  }
306 
307 #ifdef LS_UPDATE
308  reg(ic->arg[1]) = new_addr;
309 #endif
310 }
311 
data
u_short data
Definition: siireg.h:79
LS_N
void LS_N(struct cpu *cpu, struct ppc_instr_call *ic)
Definition: cpu_ppc_instr_loadstore.cc:170
if
addr & if(addr >=0x24 &&page !=NULL)
Definition: tmp_arm_multi.cc:56
MEM_READ
#define MEM_READ
Definition: memory.h:116
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
LS_GENERIC_N
void LS_GENERIC_N(struct cpu *cpu, struct ppc_instr_call *ic)
Definition: cpu_ppc_instr_loadstore.cc:42
LS_LOAD
#define LS_LOAD
Definition: tmp_alpha_misc.cc:1154
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
cpu::cd
union cpu::@1 cd
page
page
Definition: tmp_arm_multi.cc:54
ic
struct arm_instr_call * ic
Definition: tmp_arm_multi.cc:50
LS_UPDATE
#define LS_UPDATE
Definition: tmp_ppc_loadstore.cc:879
CACHE_DATA
#define CACHE_DATA
Definition: memory.h:121
cpu::is_32bit
uint8_t is_32bit
Definition: cpu.h:350
LS_B
#define LS_B
Definition: tmp_alpha_misc.cc:1016
cpu::ppc
struct ppc_cpu ppc
Definition: cpu.h:447
cpu::mem
struct memory * mem
Definition: cpu.h:362
reg
#define reg(x)
Definition: tmp_alpha_tail.cc:53
PPC_IC_ENTRIES_PER_PAGE
#define PPC_IC_ENTRIES_PER_PAGE
Definition: cpu_ppc.h:95
LS_SIZE
#define LS_SIZE
Definition: tmp_m88k_loadstore.cc:1754
cpu
Definition: cpu.h:326
PPC_INSTR_ALIGNMENT_SHIFT
#define PPC_INSTR_ALIGNMENT_SHIFT
Definition: cpu_ppc.h:93
cpu::memory_rw
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:368
cpu::pc
uint64_t pc
Definition: cpu.h:386

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18