1 /* memory.c -- Memory accessor functions for the AArch64 simulator
3 Copyright (C) 2015-2016 Free Software Foundation, Inc.
5 Contributed by Red Hat.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include <sys/types.h>
30 #include "libiberty.h"
31 #include "elf/internal.h"
32 #include "elf/common.h"
35 #include "simulator.h"
40 mem_error (sim_cpu *cpu, const char *message, uint64_t addr)
42 TRACE_MEMORY (cpu, "ERROR: %s: %" PRIx64, message, addr);
45 #define FETCH_FUNC(RETURN_TYPE, ACCESS_TYPE, NAME, N) \
47 aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address) \
49 RETURN_TYPE val = (RETURN_TYPE) sim_core_read_##N (cpu, 0, read_map, address); \
51 "read of %" PRIx64 " (%d bytes) from %" PRIx64, \
52 (uint64_t) val, N, address); \
57 /* A variant of the FETCH_FUNC macro that uses unaligned reads.
58 The AArch64 only requires 4-byte alignment for 8-byte quantities
59 but the sim common core does not support this. */
60 #define FETCH_FUNC_U(RETURN_TYPE, ACCESS_TYPE, NAME) \
62 aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address) \
64 RETURN_TYPE val = (RETURN_TYPE) sim_core_read_unaligned_8 (cpu, 0, read_map, address); \
66 "read of %" PRIx64 " (%d bytes) from %" PRIx64 " (unaligned double)", \
67 (uint64_t) val, N, address); \
72 FETCH_FUNC_U (uint64_t, uint64_t, u64)
73 FETCH_FUNC_U (int64_t, int64_t, s64)
74 FETCH_FUNC (uint32_t, uint32_t, u32, 4)
75 FETCH_FUNC (int32_t, int32_t, s32, 4)
76 FETCH_FUNC (uint32_t, uint16_t, u16, 2)
77 FETCH_FUNC (int32_t, int16_t, s16, 2)
78 FETCH_FUNC (uint32_t, uint8_t, u8, 1)
79 FETCH_FUNC (int32_t, int8_t, s8, 1)
82 aarch64_get_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister *a)
84 a->v[0] = sim_core_read_unaligned_8 (cpu, 0, read_map, address);
85 a->v[1] = sim_core_read_unaligned_8 (cpu, 0, read_map, address + 8);
88 #define STORE_FUNC(TYPE, NAME, N) \
90 aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value) \
93 "write of %" PRIx64 " (%d bytes) to %" PRIx64, \
94 (uint64_t) value, N, address); \
96 sim_core_write_unaligned_##N (cpu, 0, write_map, address, value); \
99 /* A variant of the STORE_FUNC macro that uses unaligned writes.
100 The AArch64 only requires 4-byte alignment for 8-byte quantities
101 but the sim common core does not support this. */
102 #define STORE_FUNC_U(TYPE, NAME) \
104 aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value) \
107 "write of %" PRIx64 " (8 bytes) to %" PRIx64, \
108 (uint64_t) value, address); \
110 sim_core_write_unaligned_8 (cpu, 0, write_map, address, value); \
113 STORE_FUNC_U (uint64_t, u64)
114 STORE_FUNC_U (int64_t, s64)
115 STORE_FUNC (uint32_t, u32, 4)
116 STORE_FUNC (int32_t, s32, 4)
117 STORE_FUNC (uint16_t, u16, 2)
118 STORE_FUNC (int16_t, s16, 2)
119 STORE_FUNC (uint8_t, u8, 1)
120 STORE_FUNC (int8_t, s8, 1)
123 aarch64_set_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister a)
126 "write of long double %" PRIx64 " %" PRIx64 " to %" PRIx64,
127 a.v[0], a.v[1], address);
129 sim_core_write_unaligned_8 (cpu, 0, write_map, address, a.v[0]);
130 sim_core_write_unaligned_8 (cpu, 0, write_map, address + 8, a.v[1]);
134 aarch64_get_mem_blk (sim_cpu * cpu,
141 len = sim_core_read_buffer (CPU_STATE (cpu), cpu, read_map,
142 buffer, address, length);
146 memset (buffer, 0, length);
148 mem_error (cpu, "read of non-existant mem block at", address);
150 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
151 sim_stopped, SIM_SIGBUS);
155 aarch64_get_mem_ptr (sim_cpu *cpu, uint64_t address)
157 char *addr = sim_core_trans_addr (CPU_STATE (cpu), cpu, read_map, address);
161 mem_error (cpu, "request for non-existant mem addr of", address);
162 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
163 sim_stopped, SIM_SIGBUS);
169 /* We implement a combined stack and heap. That way the sbrk()
170 function in libgloss/aarch64/syscalls.c has a chance to detect
171 an out-of-memory condition by noticing a stack/heap collision.
173 The heap starts at the end of loaded memory and carries on up
174 to an arbitary 2Gb limit. */
177 aarch64_get_heap_start (sim_cpu *cpu)
179 uint64_t heap = aarch64_get_sym_value ("end");
182 heap = aarch64_get_sym_value ("_end");
185 heap = STACK_TOP - 0x100000;
186 sim_io_eprintf (CPU_STATE (cpu),
187 "Unable to find 'end' symbol - using addr based "
188 "upon stack instead %" PRIx64 "\n",
195 aarch64_get_stack_start (sim_cpu *cpu)
197 if (aarch64_get_heap_start (cpu) >= STACK_TOP)
198 mem_error (cpu, "executable is too big", aarch64_get_heap_start (cpu));