]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/aarch64/memory.c
Add an AArch64 simulator to GDB.
[thirdparty/binutils-gdb.git] / sim / aarch64 / memory.c
CommitLineData
2e8cf49e
NC
1/* memory.c -- Memory accessor functions for the AArch64 simulator
2
3 Copyright (C) 2015 Free Software Foundation, Inc.
4
5 Contributed by Red Hat.
6
7 This file is part of GDB.
8
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.
13
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.
18
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/>. */
21
22#include "config.h"
23#include <sys/types.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "bfd.h"
29#include "libbfd.h"
30#include "libiberty.h"
31#include "elf/internal.h"
32#include "elf/common.h"
33
34#include "memory.h"
35#include "simulator.h"
36
37#include "sim-core.h"
38
39static inline void
40mem_error (sim_cpu *cpu, const char *message, uint64_t addr)
41{
42 if (disas)
43 sim_io_eprintf (CPU_STATE (cpu), "\n");
44 TRACE_MEMORY (cpu, "ERROR: %s: %" PRIx64, message, addr);
45}
46
47#define FETCH_FUNC(RETURN_TYPE, ACCESS_TYPE, NAME, N) \
48 RETURN_TYPE \
49 aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address) \
50 { \
51 return (RETURN_TYPE) sim_core_read_##N (cpu, 0, read_map, address); \
52 }
53
54/* A variant of the FETCH_FUNC macro that uses unaligned reads.
55 The AArch64 only requires 4-byte alignment for 8-byte quantities
56 but the sim common core does not support this. */
57#define FETCH_FUNC_U(RETURN_TYPE, ACCESS_TYPE, NAME) \
58 RETURN_TYPE \
59 aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address) \
60 { \
61 return (RETURN_TYPE) sim_core_read_unaligned_8 (cpu, 0, read_map, address); \
62 }
63
64FETCH_FUNC_U (uint64_t, uint64_t, u64)
65FETCH_FUNC_U (int64_t, int64_t, s64)
66FETCH_FUNC (uint32_t, uint32_t, u32, 4)
67FETCH_FUNC (int32_t, int32_t, s32, 4)
68FETCH_FUNC (uint32_t, uint16_t, u16, 2)
69FETCH_FUNC (int32_t, int16_t, s16, 2)
70FETCH_FUNC (uint32_t, uint8_t, u8, 1)
71FETCH_FUNC (int32_t, int8_t, s8, 1)
72FETCH_FUNC (float, float, float, 4)
73FETCH_FUNC_U (double, double, double)
74
75void
76aarch64_get_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister *a)
77{
78 a->v[0] = sim_core_read_unaligned_8 (cpu, 0, read_map, address);
79 a->v[1] = sim_core_read_unaligned_8 (cpu, 0, read_map, address + 8);
80}
81
82#define STORE_FUNC(TYPE, NAME, N) \
83 void \
84 aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value) \
85 { \
86 TRACE_MEMORY (cpu, \
87 "write of %" PRIx64 " (%d bytes) to %" PRIx64, \
88 (uint64_t) value, N, address); \
89 \
90 sim_core_write_unaligned_##N (cpu, 0, write_map, address, value); \
91 }
92
93/* A variant of the STORE_FUNC macro that uses unaligned writes.
94 The AArch64 only requires 4-byte alignment for 8-byte quantities
95 but the sim common core does not support this. */
96#define STORE_FUNC_U(TYPE, NAME) \
97 void \
98 aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value) \
99 { \
100 TRACE_MEMORY (cpu, \
101 "write of %" PRIx64 " (8 bytes) to %" PRIx64, \
102 (uint64_t) value, address); \
103 \
104 sim_core_write_unaligned_8 (cpu, 0, write_map, address, value); \
105 }
106
107STORE_FUNC_U (uint64_t, u64)
108STORE_FUNC_U (int64_t, s64)
109STORE_FUNC (uint32_t, u32, 4)
110STORE_FUNC (int32_t, s32, 4)
111STORE_FUNC (uint16_t, u16, 2)
112STORE_FUNC (int16_t, s16, 2)
113STORE_FUNC (uint8_t, u8, 1)
114STORE_FUNC (int8_t, s8, 1)
115STORE_FUNC (float, float, 4)
116STORE_FUNC_U (double, double)
117
118void
119aarch64_set_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister a)
120{
121 TRACE_MEMORY (cpu,
122 "write of long double %" PRIx64 " %" PRIx64 " to %" PRIx64,
123 a.v[0], a.v[1], address);
124
125 sim_core_write_unaligned_8 (cpu, 0, write_map, address, a.v[0]);
126 sim_core_write_unaligned_8 (cpu, 0, write_map, address + 8, a.v[1]);
127}
128
129void
130aarch64_get_mem_blk (sim_cpu * cpu,
131 uint64_t address,
132 char * buffer,
133 unsigned length)
134{
135 unsigned len;
136
137 len = sim_core_read_buffer (CPU_STATE (cpu), cpu, read_map,
138 buffer, address, length);
139 if (len == length)
140 return;
141
142 memset (buffer, 0, length);
143 if (cpu)
144 mem_error (cpu, "read of non-existant mem block at", address);
145
146 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
147 sim_stopped, SIM_SIGBUS);
148}
149
150const char *
151aarch64_get_mem_ptr (sim_cpu *cpu, uint64_t address)
152{
153 char *addr = sim_core_trans_addr (CPU_STATE (cpu), cpu, read_map, address);
154
155 if (addr == NULL)
156 {
157 mem_error (cpu, "request for non-existant mem addr of", address);
158 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
159 sim_stopped, SIM_SIGBUS);
160 }
161
162 return addr;
163}
164
165/* We implement a combined stack and heap. That way the sbrk()
166 function in libgloss/aarch64/syscalls.c has a chance to detect
167 an out-of-memory condition by noticing a stack/heap collision.
168
169 The heap starts at the end of loaded memory and carries on up
170 to an arbitary 2Gb limit. */
171
172uint64_t
173aarch64_get_heap_start (sim_cpu *cpu)
174{
175 uint64_t heap = aarch64_get_sym_value ("end");
176
177 if (heap == 0)
178 heap = aarch64_get_sym_value ("_end");
179 if (heap == 0)
180 {
181 heap = STACK_TOP - 0x100000;
182 sim_io_eprintf (CPU_STATE (cpu),
183 "Unable to find 'end' symbol - using addr based "
184 "upon stack instead %" PRIx64 "\n",
185 heap);
186 }
187 return heap;
188}
189
190uint64_t
191aarch64_get_stack_start (sim_cpu *cpu)
192{
193 if (aarch64_get_heap_start (cpu) >= STACK_TOP)
194 mem_error (cpu, "executable is too big", aarch64_get_heap_start (cpu));
195 return STACK_TOP;
196}