gas: avoid spurious failures in non-ELF targets in the SPARC testsuite.
[deliverable/binutils-gdb.git] / sim / ppc / hw_init.c
index 6d51c7effd296249901d7b6bb083f829a7015355..0e7403bb6c563bccf319af113bac259a43b48f06 100644 (file)
@@ -1,10 +1,10 @@
 /*  This file is part of the program psim.
     
-    Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+    Copyright 1994, 1997, 2003, 2004 Andrew Cagney
     
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
+    the Free Software Foundation; either version 3 of the License, or
     (at your option) any later version.
     
     This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@
     GNU General Public License for more details.
     
     You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+    along with this program; if not, see <http://www.gnu.org/licenses/>.
     
     */
 
@@ -47,7 +46,7 @@ dma_file(device *me,
   count = 0;
   while (1) {
     inc = fread(buf, 1, sizeof(buf), image);
-    if (feof(image) || ferror(image))
+    if (inc <= 0)
       break;
     if (device_dma_write_buffer(device_parent(me),
                                buf,
@@ -75,7 +74,7 @@ dma_file(device *me,
    DESCRIPTION
 
    Loads the entire contents of <file-name> into memory at starting at
-   <real-address>.  Assumes that memory exists for the load.
+   <<real-address>>.  Assumes that memory exists for the load.
 
    PROPERTIES
 
@@ -112,25 +111,92 @@ static device_callbacks const hw_file_callbacks = {
 
 /* DEVICE
 
-   data - initialize a memory location
+
+   data - initialize a memory location with specified data
+
 
    DESCRIPTION
 
-   A word sized quantity of data is written into memory, using the
-   targets byte ordering, at the specified memory location.
 
-   In the future this device will be extended so that it supports
-   initialization using other data types (eg array, ...)
+   The pseudo device <<data>> provides a mechanism specifying the
+   initialization of a small section of memory.
+
+   Normally, the data would be written using a dma operation.
+   However, for some addresses this will not result in the desired
+   result.  For instance, to initialize an address in an eeprom,
+   instead of a simple dma of the data, a sequence of writes (and then
+   real delays) that program the eeprom would be required.
+
+   For dma write initialization, the data device will write the
+   specified <<data>> to <<real-address>> using a normal dma.
+
+   For instance write initialization, the specified <<instance>> is
+   opened.  Then a seek to the <<real-address>> is performed followed
+   by a write of the data.
+
+
+   Integer properties are stored using the target's endian mode.
+
 
    PROPERTIES
 
-   data = <int>
 
-   Integer value to be loaded into memory
+   data = <any-valid-property> (required)
 
-   real-address = <integer>
+   Data to be loaded into memory.  The property type determines how it
+   is loaded.
+
+
+   real-address = <integer> (required)
+
+   Start address at which the data is to be stored.
+
+
+   instance = <string> (optional)
+
+   Instance specification of the device that is to be opened so that
+   the specified data can be written to it.
 
-   Start address for the data. */
+
+   EXAMPLES
+
+
+   The examples below illustrate the two alternative mechanisms that
+   can be used to store the value 0x12345678 at address 0xfff00c00,
+   which is normally part of the 512k system eeprom.
+
+
+   If the eeprom is being modeled by ram (<<memory>> device) then the
+   standard dma initialization can be used.  By convention: the data
+   devices are uniquely identified by argumenting them with the
+   destinations real address; and all data devices are put under the
+   node <</openprom/init>>.
+
+   | /openprom/memory@0xfff00000/reg 0xfff00000 0x80000
+   | /openprom/init/data@0x1000/data 0x12345678
+   | /openprom/init/data@0x1000/real-address 0x1000
+
+
+   If instead a real eeprom was being used the instance write method
+   would instead need to be used (storing just a single byte in an
+   eeprom requires a complex sequence of accesses).  The
+   <<real-address>> is specified as <<0x0c00>> which is the offset
+   into the eeprom.  For brevity, most of the eeprom properties have
+   been omited.
+
+   | /iobus/eeprom@0xfff00000/reg 0xfff00000 0x80000
+   | /openprom/init/data@0xfff00c00/real-address 0x0c00
+   | /openprom/init/data@0xfff00c00/data 0x12345667
+   | /openprom/init/data@0xfff00c00/instance /iobus/eeprom@0xfff00000/reg
+
+
+   BUGS
+
+
+   At present, only <<integer>> properties can be specified for an
+   initial data value.
+
+   */
 
 
 static void
@@ -138,27 +204,43 @@ hw_data_init_data_callback(device *me)
 {
   unsigned_word addr = device_find_integer_property(me, "real-address");
   const device_property *data = device_find_property(me, "data");
+  const char *instance_spec = (device_find_property(me, "instance") != NULL
+                              ? device_find_string_property(me, "instance")
+                              : NULL);
+  device_instance *instance = NULL;
   if (data == NULL)
     device_error(me, "missing property <data>\n");
+  if (instance_spec != NULL)
+    instance = tree_instance(me, instance_spec);
   switch (data->type) {
   case integer_property:
     {
-      unsigned32 buf = device_find_integer_property(me, "data");
+      unsigned_cell buf = device_find_integer_property(me, "data");
       H2T(buf);
-      if (device_dma_write_buffer(device_parent(me),
-                                 &buf,
-                                 0 /*address-space*/,
-                                 addr,
-                                 sizeof(buf), /*nr-bytes*/
-                                 1 /*violate ro*/) != sizeof(buf))
-       device_error(me, "Problem storing integer 0x%x at 0x%lx\n",
-                    (unsigned)buf, (unsigned long)addr);
+      if (instance == NULL) {
+       if (device_dma_write_buffer(device_parent(me),
+                                   &buf,
+                                   0 /*address-space*/,
+                                   addr,
+                                   sizeof(buf), /*nr-bytes*/
+                                   1 /*violate ro*/) != sizeof(buf))
+         device_error(me, "Problem storing integer 0x%x at 0x%lx\n",
+                      (unsigned)buf, (unsigned long)addr);
+      }
+      else {
+       if (device_instance_seek(instance, 0, addr) < 0
+           || device_instance_write(instance, &buf, sizeof(buf)) != sizeof(buf))
+         device_error(me, "Problem storing integer 0x%x at 0x%lx of instance %s\n",
+                      (unsigned)buf, (unsigned long)addr, instance_spec);
+      }
     }
     break;
   default:
     device_error(me, "Write of this data is not yet implemented\n");
     break;
   }
+  if (instance != NULL)
+    device_instance_delete(instance);
 }
 
 
@@ -174,8 +256,10 @@ static device_callbacks const hw_data_callbacks = {
 
 /* DEVICE
 
+
    load-binary - load binary segments into memory
 
+
    DESCRIPTION
 
    Each loadable segment of the specified binary is loaded into memory
@@ -185,13 +269,31 @@ static device_callbacks const hw_data_callbacks = {
    This device is normally used to load an executable into memory as
    part of real mode simulation.
 
+
    PROPERTIES
 
+
    file-name = <string>
 
    Name of the binary to be loaded.
 
-   DEVICE
+
+   claim = <anything> (optional)
+
+   If this property is present, the real memory that is to be used by
+   the image being loaded will be claimed from the memory node
+   (specified by the ihandle <</chosen/memory>>).
+
+
+   BUGS
+
+   
+   When loading the binary the bfd virtual-address is used.  It should
+   be using the bfd load-address.
+
+   */
+
+/* DEVICE
 
    map-binary - map the binary into the users address space
 
@@ -226,7 +328,7 @@ update_for_binary_section(bfd *abfd,
     return;
 
   /* check/ignore any sections of size zero */
-  section_size = bfd_get_section_size_before_reloc(the_section);
+  section_size = bfd_get_section_size (the_section);
   if (section_size == 0)
     return;
 
@@ -257,10 +359,25 @@ update_for_binary_section(bfd *abfd,
   if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
     access |= access_write;
 
+  /* if claim specified, allocate region from the memory device */
+  if (device_find_property(me, "claim") != NULL) {
+    device_instance *memory = tree_find_ihandle_property(me, "/chosen/memory");
+    unsigned_cell mem_in[3];
+    unsigned_cell mem_out[1];
+    mem_in[0] = 0; /*alignment - top-of-stack*/
+    mem_in[1] = section_size;
+    mem_in[2] = section_vma;
+    if (device_instance_call_method(memory, "claim", 3, mem_in, 1, mem_out) < 0)
+      device_error(me, "failed to claim memory for section at 0x%lx (0x%lx",
+                  section_vma,
+                  section_size);
+    if (mem_out[0] != section_vma)
+      device_error(me, "section address not as requested");
+  }
+
   /* if a map, pass up a request to create the memory in core */
   if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
     device_attach_address(device_parent(me),
-                         device_name(me),
                          attach_raw_memory,
                          0 /*address space*/,
                          section_vma,
@@ -287,7 +404,7 @@ update_for_binary_section(bfd *abfd,
                                1 /*violate_read_only*/)
        != section_size)
       device_error(me, "broken transfer\n");
-    zfree(section_init); /* only free if load */
+    free(section_init); /* only free if load */
   }
 }
 
@@ -473,16 +590,16 @@ create_ppc_elf_stack_frame(device *me,
                        start_argv, start_envp);
 
   /* set up the registers */
-  psim_write_register(device_system(me), -1,
-                     &top_of_stack, "sp", cooked_transfer);
-  psim_write_register(device_system(me), -1,
-                     &argc, "r3", cooked_transfer);
-  psim_write_register(device_system(me), -1,
-                     &start_argv, "r4", cooked_transfer);
-  psim_write_register(device_system(me), -1,
-                     &start_envp, "r5", cooked_transfer);
-  psim_write_register(device_system(me), -1,
-                     &start_aux, "r6", cooked_transfer);
+  ASSERT (psim_write_register(device_system(me), -1,
+                             &top_of_stack, "sp", cooked_transfer) > 0);
+  ASSERT (psim_write_register(device_system(me), -1,
+                             &argc, "r3", cooked_transfer) > 0);
+  ASSERT (psim_write_register(device_system(me), -1,
+                             &start_argv, "r4", cooked_transfer) > 0);
+  ASSERT (psim_write_register(device_system(me), -1,
+                             &start_envp, "r5", cooked_transfer) > 0);
+  ASSERT (psim_write_register(device_system(me), -1,
+                             &start_aux, "r6", cooked_transfer) > 0);
 }
 
 static void
@@ -501,48 +618,82 @@ create_ppc_aix_stack_frame(device *me,
   create_ppc_elf_stack_frame(me, bottom_of_stack, argv, envp);
   
   /* extract argument addresses from registers */
-  psim_read_register(device_system(me), 0,
-                    &top_of_stack, "r1", cooked_transfer);
-  psim_read_register(device_system(me), 0,
-                    &core_argc, "r3", cooked_transfer);
-  psim_read_register(device_system(me), 0,
-                    &core_argv, "r4", cooked_transfer);
-  psim_read_register(device_system(me), 0,
-                    &core_envp, "r5", cooked_transfer);
-  psim_read_register(device_system(me), 0,
-                    &core_aux, "r6", cooked_transfer);
+  ASSERT (psim_read_register(device_system(me), 0,
+                            &top_of_stack, "r1", cooked_transfer) > 0);
+  ASSERT (psim_read_register(device_system(me), 0,
+                            &core_argc, "r3", cooked_transfer) > 0);
+  ASSERT (psim_read_register(device_system(me), 0,
+                            &core_argv, "r4", cooked_transfer) > 0);
+  ASSERT (psim_read_register(device_system(me), 0,
+                            &core_envp, "r5", cooked_transfer) > 0);
+  ASSERT (psim_read_register(device_system(me), 0,
+                            &core_aux, "r6", cooked_transfer) > 0);
 
   /* extract arguments from registers */
   device_error(me, "Unfinished procedure create_ppc_aix_stack_frame\n");
 }
 
 
+static void
+create_ppc_chirp_bootargs(device *me,
+                         char **argv)
+{
+  /* concat the arguments */
+  char args[1024];
+  char **chp = argv + 1;
+  args[0] = '\0';
+  while (*chp != NULL) {
+    if (strlen(args) > 0)
+      strcat(args, " ");
+    if (strlen(args) + strlen(*chp) >= sizeof(args))
+      device_error(me, "buffer overflow");
+    strcat(args, *chp);
+    chp++;
+  }
+
+  /* set the arguments property */
+  tree_parse(me, "/chosen/bootargs \"%s", args);
+}
+
 
 static int
-hw_stack_ioctl_callback(device *me,
-                       cpu *processor,
-                       unsigned_word cia,
-                       va_list ap)
+hw_stack_ioctl(device *me,
+              cpu *processor,
+              unsigned_word cia,
+              device_ioctl_request request,
+              va_list ap)
 {
-  unsigned_word stack_pointer;
-  const char *stack_type;
-  char **argv;
-  char **envp;
-  stack_pointer = va_arg(ap, unsigned_word);
-  argv = va_arg(ap, char **);
-  envp = va_arg(ap, char **);
-  DTRACE(stack,
-        ("stack_ioctl_callback(me=0x%lx:%s processor=0x%lx cia=0x%lx argv=0x%lx envp=0x%lx)\n",
-         (long)me, device_name(me), (long)processor, (long)cia, (long)argv, (long)envp));
-  stack_type = device_find_string_property(me, "stack-type");
-  if (strcmp(stack_type, "ppc-elf") == 0)
-    create_ppc_elf_stack_frame(me, stack_pointer, argv, envp);
-  else if (strcmp(stack_type, "ppc-xcoff") == 0)
-    create_ppc_aix_stack_frame(me, stack_pointer, argv, envp);
-  else if (strcmp(stack_type, "none") != 0)
-    device_error(me, "Unknown initial stack frame type %s\n", stack_type);
-  DTRACE(stack, 
-        ("stack_ioctl_callback() = void\n"));
+  switch (request) {
+  case device_ioctl_create_stack:
+    {
+      unsigned_word stack_pointer = va_arg(ap, unsigned_word);
+      char **argv = va_arg(ap, char **);
+      char **envp = va_arg(ap, char **);
+      const char *stack_type;
+      DTRACE(stack,
+            ("stack_ioctl_callback(me=0x%lx:%s processor=0x%lx cia=0x%lx argv=0x%lx envp=0x%lx)\n",
+             (long)me, device_name(me),
+             (long)processor,
+             (long)cia,
+             (long)argv,
+             (long)envp));
+      stack_type = device_find_string_property(me, "stack-type");
+      if (strcmp(stack_type, "ppc-elf") == 0)
+       create_ppc_elf_stack_frame(me, stack_pointer, argv, envp);
+      else if (strcmp(stack_type, "ppc-xcoff") == 0)
+       create_ppc_aix_stack_frame(me, stack_pointer, argv, envp);
+      else if (strcmp(stack_type, "chirp") == 0)
+       create_ppc_chirp_bootargs(me, argv);
+      else if (strcmp(stack_type, "none") != 0)
+       device_error(me, "Unknown initial stack frame type %s", stack_type);
+      DTRACE(stack, 
+            ("stack_ioctl_callback() = void\n"));
+      break;
+    }
+  default:
+    device_error(me, "Unsupported ioctl requested");
+    break;
+  }
   return 0;
 }
 
@@ -554,7 +705,7 @@ static device_callbacks const hw_stack_callbacks = {
   { NULL, }, /* interrupt */
   { NULL, }, /* unit */
   NULL, /* instance */
-  hw_stack_ioctl_callback,
+  hw_stack_ioctl,
 };
 
 const device_descriptor hw_init_device_descriptor[] = {
@@ -566,4 +717,4 @@ const device_descriptor hw_init_device_descriptor[] = {
   { NULL },
 };
 
-#endif _HW_INIT_C_
+#endif /* _HW_INIT_C_ */
This page took 0.029154 seconds and 4 git commands to generate.