Home | History | Annotate | Line # | Download | only in aarch64
      1      1.1  christos /* memory.c -- Memory accessor functions for the AArch64 simulator
      2      1.1  christos 
      3  1.1.1.6  christos    Copyright (C) 2015-2024 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    Contributed by Red Hat.
      6      1.1  christos 
      7      1.1  christos    This file is part of GDB.
      8      1.1  christos 
      9      1.1  christos    This program is free software; you can redistribute it and/or modify
     10      1.1  christos    it under the terms of the GNU General Public License as published by
     11      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12      1.1  christos    (at your option) any later version.
     13      1.1  christos 
     14      1.1  christos    This program is distributed in the hope that it will be useful,
     15      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17      1.1  christos    GNU General Public License for more details.
     18      1.1  christos 
     19      1.1  christos    You should have received a copy of the GNU General Public License
     20      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21      1.1  christos 
     22  1.1.1.5  christos /* This must come before any other includes.  */
     23  1.1.1.5  christos #include "defs.h"
     24  1.1.1.5  christos 
     25      1.1  christos #include <sys/types.h>
     26      1.1  christos #include <stdio.h>
     27      1.1  christos #include <stdlib.h>
     28      1.1  christos #include <string.h>
     29      1.1  christos 
     30      1.1  christos #include "libiberty.h"
     31      1.1  christos 
     32      1.1  christos #include "memory.h"
     33      1.1  christos #include "simulator.h"
     34      1.1  christos 
     35      1.1  christos #include "sim-core.h"
     36  1.1.1.5  christos #include "sim-signal.h"
     37      1.1  christos 
     38      1.1  christos static inline void
     39      1.1  christos mem_error (sim_cpu *cpu, const char *message, uint64_t addr)
     40      1.1  christos {
     41      1.1  christos   TRACE_MEMORY (cpu, "ERROR: %s: %" PRIx64, message, addr);
     42      1.1  christos }
     43      1.1  christos 
     44      1.1  christos /* FIXME: AArch64 requires aligned memory access if SCTRLR_ELx.A is set,
     45      1.1  christos    but we are not implementing that here.  */
     46      1.1  christos #define FETCH_FUNC64(RETURN_TYPE, ACCESS_TYPE, NAME, N)			\
     47      1.1  christos   RETURN_TYPE								\
     48      1.1  christos   aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address)		\
     49      1.1  christos   {									\
     50      1.1  christos     RETURN_TYPE val = (RETURN_TYPE) (ACCESS_TYPE)			\
     51      1.1  christos       sim_core_read_unaligned_##N (cpu, 0, read_map, address);		\
     52      1.1  christos     TRACE_MEMORY (cpu, "read of %" PRIx64 " (%d bytes) from %" PRIx64,	\
     53      1.1  christos 		  val, N, address);					\
     54      1.1  christos 									\
     55      1.1  christos     return val;								\
     56      1.1  christos   }
     57      1.1  christos 
     58      1.1  christos FETCH_FUNC64 (uint64_t, uint64_t, u64, 8)
     59      1.1  christos FETCH_FUNC64 (int64_t,   int64_t, s64, 8)
     60      1.1  christos 
     61      1.1  christos #define FETCH_FUNC32(RETURN_TYPE, ACCESS_TYPE, NAME, N)			\
     62      1.1  christos   RETURN_TYPE								\
     63      1.1  christos   aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address)		\
     64      1.1  christos   {									\
     65      1.1  christos     RETURN_TYPE val = (RETURN_TYPE) (ACCESS_TYPE)			\
     66      1.1  christos       sim_core_read_unaligned_##N (cpu, 0, read_map, address);		\
     67      1.1  christos     TRACE_MEMORY (cpu, "read of %8x (%d bytes) from %" PRIx64,		\
     68      1.1  christos 		  val, N, address);					\
     69      1.1  christos 									\
     70      1.1  christos     return val;								\
     71      1.1  christos   }
     72      1.1  christos 
     73      1.1  christos FETCH_FUNC32 (uint32_t, uint32_t, u32, 4)
     74      1.1  christos FETCH_FUNC32 (int32_t,   int32_t, s32, 4)
     75      1.1  christos FETCH_FUNC32 (uint32_t, uint16_t, u16, 2)
     76      1.1  christos FETCH_FUNC32 (int32_t,   int16_t, s16, 2)
     77      1.1  christos FETCH_FUNC32 (uint32_t,  uint8_t, u8, 1)
     78      1.1  christos FETCH_FUNC32 (int32_t,    int8_t, s8, 1)
     79      1.1  christos 
     80      1.1  christos void
     81      1.1  christos aarch64_get_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister *a)
     82      1.1  christos {
     83      1.1  christos   a->v[0] = sim_core_read_unaligned_8 (cpu, 0, read_map, address);
     84      1.1  christos   a->v[1] = sim_core_read_unaligned_8 (cpu, 0, read_map, address + 8);
     85      1.1  christos }
     86      1.1  christos 
     87      1.1  christos /* FIXME: Aarch64 requires aligned memory access if SCTRLR_ELx.A is set,
     88      1.1  christos    but we are not implementing that here.  */
     89      1.1  christos #define STORE_FUNC(TYPE, NAME, N)					\
     90      1.1  christos   void									\
     91      1.1  christos   aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value)	\
     92      1.1  christos   {									\
     93      1.1  christos     TRACE_MEMORY (cpu,							\
     94      1.1  christos 		  "write of %" PRIx64 " (%d bytes) to %" PRIx64,	\
     95      1.1  christos 		  (uint64_t) value, N, address);			\
     96      1.1  christos 									\
     97      1.1  christos     sim_core_write_unaligned_##N (cpu, 0, write_map, address, value);	\
     98      1.1  christos   }
     99      1.1  christos 
    100      1.1  christos STORE_FUNC (uint64_t, u64, 8)
    101      1.1  christos STORE_FUNC (int64_t,  s64, 8)
    102      1.1  christos STORE_FUNC (uint32_t, u32, 4)
    103      1.1  christos STORE_FUNC (int32_t,  s32, 4)
    104      1.1  christos STORE_FUNC (uint16_t, u16, 2)
    105      1.1  christos STORE_FUNC (int16_t,  s16, 2)
    106      1.1  christos STORE_FUNC (uint8_t,  u8, 1)
    107      1.1  christos STORE_FUNC (int8_t,   s8, 1)
    108      1.1  christos 
    109      1.1  christos void
    110      1.1  christos aarch64_set_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister a)
    111      1.1  christos {
    112      1.1  christos   TRACE_MEMORY (cpu,
    113      1.1  christos 		"write of long double %" PRIx64 " %" PRIx64 " to %" PRIx64,
    114      1.1  christos 		a.v[0], a.v[1], address);
    115      1.1  christos 
    116      1.1  christos   sim_core_write_unaligned_8 (cpu, 0, write_map, address, a.v[0]);
    117      1.1  christos   sim_core_write_unaligned_8 (cpu, 0, write_map, address + 8, a.v[1]);
    118      1.1  christos }
    119      1.1  christos 
    120      1.1  christos void
    121      1.1  christos aarch64_get_mem_blk (sim_cpu *  cpu,
    122      1.1  christos 		     uint64_t   address,
    123      1.1  christos 		     char *     buffer,
    124      1.1  christos 		     unsigned   length)
    125      1.1  christos {
    126      1.1  christos   unsigned len;
    127      1.1  christos 
    128      1.1  christos   len = sim_core_read_buffer (CPU_STATE (cpu), cpu, read_map,
    129      1.1  christos 			      buffer, address, length);
    130      1.1  christos   if (len == length)
    131      1.1  christos     return;
    132      1.1  christos 
    133      1.1  christos   memset (buffer, 0, length);
    134      1.1  christos   if (cpu)
    135      1.1  christos     mem_error (cpu, "read of non-existant mem block at", address);
    136      1.1  christos 
    137      1.1  christos   sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
    138      1.1  christos 		   sim_stopped, SIM_SIGBUS);
    139      1.1  christos }
    140      1.1  christos 
    141      1.1  christos const char *
    142      1.1  christos aarch64_get_mem_ptr (sim_cpu *cpu, uint64_t address)
    143      1.1  christos {
    144      1.1  christos   char *addr = sim_core_trans_addr (CPU_STATE (cpu), cpu, read_map, address);
    145      1.1  christos 
    146      1.1  christos   if (addr == NULL)
    147      1.1  christos     {
    148      1.1  christos       mem_error (cpu, "request for non-existant mem addr of", address);
    149      1.1  christos       sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu),
    150      1.1  christos 		       sim_stopped, SIM_SIGBUS);
    151      1.1  christos     }
    152      1.1  christos 
    153      1.1  christos   return addr;
    154      1.1  christos }
    155      1.1  christos 
    156      1.1  christos /* We implement a combined stack and heap.  That way the sbrk()
    157      1.1  christos    function in libgloss/aarch64/syscalls.c has a chance to detect
    158      1.1  christos    an out-of-memory condition by noticing a stack/heap collision.
    159      1.1  christos 
    160      1.1  christos    The heap starts at the end of loaded memory and carries on up
    161      1.1  christos    to an arbitary 2Gb limit.  */
    162      1.1  christos 
    163      1.1  christos uint64_t
    164      1.1  christos aarch64_get_heap_start (sim_cpu *cpu)
    165      1.1  christos {
    166  1.1.1.2  christos   uint64_t heap = trace_sym_value (CPU_STATE (cpu), "end");
    167      1.1  christos 
    168      1.1  christos   if (heap == 0)
    169  1.1.1.2  christos     heap = trace_sym_value (CPU_STATE (cpu), "_end");
    170      1.1  christos   if (heap == 0)
    171      1.1  christos     {
    172      1.1  christos       heap = STACK_TOP - 0x100000;
    173      1.1  christos       sim_io_eprintf (CPU_STATE (cpu),
    174      1.1  christos 		      "Unable to find 'end' symbol - using addr based "
    175      1.1  christos 		      "upon stack instead %" PRIx64 "\n",
    176      1.1  christos 		      heap);
    177      1.1  christos     }
    178      1.1  christos   return heap;
    179      1.1  christos }
    180      1.1  christos 
    181      1.1  christos uint64_t
    182      1.1  christos aarch64_get_stack_start (sim_cpu *cpu)
    183      1.1  christos {
    184      1.1  christos   if (aarch64_get_heap_start (cpu) >= STACK_TOP)
    185      1.1  christos     mem_error (cpu, "executable is too big", aarch64_get_heap_start (cpu));
    186      1.1  christos   return STACK_TOP;
    187      1.1  christos }
    188