cpu_m88k_instr_loadstore.cc Source File

Back to the index.

cpu_m88k_instr_loadstore.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-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  * M88K load/store instructions; the following args are used:
29  *
30  * arg[0] = pointer to the register to load to or store from (d)
31  * arg[1] = pointer to the base register (s1)
32  * arg[2] = pointer to the offset register (s2), or an uint32_t offset
33  *
34  * The GENERIC function always checks for alignment, and supports both big
35  * and little endian byte order.
36  *
37  * The quick function is included twice (big/little endian) for each
38  * GENERIC function.
39  *
40  *
41  * Defines:
42  * LS_LOAD or LS_STORE (only one)
43  * LS_INCLUDE_GENERIC (to generate the generic function)
44  * LS_GENERIC_N is defined as the name of the generic function
45  * LS_N is defined as the name of the fast function
46  * LS_1, LS_2, LS_4, or LS_8 (only one)
47  * LS_SIZE is defined to 1, 2, 4, or 8
48  * LS_SIGNED is defined for signed loads
49  * LS_LE or LS_BE (only one)
50  * LS_SCALED for scaled accesses
51  * LS_USR for usr accesses
52  * LS_REGOFS is defined when arg[2] is a register pointer
53  */
54 
55 
56 #ifdef LS_INCLUDE_GENERIC
57 void LS_GENERIC_N(struct cpu *cpu, struct m88k_instr_call *ic)
58 {
59 #ifdef LS_USR
60  const int memory_rw_flags = CACHE_DATA | MEMORY_USER_ACCESS;
61 #else
62  const int memory_rw_flags = CACHE_DATA;
63 #endif
64  uint32_t addr = reg(ic->arg[1]) +
65 #ifdef LS_REGOFS
66 #ifdef LS_SCALED
67  LS_SIZE *
68 #endif
69  reg(ic->arg[2]);
70 #else
71  ic->arg[2];
72 #endif
73  uint8_t data[LS_SIZE];
74  uint64_t x;
75 
76  /* Synchronize the PC: */
77  int low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page)
78  / sizeof(struct m88k_instr_call);
80  cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT);
81 
82  /*
83  * Update the memory transaction registers:
84  */
85  cpu->cd.m88k.dmt[1] = 0;
86 
87  cpu->cd.m88k.dmt[0] = DMT_VALID;
88 #ifdef LS_STORE
89  cpu->cd.m88k.dmt[0] |= DMT_WRITE;
90 #else
91  {
92  int dreg = (((uint32_t *)ic->arg[0]) - &cpu->cd.m88k.r[0]);
93  if (dreg < 1 || dreg > 31) {
94  fatal("HUH? dreg = %i in cpu_m88k_instr_loadstore.c."
95  " Internal error.\n", dreg);
96  exit(1);
97  }
98  cpu->cd.m88k.dmt[0] |= dreg << DMT_DREGSHIFT;
99  }
100 #ifdef LS_SIGNED
101  cpu->cd.m88k.dmt[0] |= DMT_SIGNED;
102 #endif
103 #endif
105  cpu->cd.m88k.dmt[0] |= DMT_BO;
106 
107 #ifndef LS_USR
109  cpu->cd.m88k.dmt[0] |= DMT_DAS; /* supervisor */
110 #endif
111 
112  /* EN bits: */
113 #ifdef LS_1
114  /* TODO: Is the EN offset only valid for Big-Endian? */
115  cpu->cd.m88k.dmt[0] |= 1 << DMT_ENSHIFT << (3 - (addr & 3));
116 #else
117 #ifdef LS_2
118  cpu->cd.m88k.dmt[0] |= 3 << DMT_ENSHIFT << (2 - (addr & 2));
119 #else
120  cpu->cd.m88k.dmt[0] |= 0xf << DMT_ENSHIFT;
121 #endif
122 #endif
123 
124  cpu->cd.m88k.dma[0] = addr & ~0x3;
125  cpu->cd.m88k.dmd[0] = 0;
126 
127 #ifdef LS_8
128  cpu->cd.m88k.dmt[1] = cpu->cd.m88k.dmt[0];
129  cpu->cd.m88k.dmt[0] |= DMT_DOUB1;
130  cpu->cd.m88k.dma[1] = cpu->cd.m88k.dma[0] + sizeof(uint32_t);
131  cpu->cd.m88k.dmd[1] = 0;
132 #ifdef LS_LOAD
133  {
134  int dreg = (((uint32_t *)ic->arg[0]) - &cpu->cd.m88k.r[0]);
135  dreg ++;
136  if (dreg < 1 || dreg > 31) {
137  fatal("HUH? dreg = %i in cpu_m88k_instr_loadstore.c."
138  " Internal error.\n", dreg);
139  exit(1);
140  }
141  cpu->cd.m88k.dmt[1] &= ~((0x1f) << DMT_DREGSHIFT);
142  cpu->cd.m88k.dmt[1] |= dreg << DMT_DREGSHIFT;
143  }
144 #endif
145 #endif
146 
147 
148 #ifdef LS_USR
149  if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)) {
150  /* Cause a privilege violation exception: */
152  return;
153  }
154 #endif
155 
156 #ifndef LS_1
157  /* Check alignment: */
158  if (addr & (LS_SIZE - 1)) {
159 #if 0
160  /* Cause an address alignment exception: */
162 #else
163  fatal("{ m88k dyntrans alignment exception, size = %i,"
164  " addr = %08" PRIx32", pc = %08" PRIx32" }\n", LS_SIZE,
165  (uint32_t) addr, (uint32_t) cpu->pc);
166 
167  /* TODO: Generalize this into a abort_call, or similar: */
168  cpu->running = 0;
170  cpu->cd.m88k.next_ic = &nothing_call;
171 
172  if (cpu->delay_slot)
174 #endif
175  return;
176  }
177 #endif
178 
179 #ifdef LS_LOAD
180  if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
181  MEM_READ, memory_rw_flags)) {
182  /* Exception. */
183  return;
184  }
186 #ifdef LS_8
187  if (cpu->byte_order == EMUL_BIG_ENDIAN) {
188  reg(ic->arg[0]) = x >> 32;
189  reg(ic->arg[0] + 4) = x;
190  } else {
191  reg(ic->arg[0]) = x;
192  reg(ic->arg[0] + 4) = x >> 32;
193  }
194 #else
195 #ifdef LS_SIGNED
196 #ifdef LS_1
197  x = (int8_t)x;
198 #endif
199 #ifdef LS_2
200  x = (int16_t)x;
201 #endif
202 #ifdef LS_4
203  x = (int32_t)x;
204 #endif
205 #endif
206  reg(ic->arg[0]) = x;
207 #endif
208 
209 #else /* LS_STORE: */
210 
211 #ifdef LS_8
213  x = ((uint64_t)reg(ic->arg[0]) << 32) + reg(ic->arg[0] + 4);
214  else
215  x = ((uint64_t)reg(ic->arg[0] + 4) << 32) + reg(ic->arg[0]);
216  cpu->cd.m88k.dmd[0] = reg(ic->arg[0]);
217  cpu->cd.m88k.dmd[1] = reg(ic->arg[0] + 4);
218 #else
219  x = reg(ic->arg[0]);
220  cpu->cd.m88k.dmd[0] = x;
221 #endif
223  if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
224  MEM_WRITE, memory_rw_flags)) {
225  /* Exception. */
226  return;
227  }
228 #endif
229 }
230 #endif /* LS_INCLUDE_GENERIC */
231 
232 
233 void LS_N(struct cpu *cpu, struct m88k_instr_call *ic)
234 {
235  uint32_t addr = reg(ic->arg[1]) +
236 #ifdef LS_REGOFS
237 #ifdef LS_SCALED
238  LS_SIZE *
239 #endif
240  reg(ic->arg[2]);
241 #else
242  ic->arg[2];
243 #endif
244 
245 #ifdef LS_USR
246 #ifdef LS_LOAD
247  uint8_t *p = cpu->cd.m88k.host_load_usr[addr >> 12];
248 #else
249  uint8_t *p = cpu->cd.m88k.host_store_usr[addr >> 12];
250 #endif
251 #else
252 #ifdef LS_LOAD
253  uint8_t *p = cpu->cd.m88k.host_load[addr >> 12];
254 #else
255  uint8_t *p = cpu->cd.m88k.host_store[addr >> 12];
256 #endif
257 #endif
258 
259  /*
260  * Call the generic function, if things become too complicated:
261  *
262  * 1) .usr used in non-supervisor mode
263  * 2) the page pointer is NULL
264  * 3) unaligned access
265  */
266  if (
267 #ifdef LS_USR
269 #endif
270 
271  p == NULL
272 #ifndef LS_1
273  || addr & (LS_SIZE - 1)
274 #endif
275  ) {
276  LS_GENERIC_N(cpu, ic);
277  return;
278  }
279 
280  addr &= 0xfff;
281 
282 #ifdef LS_LOAD
283  /* Load: */
284 
285 #ifdef LS_1
286  reg(ic->arg[0]) =
287 #ifdef LS_SIGNED
288  (int8_t)
289 #endif
290  p[addr];
291 #endif /* LS_1 */
292 
293 #ifdef LS_2
294  reg(ic->arg[0]) =
295 #ifdef LS_SIGNED
296  (int16_t)
297 #endif
298 #ifdef LS_BE
299 #ifdef HOST_BIG_ENDIAN
300  ( *(uint16_t *)(p + addr) );
301 #else
302  ((p[addr]<<8) + p[addr+1]);
303 #endif
304 #else
305 #ifdef HOST_LITTLE_ENDIAN
306  ( *(uint16_t *)(p + addr) );
307 #else
308  (p[addr] + (p[addr+1]<<8));
309 #endif
310 #endif
311 #endif /* LS_2 */
312 
313 #ifdef LS_4
314  reg(ic->arg[0]) =
315 #ifdef LS_SIGNED
316  (int32_t)
317 #else
318  (uint32_t)
319 #endif
320 #ifdef LS_BE
321 #ifdef HOST_BIG_ENDIAN
322  ( *(uint32_t *)(p + addr) );
323 #else
324  ((p[addr]<<24) + (p[addr+1]<<16) + (p[addr+2]<<8) + p[addr+3]);
325 #endif
326 #else
327 #ifdef HOST_LITTLE_ENDIAN
328  ( *(uint32_t *)(p + addr) );
329 #else
330  (p[addr] + (p[addr+1]<<8) + (p[addr+2]<<16) + (p[addr+3]<<24));
331 #endif
332 #endif
333 #endif /* LS_4 */
334 
335 #ifdef LS_8
336 
337  /* Load first word in pair: */
338  reg(ic->arg[0]) =
339 #ifdef LS_BE
340 #ifdef HOST_BIG_ENDIAN
341  ( *(uint32_t *)(p + addr) );
342 #else
343  ((p[addr]<<24) + (p[addr+1]<<16) + (p[addr+2]<<8) + p[addr+3]);
344 #endif
345 #else
346 #ifdef HOST_LITTLE_ENDIAN
347  ( *(uint32_t *)(p + addr + 4) );
348 #else
349  (p[addr+4] + (p[addr+5]<<8) + (p[addr+6]<<16) + (p[addr+7]<<24));
350 #endif
351 #endif
352 
353  /* Load second word in pair: */
354  reg(ic->arg[0] + 4) =
355 #ifdef LS_BE
356 #ifdef HOST_BIG_ENDIAN
357  ( *(uint32_t *)(p + addr + 4) );
358 #else
359  ((p[addr+4]<<24) + (p[addr+5]<<16) + (p[addr+6]<<8) + p[addr+7]);
360 #endif
361 #else
362 #ifdef HOST_LITTLE_ENDIAN
363  ( *(uint32_t *)(p + addr) );
364 #else
365  (p[addr] + (p[addr+1]<<8) + (p[addr+2]<<16) + (p[addr+3]<<24));
366 #endif
367 #endif
368 
369 #endif /* LS_8 */
370 
371 #else
372  /* Store: */
373 
374 #ifdef LS_1
375  p[addr] = reg(ic->arg[0]);
376 #endif
377 #ifdef LS_2
378  { uint32_t x = reg(ic->arg[0]);
379 #ifdef LS_BE
380 #ifdef HOST_BIG_ENDIAN
381  *((uint16_t *)(p+addr)) = x; }
382 #else
383  p[addr] = x >> 8; p[addr+1] = x; }
384 #endif
385 #else
386 #ifdef HOST_LITTLE_ENDIAN
387  *((uint16_t *)(p+addr)) = x; }
388 #else
389  p[addr] = x; p[addr+1] = x >> 8; }
390 #endif
391 #endif
392 #endif /* LS_2 */
393 #ifdef LS_4
394  { uint32_t x = reg(ic->arg[0]);
395 #ifdef LS_BE
396 #ifdef HOST_BIG_ENDIAN
397  *((uint32_t *)(p+addr)) = x; }
398 #else
399  p[addr] = x >> 24; p[addr+1] = x >> 16;
400  p[addr+2] = x >> 8; p[addr+3] = x; }
401 #endif
402 #else
403 #ifdef HOST_LITTLE_ENDIAN
404  *((uint32_t *)(p+addr)) = x; }
405 #else
406  p[addr] = x; p[addr+1] = x >> 8;
407  p[addr+2] = x >> 16; p[addr+3] = x >> 24; }
408 #endif
409 #endif
410 #endif /* LS_4 */
411 #ifdef LS_8
412 
413  /* First word in pair: */
414  { uint32_t x = reg(ic->arg[0]);
415 #ifdef LS_BE
416 #ifdef HOST_BIG_ENDIAN
417  *((uint32_t *)(p+addr)) = x; }
418 #else
419  p[addr] = x >> 24; p[addr+1] = x >> 16;
420  p[addr+2] = x >> 8; p[addr+3] = x; }
421 #endif
422 #else
423 #ifdef HOST_LITTLE_ENDIAN
424  *((uint32_t *)(p+addr+4)) = x; }
425 #else
426  p[addr +4] = x; p[addr+1+4] = x >> 8;
427  p[addr+2+4] = x >> 16; p[addr+3+4] = x >> 24; }
428 #endif
429 #endif
430 
431  /* Second word in pair: */
432  { uint32_t x = reg(ic->arg[0] + 4);
433 #ifdef LS_BE
434 #ifdef HOST_BIG_ENDIAN
435  *((uint32_t *)(p+addr+4)) = x; }
436 #else
437  p[addr +4] = x >> 24; p[addr+1+4] = x >> 16;
438  p[addr+2+4] = x >> 8; p[addr+3+4] = x; }
439 #endif
440 #else
441 #ifdef HOST_LITTLE_ENDIAN
442  *((uint32_t *)(p+addr)) = x; }
443 #else
444  p[addr ] = x; p[addr+1] = x >> 8;
445  p[addr+2] = x >> 16; p[addr+3] = x >> 24; }
446 #endif
447 #endif
448 
449 #endif /* LS_8 */
450 
451 #endif /* store */
452 }
453 
data
u_short data
Definition: siireg.h:79
M88K_EXCEPTION_PRIVILEGE_VIOLATION
#define M88K_EXCEPTION_PRIVILEGE_VIOLATION
Definition: M88K_CPUComponent.h:289
cpu::running
uint8_t running
Definition: cpu.h:353
m88k_cpu::dmd
uint32_t dmd[2]
Definition: cpu_m88k.h:254
LS_1
#define LS_1
Definition: tmp_m88k_loadstore.cc:1159
MEM_READ
#define MEM_READ
Definition: memory.h:116
cpu::byte_order
uint8_t byte_order
Definition: cpu.h:347
EMUL_BIG_ENDIAN
#define EMUL_BIG_ENDIAN
Definition: misc.h:165
DMT_ENSHIFT
#define DMT_ENSHIFT
Definition: m88k_dmt.h:55
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
cpu::m88k
struct m88k_cpu m88k
Definition: cpu.h:442
LS_GENERIC_N
void LS_GENERIC_N(struct cpu *cpu, struct ppc_instr_call *ic)
Definition: cpu_ppc_instr_loadstore.cc:42
DMT_DAS
#define DMT_DAS
Definition: m88k_dmt.h:45
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
MEMORY_USER_ACCESS
#define MEMORY_USER_ACCESS
Definition: memory.h:127
DMT_SIGNED
#define DMT_SIGNED
Definition: m88k_dmt.h:49
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
cpu::cd
union cpu::@1 cd
ic
struct arm_instr_call * ic
Definition: tmp_arm_multi.cc:50
M88K_IC_ENTRIES_PER_PAGE
#define M88K_IC_ENTRIES_PER_PAGE
Definition: M88K_CPUComponent.h:261
m88k_cpu::dmt
uint32_t dmt[2]
Definition: cpu_m88k.h:253
DMT_WRITE
#define DMT_WRITE
Definition: m88k_dmt.h:51
m88k_exception
void m88k_exception(struct cpu *cpu, int vector, int is_trap)
Definition: cpu_m88k.cc:648
CACHE_DATA
#define CACHE_DATA
Definition: memory.h:121
M88K_PSR_MODE
#define M88K_PSR_MODE
Definition: m88k_psl.h:70
M88K_INSTR_ALIGNMENT_SHIFT
#define M88K_INSTR_ALIGNMENT_SHIFT
Definition: M88K_CPUComponent.h:260
m88k_cpu::cr
uint32_t cr[N_M88K_CONTROL_REGS]
Definition: cpu_m88k.h:241
cpu::mem
struct memory * mem
Definition: cpu.h:362
debugger_n_steps_left_before_interaction
int debugger_n_steps_left_before_interaction
Definition: debugger.cc:73
EMUL_LITTLE_ENDIAN
#define EMUL_LITTLE_ENDIAN
Definition: misc.h:164
cpu::delay_slot
uint8_t delay_slot
Definition: cpu.h:356
DMT_VALID
#define DMT_VALID
Definition: m88k_dmt.h:52
reg
#define reg(x)
Definition: tmp_alpha_tail.cc:53
DMT_DREGSHIFT
#define DMT_DREGSHIFT
Definition: m88k_dmt.h:54
LS_USR
#define LS_USR
Definition: tmp_m88k_loadstore.cc:1758
LS_BE
#define LS_BE
Definition: tmp_m88k_loadstore.cc:1756
DMT_DOUB1
#define DMT_DOUB1
Definition: m88k_dmt.h:46
M88K_CR_PSR
#define M88K_CR_PSR
Definition: M88K_CPUComponent.h:183
m88k_cpu::r
uint32_t r[N_M88K_REGS+1]
Definition: cpu_m88k.h:235
m88k_cpu::dma
uint32_t dma[2]
Definition: cpu_m88k.h:255
LS_N
void LS_N(struct cpu *cpu, struct m88k_instr_call *ic)
Definition: cpu_m88k_instr_loadstore.cc:233
M88K_EXCEPTION_MISALIGNED_ACCESS
#define M88K_EXCEPTION_MISALIGNED_ACCESS
Definition: M88K_CPUComponent.h:287
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
LS_SIZE
#define LS_SIZE
Definition: tmp_m88k_loadstore.cc:1754
cpu
Definition: cpu.h:326
DMT_BO
#define DMT_BO
Definition: m88k_dmt.h:44
EXCEPTION_IN_DELAY_SLOT
#define EXCEPTION_IN_DELAY_SLOT
Definition: cpu.h:308
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:365
cpu::pc
uint64_t pc
Definition: cpu.h:383

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17