dev_ram.cc Source File

Back to the index.

dev_ram.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2019 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  * COMMENT: A generic RAM (memory) device
29  *
30  * Note: This device can also be used to mirror/alias another part of RAM.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/mman.h>
38 
39 #include "cpu.h"
40 #include "devices.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44 
45 
46 struct ram_data {
47  uint64_t baseaddress;
48  const char* name;
49 
50  bool trace;
51  int mode;
52  uint64_t otheraddress;
53 
54  /* If mode = DEV_RAM_MIRROR: */
55  uint64_t offset;
56 
57  /* If mode = DEV_RAM_RAM: */
58  unsigned char *data;
59  uint64_t length;
60 };
61 
62 
64 {
65  struct ram_data *d = (struct ram_data *) extra;
66 
67  if (cpu->running && d->trace && writeflag == MEM_WRITE) {
68  fatal("[ %s: write %i byte%s from 0x%x:",
69  d->name, (int)len, len==1? "":"s", (int)relative_addr);
70  for (size_t i=0; i<len; i++)
71  fatal(" %02x", data[i]);
72  fatal(" ]\n");
73  }
74 
75  switch (d->mode) {
76 
77  case DEV_RAM_MIRROR:
78  /* TODO: how about caches? */
79  {
80  int result = cpu->memory_rw(cpu, mem,
81  d->otheraddress + relative_addr, data, len,
82  writeflag, PHYSICAL);
83 
84  /* Invalidate any code translations in both the MIRRORED
85  and the MIRROR address ranges on a write: */
86  if (writeflag == MEM_WRITE &&
89  cpu, d->otheraddress + relative_addr,
92  cpu, d->baseaddress + relative_addr,
94  }
95 
96  if (cpu->running && d->trace && writeflag == MEM_READ) {
97  fatal("[ %s: read %i byte%s from 0x%x:",
98  d->name, (int)len, len==1? "":"s", (int)relative_addr);
99  for (size_t i=0; i<len; i++)
100  fatal(" %02x", data[i]);
101  fatal(" ]\n");
102  }
103 
104  return result;
105  }
106 
107  case DEV_RAM_RAM:
108  if (writeflag == MEM_WRITE) {
109  memcpy(&d->data[relative_addr], data, len);
110 
111  /* Invalidate any code translations on a write: */
112  if (cpu->invalidate_code_translation != NULL) {
114  cpu, d->baseaddress + relative_addr,
116  }
117  } else {
118  memcpy(data, &d->data[relative_addr], len);
119 
120  if (cpu->running && d->trace && writeflag == MEM_READ) {
121  fatal("[ %s: read %i byte%s from 0x%x:",
122  d->name, (int)len, len==1? "":"s", (int)relative_addr);
123  for (size_t i=0; i<len; i++)
124  fatal(" %02x", data[i]);
125  fatal(" ]\n");
126  }
127  }
128  break;
129 
130  default:
131  fatal("dev_ram_access(): unknown mode %i\n", d->mode);
132  exit(1);
133  }
134 
135  return 1;
136 }
137 
138 
139 /*
140  * dev_ram_init():
141  *
142  * Initializes a RAM or mirror device. Things get a bit complicated because
143  * of dyntrans (i.e. mirrored memory ranges should be entered into the
144  * translation arrays just as normal memory and other devices are).
145  */
146 void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length,
147  int mode, uint64_t otheraddress, const char* name)
148 {
149  struct ram_data *d;
150  int flags = DM_DEFAULT, points_to_ram = 1;
151 
152  CHECK_ALLOCATION(d = (struct ram_data *) malloc(sizeof(struct ram_data)));
153  memset(d, 0, sizeof(struct ram_data));
154 
155  d->name = strdup((name == NULL) ? "ram" : name);
156 
159  points_to_ram = 0;
160  }
161 
164  d->trace = true;
165  }
166 
167  d->mode = mode;
168  d->baseaddress = baseaddr;
170 
171  switch (d->mode) {
172 
173  case DEV_RAM_MIRROR:
174  /*
175  * Calculate the amount that the mirror memory is offset from
176  * the real (physical) memory. This is used in src/memory_rw.c
177  * with dyntrans accesses if DM_EMULATED_RAM is set.
178  */
179  d->offset = baseaddr - otheraddress;
180  d->name = (string(d->name) + " [mirror]").c_str();
181 
182  /* Aligned RAM? Then it works with dyntrans. */
183  if (points_to_ram &&
184  (baseaddr & (machine->arch_pagesize-1)) == 0 &&
185  (otheraddress & (machine->arch_pagesize - 1)) == 0 &&
186  (length & (machine->arch_pagesize - 1)) == 0 &&
187  !d->trace)
189  | DM_EMULATED_RAM;
190 
192  baseaddr, length, dev_ram_access, d, flags
193  | DM_READS_HAVE_NO_SIDE_EFFECTS, (unsigned char*) (void *) &d->offset);
194  break;
195 
196  case DEV_RAM_RAM:
197  /*
198  * Allocate zero-filled RAM using mmap(). If mmap() failed,
199  * try malloc(), but then memset() must also be called, which
200  * can be slow for large chunks of memory.
201  */
202  d->length = length;
203  d->data = (unsigned char *) mmap(NULL, length,
204  PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
205  if (d->data == NULL) {
206  CHECK_ALLOCATION(d->data = (unsigned char *) malloc(length));
207  memset(d->data, 0, length);
208  }
209 
210  /* Aligned memory? Then it works with dyntrans. */
211  if ((baseaddr & (machine->arch_pagesize - 1)) == 0 &&
212  (length & (machine->arch_pagesize - 1)) == 0 &&
213  !d->trace)
215 
216  memory_device_register(machine->memory, d->name, baseaddr,
217  d->length, dev_ram_access, d, flags
219  break;
220 
221  default:
222  fatal("dev_ram_access(): %s: unknown mode %i\n", d->name, d->mode);
223  exit(1);
224  }
225 }
226 
ram_data::name
const char * name
Definition: dev_ram.cc:48
DM_EMULATED_RAM
#define DM_EMULATED_RAM
Definition: memory.h:134
ram_data::otheraddress
uint64_t otheraddress
Definition: dev_ram.cc:52
data
u_short data
Definition: siireg.h:79
machine::arch_pagesize
int arch_pagesize
Definition: machine.h:151
cpu::running
uint8_t running
Definition: cpu.h:353
ram_data::length
uint64_t length
Definition: dev_ram.cc:59
DEV_RAM_MIRROR
#define DEV_RAM_MIRROR
Definition: devices.h:365
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
MEM_READ
#define MEM_READ
Definition: memory.h:116
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
DEV_RAM_RAM
#define DEV_RAM_RAM
Definition: devices.h:364
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
cpu::invalidate_code_translation
void(* invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:379
DM_DYNTRANS_WRITE_OK
#define DM_DYNTRANS_WRITE_OK
Definition: memory.h:132
ram_data::data
unsigned char * data
Definition: dev_ram.cc:58
DEVICE_ACCESS
DEVICE_ACCESS(ram)
Definition: dev_ram.cc:63
PHYSICAL
#define PHYSICAL
Definition: memory.h:126
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
misc.h
machine.h
machine
Definition: machine.h:97
dev_ram_access
int dev_ram_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
ram_data
Definition: dev_ram.cc:46
cpu.h
machine::memory
struct memory * memory
Definition: machine.h:126
DEV_RAM_MIGHT_POINT_TO_DEVICES
#define DEV_RAM_MIGHT_POINT_TO_DEVICES
Definition: devices.h:366
ram_data::offset
uint64_t offset
Definition: dev_ram.cc:55
DM_READS_HAVE_NO_SIDE_EFFECTS
#define DM_READS_HAVE_NO_SIDE_EFFECTS
Definition: memory.h:133
ram_data::baseaddress
uint64_t baseaddress
Definition: dev_ram.cc:47
ram_data::trace
bool trace
Definition: dev_ram.cc:50
INVALIDATE_PADDR
#define INVALIDATE_PADDR
Definition: cpu.h:482
devices.h
cpu
Definition: cpu.h:326
DM_DYNTRANS_OK
#define DM_DYNTRANS_OK
Definition: memory.h:131
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
dev_ram_init
void dev_ram_init(struct machine *machine, uint64_t baseaddr, uint64_t length, int mode, uint64_t otheraddress, const char *name)
Definition: dev_ram.cc:146
memory.h
DEV_RAM_TRACE_ALL_ACCESSES
#define DEV_RAM_TRACE_ALL_ACCESSES
Definition: devices.h:367
ram_data::mode
int mode
Definition: dev_ram.cc:51
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

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