+/* Return a pointer into the raw buffer designated by phys_addr. It
+ is assumed that the client has already ensured that the access
+ isn't going to cross a segment boundary. */
+
+uint8 *
+map_memory (unsigned phys_addr)
+{
+ uint8 **memory;
+ uint8 *raw;
+ unsigned offset;
+ int segment = ((phys_addr >> 24) & 0xff);
+
+ switch (segment)
+ {
+
+ case 0x00: /* Unified memory */
+ {
+ memory = &State.mem.unif[(phys_addr / SEGMENT_SIZE) % UMEM_SEGMENTS];
+ last_segname = "umem";
+ break;
+ }
+
+ case 0x01: /* On-chip insn memory */
+ {
+ memory = &State.mem.insn[(phys_addr / SEGMENT_SIZE) % IMEM_SEGMENTS];
+ last_segname = "imem";
+ break;
+ }
+
+ case 0x02: /* On-chip data memory */
+ {
+ if ((phys_addr & 0xff00) == 0xff00)
+ {
+ phys_addr = (phys_addr & 0xffff);
+ if (phys_addr == DMAP2_SHADDOW)
+ {
+ phys_addr = DMAP2_OFFSET;
+ last_segname = "dmap";
+ }
+ else
+ last_segname = "reg";
+ }
+ else
+ last_segname = "dmem";
+ memory = &State.mem.data[(phys_addr / SEGMENT_SIZE) % DMEM_SEGMENTS];
+ break;
+ }
+
+ default:
+ /* OOPS! */
+ last_segname = "scrap";
+ return State.mem.fault;
+ }
+
+ if (*memory == NULL)
+ {
+ *memory = calloc (1, SEGMENT_SIZE);
+ if (*memory == NULL)
+ {
+ (*d10v_callback->printf_filtered) (d10v_callback, "Malloc failed.\n");
+ return State.mem.fault;
+ }
+ }
+
+ offset = (phys_addr % SEGMENT_SIZE);
+ raw = *memory + offset;
+ return raw;
+}
+
+/* Transfer data to/from simulated memory. Since a bug in either the
+ simulated program or in gdb or the simulator itself may cause a
+ bogus address to be passed in, we need to do some sanity checking
+ on addresses to make sure they are within bounds. When an address
+ fails the bounds check, treat it as a zero length read/write rather
+ than aborting the entire run. */