+2011-03-14 Mike Frysinger <vapier@gentoo.org>
+
+ * callback.c, cgen-engine.h, dv-core.c, dv-glue.c, dv-pal.c,
+ hw-base.c, hw-device.c, hw-device.h, hw-handles.c, hw-instances.c,
+ hw-ports.c, hw-ports.h, hw-properties.c, hw-tree.c, nrun.c,
+ run-sim.h, run.c, sim-alu.h, sim-assert.h, sim-base.h, sim-basics.h,
+ sim-config.c, sim-core.c, sim-core.h, sim-engine.h, sim-events.c,
+ sim-events.h, sim-fpu.c, sim-hw.c, sim-inline.h, sim-load.c,
+ sim-memopt.c, sim-n-core.h, sim-options.c, sim-profile.c,
+ sim-signal.c, sim-trace.c, sim-trace.h, sim-utils.c, sim-watch.c,
+ syscall.c: Trim trailing whitespace.
+
2011-03-05 Mike Frysinger <vapier@gentoo.org>
* gennltvals.sh: Handle bfin targets.
/* Set the callback copy of errno from what we see now. */
-static int
+static int
wrap (p, val)
host_callback *p;
int val;
/* Make sure the FD provided is ok. If not, return non-zero
and set errno. */
-static int
+static int
fdbad (p, fd)
host_callback *p;
int fd;
return 0;
}
-static int
+static int
fdmap (p, fd)
host_callback *p;
int fd;
return p->fdmap[fd];
}
-static int
+static int
os_close (p, fd)
host_callback *p;
int fd;
{
return 1;
}
- else
+ else
{
sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
}
#define os_poll_quit 0
#endif /* defined(__GO32__) || defined(_MSC_VER) */
-static int
+static int
os_get_errno (p)
host_callback *p;
{
}
-static int
+static int
os_isatty (p, fd)
host_callback *p;
int fd;
return result;
}
-static int
+static int
os_lseek (p, fd, off, way)
host_callback *p;
int fd;
return result;
}
-static int
+static int
os_open (p, name, flags)
host_callback *p;
const char *name;
return -1;
}
-static int
+static int
os_read (p, fd, buf, len)
host_callback *p;
int fd;
return result;
}
-static int
+static int
os_read_stdin (p, buf, len)
host_callback *p;
char *buf;
return wrap (p, read (0, buf, len));
}
-static int
+static int
os_write (p, fd, buf, len)
host_callback *p;
int fd;
return result;
}
-static int
+static int
os_write_stdout (p, buf, len)
host_callback *p ATTRIBUTE_UNUSED;
const char *buf;
fflush (stdout);
}
-static int
+static int
os_write_stderr (p, buf, len)
host_callback *p ATTRIBUTE_UNUSED;
const char *buf;
fflush (stderr);
}
-static int
+static int
os_rename (p, f1, f2)
host_callback *p;
const char *f1;
return wrap (p, system (s));
}
-static long
+static long
os_time (p, t)
host_callback *p;
long *t;
}
-static int
+static int
os_unlink (p, f1)
host_callback *p;
const char *f1;
#endif
}
-static int
+static int
os_ftruncate (p, fd, len)
host_callback *p;
int fd;
0, /* open_map */
0, /* signal_map */
0, /* stat_map */
-
+
/* Defaults expected to be overridden at initialization, where needed. */
BFD_ENDIAN_UNKNOWN, /* target_endian */
4, /* target_sizeof_int */
#ifdef __GNUC__
#define SEM_SET_FULL_CODE(abuf, idesc) \
do { (abuf)->semantic.sem_case = (idesc)->sem_full_lab; } while (0)
-#else
+#else
#define SEM_SET_FULL_CODE(abuf, idesc) \
do { (abuf)->semantic.sem_case = (idesc)->num; } while (0)
#endif
#ifdef __GNUC__
#define SEM_SET_FAST_CODE(abuf, idesc) \
do { (abuf)->semantic.sem_case = (idesc)->sem_fast_lab; } while (0)
-#else
+#else
#define SEM_SET_FAST_CODE(abuf, idesc) \
do { (abuf)->semantic.sem_case = (idesc)->num; } while (0)
#endif
#include "hw-main.h"
/* DEVICE
-
+
core - root of the device tree
-
+
DESCRIPTION
-
+
The core device, positioned at the root of the device tree appears
to its child devices as a normal device just like every other
device in the tree.
#endif
/* DEVICE
-
+
glue - glue to interconnect and test hardware ports
-
+
DESCRIPTION
-
+
The glue device provides two functions. Firstly, it provides a
mechanism for inspecting and driving the port network. Secondly,
PROPERTIES
-
+
reg = <address> <size> (required)
PORTS
-
+
int[0..] (input, output)
Both an input and an output port.
| write_string("AND is ");
| write_int(ans);
| write_line();
-
+
BUGS
-
+
A future implementation of this device may support multiple
interrupt ranges.
hw_glue_finish (struct hw *me)
{
struct hw_glue *glue = HW_ZALLOC (me, struct hw_glue);
-
+
/* establish our own methods */
set_hw_data (me, glue);
set_hw_io_read_buffer (me, hw_glue_io_read_buffer);
/* attach to our parent bus */
do_hw_attach_regs (me);
-
+
/* establish the output registers */
{
reg_property_spec unit;
glue->nr_outputs = glue->sizeof_output / sizeof (unsigned_word);
glue->output = hw_zalloc (me, glue->sizeof_output);
}
-
+
/* establish the input ports */
{
const struct hw_property *ranges;
glue->sizeof_input = glue->nr_inputs * sizeof (unsigned);
glue->input = hw_zalloc (me, glue->sizeof_input);
}
-
+
/* determine our type */
{
const char *name = hw_name(me);
else
hw_abort (me, "unimplemented glue type");
}
-
+
HW_TRACE ((me, "int-number %d, nr_inputs %d, nr_outputs %d",
glue->int_number, glue->nr_inputs, glue->nr_outputs));
}
/* DEVICE
-
+
pal - glue logic device containing assorted junk
-
+
DESCRIPTION
-
+
Typical hardware dependant hack. This device allows the firmware
to gain access to all the things the firmware needs (but the OS
doesn't).
RESET (write): halts the simulator. The value written to the
register is used as an exit status.
-
+
PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
the processor performing the read.
-
+
INTERRUPT (write): This register must be written using a two byte
store. The low byte specifies a port and the upper byte specifies
the a level. LEVEL is driven on the specified port. By
PROPERTIES
-
+
reg = <address> <size> (required)
{
hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me);
unsigned_1 *byte = (unsigned_1 *) source;
-
+
switch (addr & hw_pal_address_mask)
{
do_counter_write (me, hw_pal, "countdown",
&hw_pal->countdown, source, nr_bytes);
break;
-
+
case hw_pal_timer:
do_counter_write (me, hw_pal, "timer",
&hw_pal->timer, source, nr_bytes);
break;
-
+
}
return nr_bytes;
}
strcat (buf, hw_name (leaf));
strcat (buf, unit);
}
-
+
/* return it usefully */
if (buf == full_name)
buf = hw_strdup (leaf, full_name);
root = root->parent_of_hw;
hw->root_of_hw = root;
}
-
+
/* a unique identifier for the device on the parents bus */
if (parent != NULL)
{
create_hw_event_data (hw);
create_hw_handle_data (hw);
create_hw_instance_data (hw);
-
+
return hw;
}
&& hw_find_property (hw_root (me), "global-trace?") != NULL
&& hw_find_boolean_property (hw_root (me), "global-trace?"))
me->trace_of_hw_p = 1;
-
+
/* Allow the real device to override any methods */
me->base_of_hw->descriptor->to_finish (me);
va_end(ap);
return status;
}
-
+
char *
hw_strdup (struct hw *me, const char *str)
{
const hw_unit *unit,
char *encoded,
int sizeof_buf);
-
+
#define hw_unit_encode(bus, unit, encoded, sizeof_encoded) \
((bus)->to_unit_encode (bus, unit, encoded, sizeof_encoded))
struct hw_instance *internal)
{
struct hw_handle_data *db = hw->handles_of_hw;
- if (hw_handle_2ihandle (hw, internal) != 0)
+ if (hw_handle_2ihandle (hw, internal) != 0)
{
hw_abort (hw, "attempting to add an ihandle already in the data base");
}
struct hw *internal)
{
struct hw_handle_data *db = hw->handles_of_hw;
- if (hw_handle_2phandle (hw, internal) != 0)
+ if (hw_handle_2phandle (hw, internal) != 0)
{
hw_abort (hw, "attempting to add a phandle already in the data base");
}
}
hw_abort (hw, "attempt to remove nonexistant phandle");
}
-
-
hw_instance_call_method (struct hw_instance *instance,
const char *method_name,
int n_stack_args,
- unsigned_cell stack_args[/*n_stack_args*/],
+ unsigned_cell stack_args[/*n_stack_args*/],
int n_stack_returns,
unsigned_cell stack_returns[/*n_stack_args*/])
{
{
const struct hw_port_descriptor *ports =
me->ports_of_hw->ports;
- if (ports != NULL)
+ if (ports != NULL)
{
while (ports->name != NULL)
{
struct hw_port_descriptor {
const char *name;
- int number;
+ int number;
int nr_ports;
port_direction direction;
};
(struct hw *me,
hw_port_traverse_function *handler,
void *data);
-
+
/* DESTINATION is attached (detached) to LINE of the device ME
char *buf,
int sizeof_buf,
port_direction direction);
-
+
#endif
{
struct hw_property_data *new_entry = NULL;
struct hw_property *new_value = NULL;
-
+
/* find the list end */
struct hw_property_data **insertion_point = &me->properties_of_hw;
while (*insertion_point != NULL)
return;
insertion_point = &(*insertion_point)->next;
}
-
+
/* create a new value */
new_value = HW_ZALLOC (me, struct hw_property);
new_value->name = (char *) strdup (property);
new_value->owner = me;
new_value->original = original;
new_value->disposition = disposition;
-
+
/* insert the value into the list */
new_entry = HW_ZALLOC (me, struct hw_property_data);
*insertion_point = new_entry;
cells = H2BE_cell (hw_instance_to_external (ihandle));
hw_set_property (me, property, ihandle_property,
&cells, sizeof (cells));
-
+
}
#endif
int sizeof_integer = sizeof (*integer);
signed_cell *cell;
HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
-
+
/* check things sane */
node = hw_find_property (me, property);
if (node == NULL)
hw_abort (me, "property \"%s\" contains an incomplete number of cells", property);
if (node->sizeof_array <= sizeof_integer * index)
return 0;
-
+
/* Find and convert the value */
cell = ((signed_cell*)node->array) + index;
*integer = BE2H_cell (*cell);
-
+
return node->sizeof_array / sizeof_integer;
}
unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
unsigned_cell *cell;
int i;
-
+
/* copy the property elements over */
cell = cells;
for (i = 0; i < nr_ranges; i++)
cell = unit_address_to_cells (&range->child_address, cell,
hw_unit_nr_address_cells (me));
/* copy the parent address */
- cell = unit_address_to_cells (&range->parent_address, cell,
+ cell = unit_address_to_cells (&range->parent_address, cell,
hw_unit_nr_address_cells (hw_parent (me)));
/* copy the size */
- cell = unit_address_to_cells (&range->size, cell,
+ cell = unit_address_to_cells (&range->size, cell,
hw_unit_nr_size_cells (me));
}
ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]);
-
+
/* add it */
hw_add_property (me, property, range_array_property,
cells, sizeof_cells,
cells, sizeof_cells,
NULL, permenant_object);
-
+
hw_free (me, cells);
}
unsigned sizeof_entry = (nr_range_property_cells (me, 1)
* sizeof (unsigned_cell));
const unsigned_cell *cells;
-
+
/* locate the property */
node = hw_find_property (me, property);
if (node == NULL)
hw_abort (me, "property \"%s\" not found", property);
if (node->type != range_array_property)
hw_abort (me, "property \"%s\" of wrong type (range array)", property);
-
+
/* aligned ? */
if ((node->sizeof_array % sizeof_entry) != 0)
hw_abort (me, "property \"%s\" contains an incomplete number of entries",
property);
-
+
/* within bounds? */
if (node->sizeof_array < sizeof_entry * (index + 1))
return 0;
-
+
/* find the range of interest */
cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
-
+
/* copy the child address out - converting as we go */
cells = cells_to_unit_address (cells, &range->child_address,
hw_unit_nr_address_cells (me));
-
+
/* copy the parent address out - converting as we go */
cells = cells_to_unit_address (cells, &range->parent_address,
hw_unit_nr_address_cells (hw_parent (me)));
-
+
/* copy the size - converting as we go */
cells = cells_to_unit_address (cells, &range->size,
hw_unit_nr_size_cells (me));
-
+
return node->sizeof_array / sizeof_entry;
}
unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
unsigned_cell *cell;
int i;
-
+
/* copy the property elements over */
cell = cells;
for (i = 0; i < nr_regs; i++)
hw_unit_nr_size_cells (hw_parent (me)));
}
ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]);
-
+
/* add it */
hw_add_property (me, property, reg_array_property,
cells, sizeof_cells,
cells, sizeof_cells,
NULL, permenant_object);
-
+
hw_free (me, cells);
}
unsigned sizeof_entry = (nr_reg_property_cells (me, 1)
* sizeof (unsigned_cell));
const unsigned_cell *cells;
-
+
/* locate the property */
node = hw_find_property (me, property);
if (node == NULL)
hw_abort (me, "property \"%s\" not found", property);
if (node->type != reg_array_property)
hw_abort (me, "property \"%s\" of wrong type (reg array)", property);
-
+
/* aligned ? */
if ((node->sizeof_array % sizeof_entry) != 0)
hw_abort (me, "property \"%s\" contains an incomplete number of entries",
property);
-
+
/* within bounds? */
if (node->sizeof_array < sizeof_entry * (index + 1))
return 0;
-
+
/* find the range of interest */
cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
-
+
/* copy the address out - converting as we go */
cells = cells_to_unit_address (cells, ®->address,
hw_unit_nr_address_cells (hw_parent (me)));
-
+
/* copy the size out - converting as we go */
cells = cells_to_unit_address (cells, ®->size,
hw_unit_nr_size_cells (hw_parent (me)));
-
+
return node->sizeof_array / sizeof_entry;
}
/* manipulate/lookup device names */
typedef struct _name_specifier {
-
+
/* components in the full length name */
char *path;
char *property;
char *value;
-
+
/* current device */
char *family;
char *name;
char *unit;
char *args;
-
+
/* previous device */
char *last_name;
char *last_family;
char *last_unit;
char *last_args;
-
+
/* work area */
char buf[1024];
-
+
} name_specifier;
name_specifier *spec)
{
char *chp = NULL;
-
+
/* expand any leading alias if present */
if (current != NULL
&& *device_specifier != '\0'
{
strcpy(spec->buf, device_specifier);
}
-
+
/* check no overflow */
if (strlen(spec->buf) >= sizeof(spec->buf))
hw_abort (NULL, "split_device_specifier: buffer overflow\n");
-
+
/* strip leading spaces */
chp = spec->buf;
while (*chp != '\0' && isspace(*chp))
chp++;
if (*chp == '\0')
return 0;
-
+
/* find the path and terminate it with null */
spec->path = chp;
while (*chp != '\0' && !isspace(*chp))
*chp = '\0';
chp++;
}
-
+
/* and any value */
while (*chp != '\0' && isspace(*chp))
chp++;
spec->value = chp;
-
+
/* now go back and chop the property off of the path */
if (spec->value[0] == '\0')
{
spec->property = chp+1;
}
}
-
+
/* and mark the rest as invalid */
spec->name = NULL;
spec->family = NULL;
spec->last_family = NULL;
spec->last_unit = NULL;
spec->last_args = NULL;
-
+
return 1;
}
chp = strchr (spec->name, '/');
if (chp == NULL)
spec->path = strchr (spec->name, '\0');
- else
+ else
{
spec->path = chp+1;
*chp = '\0';
else
break;
}
-
+
/* now go through the path proper */
-
+
if (current == NULL)
{
split_device_name (spec);
return NULL;
}
-
+
while (split_device_name (spec))
{
struct hw *child;
return current; /* search failed */
current = child;
}
-
+
return current;
}
/* break it up */
if (!split_device_specifier (current, device_specifier, spec))
hw_abort (current, "error parsing %s\n", device_specifier);
-
+
/* fill our tree with its contents */
current = split_find_device (current, spec);
-
+
/* add any additional devices as needed */
if (spec->name != NULL)
{
}
while (split_device_name (spec));
}
-
+
return current;
}
int reg_nr;
reg_property_spec *regs;
const char *chp;
-
+
/* determine the number of reg entries by counting tokens */
nr_regs = count_entries (current, property_name, property_value, 2);
-
+
/* create working space */
regs = zalloc (nr_regs * sizeof (*regs));
-
+
/* fill it in */
chp = property_value;
for (reg_nr = 0; reg_nr < nr_regs; reg_nr++)
chp = parse_size (current, hw_parent(current),
chp, ®s[reg_nr].size);
}
-
+
/* create it */
hw_add_reg_array_property (current, property_name,
regs, nr_regs);
-
+
free (regs);
}
int range_nr;
range_property_spec *ranges;
const char *chp;
-
+
/* determine the number of ranges specified */
nr_ranges = count_entries (current, property_name, property_value, 3);
-
+
/* create a property of that size */
ranges = zalloc (nr_ranges * sizeof(*ranges));
-
+
/* fill it in */
chp = property_value;
for (range_nr = 0; range_nr < nr_ranges; range_nr++)
chp = parse_size (current, current,
chp, &ranges[range_nr].size);
}
-
+
/* create it */
hw_add_range_array_property (current, property_name, ranges, nr_ranges);
-
+
free (ranges);
}
const char *chp;
int nr_strings;
int approx_nr_strings;
-
+
/* get an estimate as to the number of strings by counting double
quotes */
approx_nr_strings = 2;
approx_nr_strings++;
}
approx_nr_strings = (approx_nr_strings) / 2;
-
+
/* create a string buffer for that many (plus a null) */
strings = (char**) zalloc ((approx_nr_strings + 1) * sizeof(char*));
-
+
/* now find all the strings */
chp = property_value;
nr_strings = 0;
while (1)
{
-
+
/* skip leading space */
while (*chp != '\0' && isspace (*chp))
chp += 1;
if (*chp == '\0')
break;
-
+
/* copy it in */
if (*chp == '"')
{
property_name);
}
ASSERT (strings[nr_strings] == NULL); /* from zalloc */
-
+
/* install it */
if (nr_strings == 0)
hw_add_string_property (current, property_name, "");
hw_add_string_array_property (current, property_name,
specs, nr_strings);
}
-
+
/* flush the created string */
while (nr_strings > 0)
{
const char *value)
{
ihandle_runtime_property_spec ihandle;
-
+
/* pass the full path */
ihandle.full_path = value;
-
+
/* save this ready for the ihandle create */
hw_add_ihandle_runtime_property (current, property,
&ihandle);
va_end (ap);
return current;
}
-
+
struct hw *
hw_tree_vparse (struct hw *current,
const char *fmt,
{
char device_specifier[1024];
name_specifier spec;
-
+
/* format the path */
vsprintf (device_specifier, fmt, ap);
if (strlen (device_specifier) >= sizeof (device_specifier))
hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n");
-
+
/* construct the tree down to the final struct hw */
current = split_fill_path (current, device_specifier, &spec);
-
+
/* is there an interrupt spec */
if (spec.property == NULL
&& spec.value != NULL)
break;
}
}
-
+
/* is there a property */
if (spec.property != NULL)
{
if (property->original != NULL)
{
p->print (p->file, " !");
- p->print (p->file, "%s/%s",
+ p->print (p->file, "%s/%s",
hw_path (property->original->owner),
property->original->name);
}
{
struct hw *node;
name_specifier spec;
-
+
/* parse the path */
split_device_specifier (root, path_to_device, &spec);
if (spec.value != NULL)
return NULL; /* something wierd */
-
+
/* now find it */
node = split_find_device (root, &spec);
if (spec.name != NULL)
return NULL; /* not a leaf */
-
+
return node;
}
prog_bfd = bfd_openr (name, 0);
if (prog_bfd == NULL)
{
- fprintf (stderr, "%s: can't open \"%s\": %s\n",
+ fprintf (stderr, "%s: can't open \"%s\": %s\n",
myname, name, bfd_errmsg (bfd_get_error ()));
exit (1);
}
- if (!bfd_check_format (prog_bfd, bfd_object))
+ if (!bfd_check_format (prog_bfd, bfd_object))
{
fprintf (stderr, "%s: \"%s\" is not an object file: %s\n",
myname, name, bfd_errmsg (bfd_get_error ()));
/* remain on breakpoint or signals in oe mode*/
while (((reason == sim_signalled) &&
(sigrc == sim_signal_to_host (sd, SIM_SIGTRAP))) ||
- ((reason == sim_stopped) &&
+ ((reason == sim_stopped) &&
(STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)));
}
- else
+ else
{
do
{
sim_resume (sd, 0, sigrc);
signal (SIGINT, prev_sigint);
sim_stop_reason (sd, &reason, &sigrc);
-
+
if ((reason == sim_stopped) &&
(sigrc == sim_signal_to_host (sd, SIM_SIGINT)))
break; /* exit on control-C */
-
+
/* remain on signals in oe mode */
} while ((reason == sim_stopped) &&
(STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT));
-
+
}
/* Print any stats the simulator collected. */
if (STATE_VERBOSE_P (sd))
sim_info (sd, 0);
-
+
/* Shutdown the simulator. */
sim_close (sd, 0);
-
+
/* If reason is sim_exited, then sigrc holds the exit code which we want
to return. If reason is sim_stopped or sim_signalled, then sigrc holds
the signal that the simulator received; we want to return that to
indicate failure. */
-
+
/* Why did we stop? */
switch (reason)
{
/* This file defines the part of the interface between the standalone
simaulator program - run - and simulator library - libsim.a - that
is not used by GDB. The GDB part is described in include/remote-sim.h.
-
+
Copyright 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GDB.
exit (help ? 0 : 1);
}
-static void
+static void
print_version ()
{
printf ("GNU simulator %s%s\n", PKGVERSION, version);
if (ALU16_HAD_OVERFLOW) \
sim_engine_halt (...); \
(RES) = ALU16_OVERFLOW_RESULT
-
+
ALU*_HAD_CARRY_BORROW: Returns a nonzero value if unsigned
overflow or underflow (also referred to as carry and borrow)
occurred.
#define ALU64_END(RES) \
State.carry = ALU64_HAD_CARRY_BORROW; \
(RES) = ALU64_CARRY_BORROW_RESULT
-
-
+
+
Addition:
ALU*_ADD(VAL): Add VAL to the ALU accumulator. Record any
/* Twos complement arithmetic - addition/subtraction - carry/borrow
(or you thought you knew the answer to 0-0)
-
+
Notation and Properties:
UMAXn: The upper bound of an unsigned N bit value (the lower
bound is always zero).
- Un: UMAXn + 1. Unsigned arithmetic is computed `modulo (Un)'.
+ Un: UMAXn + 1. Unsigned arithmetic is computed `modulo (Un)'.
X[p]: Is bit P of X. X[0] denotes the least significant bit.
The two N bit operands are sign extended to M>N bits and then
added. Overflow occurs when SIGN_BIT<n> and SIGN_BIT<m> do not
match.
-
+
Rm = (SEXTn (Xn) + SEXTn (Yn))
V = MSBn ((Rm >> (M - N)) ^ Rm)
The following table lists the output for all given inputs into a
full-adder.
-
+
I X Y R | C
------------+---
0 0 0 0 | 0
XY\R 0 1
+-------
- 00 | 0 0
+ 00 | 0 0
01 | 1 0
11 | 1 1
10 | 1 0
Verifying:
- I X Y R | C | X&Y X&~R Y&~R
+ I X Y R | C | X&Y X&~R Y&~R
------------+---+---------------
0 0 0 0 | 0 | 0 0 0
0 0 1 1 | 0 | 0 0 0
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-
+
*/
CIA_ADDR to return the integral value. *-/
/-* #define CIA_ADDR(cia) (...) *-/
#include "sim-base.h"
-
+
finally, two data types `struct _sim_cpu' and `struct sim_state'
are defined:
#endif
-
+
/* Some versions of GCC include an attribute operator, define it */
#if !defined (__attribute__)
config_stdio_to_a (current_stdio));
return SIM_RC_FAIL;
}
-
-
+
+
/* check the value of MSB */
if (WITH_TARGET_WORD_MSB != 0
&& WITH_TARGET_WORD_MSB != (WITH_TARGET_WORD_BITSIZE - 1))
WITH_TARGET_WORD_BITSIZE, WITH_TARGET_WORD_MSB);
return SIM_RC_FAIL;
}
-
-
+
+
/* set the environment */
#if (WITH_TREE_PROPERTIES)
if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
#endif
if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
STATE_ENVIRONMENT (sd) = DEFAULT_ENVIRONMENT;
-
-
+
+
/* set the alignment */
#if (WITH_TREE_PROPERTIES)
if (current_alignment == 0)
current_alignment = WITH_ALIGNMENT;
if (current_alignment == 0)
current_alignment = WITH_DEFAULT_ALIGNMENT;
-
+
/* verify the alignment */
if (CURRENT_ALIGNMENT == 0)
{
config_alignment_to_a (current_alignment));
return SIM_RC_FAIL;
}
-
+
#if defined (WITH_FLOATING_POINT)
-
+
/* set the floating point */
if (current_floating_point == 0)
current_floating_point = WITH_FLOATING_POINT;
-
+
/* verify the floating point */
if (CURRENT_FLOATING_POINT == 0)
{
config_alignment_to_a (current_floating_point));
return SIM_RC_FAIL;
}
-
+
#endif
return SIM_RC_OK;
}
#if defined (WITH_RESERVED_BITS)
sim_io_printf (sd, "WITH_RESERVED_BITS = %d\n", WITH_RESERVED_BITS);
#endif
-
+
#if defined (WITH_PROFILE)
sim_io_printf (sd, "WITH_PROFILE = %d\n", WITH_PROFILE);
#endif
-
+
}
last_mapping = &next_mapping->next;
next_mapping = next_mapping->next;
}
-
+
/* check insertion point correct */
SIM_ASSERT (next_mapping == NULL || next_mapping->level >= level);
if (next_mapping != NULL && next_mapping->level == level
}
/* attach the region to all applicable access maps */
- for (map = 0;
+ for (map = 0;
map < nr_maps;
map++)
{
free_buffer = NULL;
}
}
-
+
/* Just copy this map to each of the processor specific data structures.
FIXME - later this will be replaced by true processor specific
maps. */
(unsigned_1*)buffer + count,
mapping->space,
raddr,
- nr_bytes,
+ nr_bytes,
sd,
- cpu,
+ cpu,
cia) != nr_bytes)
break;
count += nr_bytes;
raddr,
nr_bytes,
sd,
- cpu,
+ cpu,
cia) != nr_bytes)
break;
count += nr_bytes;
core->byte_xor = WITH_XOR_ENDIAN - 1;
else
core->byte_xor = 0;
- }
+ }
}
}
else {
}
}
#endif
-
-
+
+
#if EXTERN_SIM_CORE_P
unsigned
sim_core_xor_write_buffer (SIM_DESC sd,
DECLARE_SIM_CORE_WRITE_N(aligned,8,8)
DECLARE_SIM_CORE_WRITE_N(aligned,16,16)
-#define sim_core_write_unaligned_1 sim_core_write_aligned_1
+#define sim_core_write_unaligned_1 sim_core_write_aligned_1
DECLARE_SIM_CORE_WRITE_N(unaligned,2,2)
DECLARE_SIM_CORE_WRITE_N(unaligned,4,4)
DECLARE_SIM_CORE_WRITE_N(unaligned,8,8)
if ((LAST_CPU) != NULL) CIA_SET (LAST_CPU, CIA)
#endif
-/* NB: If a port uses the SIM_CPU_EXCEPTION_* hooks, the default
+/* NB: If a port uses the SIM_CPU_EXCEPTION_* hooks, the default
SIM_ENGINE_HALT_HOOK and SIM_ENGINE_RESUME_HOOK must not be used.
They conflict in that the PC set by the HALT_HOOK may overwrite the
proper one, as intended to be saved by the EXCEPTION_TRIGGER
watch_sim_le_2,
watch_sim_le_4,
watch_sim_le_8,
-
+
/* wallclock */
watch_clock,
/* The event queue maintains a single absolute time using two
variables.
-
+
TIME_OF_EVENT: this holds the time at which the next event is ment
to occur. If no next event it will hold the time of the last
event.
{
if (event == 0)
return 0;
-
+
return (event->time_of_event - sim_events_time (sd));
}
if (delta < 0)
sim_io_error (sd, "what is past is past!\n");
-
+
/* compute when the event should occur */
time_of_event = sim_events_time (sd) + delta;
-
+
/* find the queue insertion point - things are time ordered */
prev = &events->queue;
curr = events->queue;
curr = curr->next;
}
SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
-
+
/* insert it */
new_event->next = curr;
*prev = new_event;
new_event->time_of_event = time_of_event;
-
+
/* adjust the time until the first event */
update_time_from_event (sd);
}
sigfillset(&new_mask);
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
#endif
-
+
/* allocate an event entry from the signal buffer */
new_event = &events->held [events->nr_held];
events->nr_held ++;
sim_engine_abort (NULL, NULL, NULL_CIA,
"sim_events_schedule_after_signal - buffer oveflow");
}
-
+
new_event->data = data;
new_event->handler = handler;
new_event->time_of_event = delta_time; /* work it out later */
/*-UNLOCK-*/
sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif
-
+
ETRACE ((_ETRACE,
"signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
(long)sim_events_time(sd),
if (events->nr_held > 0)
{
int i;
-
+
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
/*-LOCK-*/
sigset_t old_mask;
entry->data);
}
events->nr_held = 0;
-
+
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
/*-UNLOCK-*/
sigprocmask(SIG_SETMASK, &old_mask, NULL);
#endif
-
+
}
-
+
/* Process any watchpoints. Be careful to allow a watchpoint to
appear/disappear under our feet.
To ensure that watchpoints are processed only once per cycle,
events->watchedpoints = to_do;
}
}
-
+
/* consume all events for this or earlier times. Be careful to
allow an event to appear/disappear under our feet */
while (events->queue->time_of_event <
sim_events_free (sd, to_do);
handler (sd, data);
}
-
+
/* put things back where they belong ready for the next iteration */
events->watchpoints = events->watchedpoints;
events->watchedpoints = NULL;
if (events->watchpoints != NULL)
events->work_pending = 1;
-
+
/* advance the time */
SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
SIM_ASSERT (events->queue != NULL); /* always poll event */
if (events-were-next)
next-cpu-nr = 0;
- .... // prime main loop
+ .... // prime main loop
while (1)
{
#include "sim-assert.h"
-/* Debugging support.
+/* Debugging support.
If digits is -1, then print all digits. */
static void
typedef union {
double d;
unsigned64 i;
-} sim_fpu_map;
+} sim_fpu_map;
/* A packed IEEE floating point number.
Zero (0 == BIASEDEXP && FRAC == 0):
(sign ? "-" : "+") 0.0
-
+
Infinity (BIASEDEXP == EXPMAX && FRAC == 0):
(sign ? "-" : "+") "infinity"
/* Infinity */
sign = src->sign;
exp = EXPMAX;
- fraction = 0;
+ fraction = 0;
}
else
{
(long) LSEXTRACTED32 (packed, 23 - 1, 0));
}
#endif
-
+
return packed;
}
f->sign = (i < 0);
f->normal_exp = NR_FRAC_GUARD;
- if (f->sign)
+ if (f->sign)
{
/* Special case for minint, since there is no corresponding
+ve integer representation for it */
if (f->fraction >= IMPLICIT_2)
{
- do
+ do
{
f->fraction = (f->fraction >> 1) | (f->fraction & 1);
f->normal_exp += 1;
return 0;
break;
case sim_fpu_class_snan:
- /* Quieten a SignalingNaN */
+ /* Quieten a SignalingNaN */
f->class = sim_fpu_class_qnan;
return sim_fpu_status_invalid_snan;
break;
res2 += ((ps_hh__ >> 32) & 0xffffffff) + pp_hh;
high = res2;
low = res0;
-
+
f->normal_exp = l->normal_exp + r->normal_exp;
f->sign = l->sign ^ r->sign;
f->class = sim_fpu_class_number;
/* Input is bounded by [1,2) ; [2^60,2^61)
Output is bounded by [1,4) ; [2^120,2^122) */
-
+
/* Adjust the exponent according to where the decimal point ended
up in the high 64 bit word. In the source the decimal point
was at NR_FRAC_GUARD. */
f->normal_exp--;
}
ASSERT (numerator >= denominator);
-
+
/* Gain extra precision, already used one spare bit */
numerator <<= NR_SPARE;
denominator <<= NR_SPARE;
}
ASSERT (l->sign == r->sign);
if (l->normal_exp > r->normal_exp
- || (l->normal_exp == r->normal_exp &&
+ || (l->normal_exp == r->normal_exp &&
l->fraction > r->fraction))
{
/* |l| > |r| */
}
ASSERT (l->sign == r->sign);
if (l->normal_exp > r->normal_exp
- || (l->normal_exp == r->normal_exp &&
+ || (l->normal_exp == r->normal_exp &&
l->fraction > r->fraction))
{
/* |l| > |r| */
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
+ * software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
-
+
/* __ieee754_sqrt(x)
* Return correctly rounded sqrt.
* ------------------------------------------
* | Use the hardware sqrt if you have one |
* ------------------------------------------
- * Method:
- * Bit by bit method using integer arithmetic. (Slow, but portable)
+ * Method:
+ * Bit by bit method using integer arithmetic. (Slow, but portable)
* 1. Normalization
- * Scale x to y in [1,4) with even powers of 2:
+ * Scale x to y in [1,4) with even powers of 2:
* find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
* sqrt(x) = 2^k * sqrt(y)
-
* i+1 2
* s = 2*q , and y = 2 * ( y - q ). (1)
* i i i i
- *
- * To compute q from q , one checks whether
- * i+1 i
+ *
+ * To compute q from q , one checks whether
+ * i+1 i
*
* -(i+1) 2
* (q + 2 ) <= y. (2)
* i+1 i i+1 i
*
* With some algebric manipulation, it is not difficult to see
- * that (2) is equivalent to
+ * that (2) is equivalent to
* -(i+1)
* s + 2 <= y (3)
* i i
*
- * The advantage of (3) is that s and y can be computed by
+ * The advantage of (3) is that s and y can be computed by
* i i
* the following recurrence formula:
* if (3) is false
* -i -(i+1)
* s = s + 2 , y = y - s - 2 (5)
* i+1 i i+1 i i
- *
+ *
-
- -(i+1)
- - NOTE: y = 2 (y - s - 2 )
+ - NOTE: y = 2 (y - s - 2 )
- i+1 i i
-
- * One may easily use induction to prove (4) and (5).
+ * One may easily use induction to prove (4) and (5).
* Note. Since the left hand side of (3) contain only i+2 bits,
- * it does not necessary to do a full (53-bit) comparison
+ * it does not necessary to do a full (53-bit) comparison
* in (3).
* 3. Final rounding
* After generating the 53 bits result, we compute one more bit.
* The rounding mode can be detected by checking whether
* huge + tiny is equal to huge, and whether huge - tiny is
* equal to huge for some floating point number "huge" and "tiny".
- *
+ *
* Special cases:
* sqrt(+-0) = +-0 ... exact
* sqrt(inf) = inf
b = IMPLICIT_1;
q = 0;
s = 0;
-
+
while (b)
{
unsigned64 t = s + b;
struct hw *current = STATE_HW (sd)->tree;
int line_nr;
char device_path[1000];
-
+
/* try opening the file */
description = fopen (file_name, "r");
if (description == NULL)
perror (file_name);
return SIM_RC_FAIL;
}
-
+
line_nr = 0;
while (fgets (device_path, sizeof(device_path), description))
{
sim_hw_print (sd, sim_io_vprintf);
return SIM_RC_OK;
}
-
+
case OPTION_HW_FILE:
{
return merge_device_file (sd, arg);
/* CPU: The simulation is running and the current CPU/CIA
initiates a data transfer. */
-void
+void
sim_cpu_hw_io_read_buffer (sim_cpu *cpu,
sim_cia cia,
struct hw *hw,
sim_engine_abort (sd, cpu, cia, "broken CPU read");
}
-void
+void
sim_cpu_hw_io_write_buffer (sim_cpu *cpu,
sim_cia cia,
struct hw *hw,
/* SYSTEM: A data transfer is being initiated by the system. */
-unsigned
+unsigned
sim_hw_io_read_buffer (struct sim_state *sd,
struct hw *hw,
void *dest,
Since no inlining is defined. All macro's get standard defaults
(extern, static, ...).
-
+
H_REVEALS_MODULE (alt includes our):
altprog.c defines ALTPROG_C and then includes sim-inline.c
sim-inline.c defines C_INLINE_C and then includes sim-inline.h
-
+
In sim-inline.h the expression `` defined (SIM_INLINE) && !
defined (OURPROG_C) && REVEAL_MODULE_P (OURPROG_INLINE) '' is
true so it defines *_OURPROG as static and EXTERN_OURPROG_P as
ourprog.c defines OURPROG_C and then includes sim-inline.c
sim-inline.c defines C_INLINE_C and then includes sim-inline.h
-
+
In sim-inline.h the term `` ! defined (OURPROG_C) '' is FALSE
so it defines *_OURPROG as non-static and EXTERN_OURPROG_P as
TRUE.
result_bfd = bfd_openr (prog, 0);
if (result_bfd == NULL)
{
- eprintf (callback, "%s: can't open \"%s\": %s\n",
+ eprintf (callback, "%s: can't open \"%s\": %s\n",
myname, prog, bfd_errmsg (bfd_get_error ()));
return NULL;
}
}
- if (!bfd_check_format (result_bfd, bfd_object))
+ if (!bfd_check_format (result_bfd, bfd_object))
{
eprintf (callback, "%s: \"%s\" is not an object file: %s\n",
myname, prog, bfd_errmsg (bfd_get_error ()));
start_time = time (NULL);
found_loadable_section = 0;
- for (s = result_bfd->sections; s; s = s->next)
+ for (s = result_bfd->sections; s; s = s->next)
{
- if (s->flags & SEC_LOAD)
+ if (s->flags & SEC_LOAD)
{
bfd_size_type size;
if (mmap_next_fd >= 0)
{
/* Some kernels will SIGBUS the application if mmap'd file
- is not large enough. */
+ is not large enough. */
if (s.st_size < bytes)
{
sim_io_error (sd,
strerror(errno));
}
}
-#endif
+#endif
- /* Need heap allocation? */
+ /* Need heap allocation? */
if (free_buffer == NULL)
{
/* If filling with non-zero value, do not use clearing allocator. */
parse_addr (arg, &level, &space, &addr);
return do_memopt_delete (sd, level, space, addr);
}
-
+
case OPTION_MEMORY_REGION:
{
char *chp = arg;
}
#endif
-
+
/* TAGS: sim_core_read_aligned_1 sim_core_read_aligned_2 */
/* TAGS: sim_core_read_aligned_4 sim_core_read_aligned_8 */
/* TAGS: sim_core_read_aligned_16 */
return val;
}
#endif
-
+
/* TAGS: sim_core_read_unaligned_1 sim_core_read_unaligned_2 */
/* TAGS: sim_core_read_unaligned_4 sim_core_read_unaligned_8 */
/* TAGS: sim_core_read_unaligned_16 */
arg_table[hash] = arg;
return 0;
}
-
+
/* Called by sim_open to parse the arguments. */
SIM_RC
}
}
}
-
+
/* Terminate the short and long option lists. */
*p = 0;
lp->name = NULL;
}
while (OPTION_VALID_P (o) && o->doc == NULL);
}
-
+
/* list any long options (aliases) for the current OPT */
o = opt;
do
/* something to do? */
if (cmd == NULL)
return SIM_RC_OK; /* FIXME - perhaps help would be better */
-
+
if (cmd [0] == '-')
{
/* user specified -<opt> ... form? */
freeargv (argv);
}
-
+
/* didn't find anything that remotly matched */
return SIM_RC_FAIL;
}
}
}
}
- }
+ }
return SIM_RC_OK;
}
{
PROFILE_PC_START (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = base;
PROFILE_PC_END (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = bound;
- }
+ }
for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr)
CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1;
}
PROFILE_PC_COUNT (profile) [i] += 1; /* Overflow? */
else
PROFILE_PC_COUNT (profile) [PROFILE_PC_NR_BUCKETS (profile)] += 1;
- PROFILE_PC_EVENT (profile) =
+ PROFILE_PC_EVENT (profile) =
sim_events_schedule (sd, PROFILE_PC_FREQ (profile), profile_pc_event, cpu);
}
/* FIXME: Is this the best place for this code? */
{
FILE *pf = fopen ("gmon.out", "wb");
-
+
if (pf == NULL)
sim_io_eprintf (sd, "Failed to open \"gmon.out\" profile file\n");
else
#endif
}
-enum target_signal
+enum target_signal
sim_signal_to_target (SIM_DESC sd, SIM_SIGNAL sig)
{
switch (sig)
}
}
}
- }
+ }
return SIM_RC_OK;
}
abort ();
}
}
-
+
static const char *
trace_idx_to_str (int trace_idx)
{
save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result0 (SIM_DESC sd,
last_input = TRACE_INPUT_IDX (data);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_word2 (SIM_DESC sd,
save_data (sd, data, trace_fmt_word, sizeof (r1), &r1);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_word4 (SIM_DESC sd,
save_data (sd, data, trace_fmt_word, sizeof (r3), &r3);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_bool1 (SIM_DESC sd,
save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_addr1 (SIM_DESC sd,
save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_fp1 (SIM_DESC sd,
save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_fp2 (SIM_DESC sd,
save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_fpu1 (SIM_DESC sd,
save_data (sd, data, trace_fmt_fp, sizeof (double), &d);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_string1 (SIM_DESC sd,
save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
void
trace_result_word1_string1 (SIM_DESC sd,
save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0);
trace_results (sd, cpu, trace_idx, last_input);
-}
+}
\f
void
trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
if (TRACE_ALU_P (CPU)) \
trace_input0 (SD, CPU, TRACE_ALU_IDX); \
} while (0)
-
+
#define TRACE_ALU_INPUT1(V0) \
do { \
if (TRACE_ALU_P (CPU)) \
if (TRACE_FPU_P (CPU)) \
trace_input0 (SD, CPU, TRACE_FPU_IDX); \
} while (0)
-
+
#define TRACE_FP_INPUT1(V0) \
do { \
if (TRACE_FPU_P (CPU)) \
if (TRACE_FPU_P (CPU)) \
trace_input_word1 (SD, CPU, TRACE_FPU_IDX, (V0)); \
} while (0)
-
+
#define TRACE_FP_RESULT(R0) \
do { \
if (TRACE_FPU_P (CPU)) \
prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd));
if (prog_bfd == NULL)
{
- sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n",
+ sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n",
STATE_MY_NAME (sd),
prog_name,
bfd_errmsg (bfd_get_error ()));
return SIM_RC_FAIL;
}
- if (!bfd_check_format (prog_bfd, bfd_object))
+ if (!bfd_check_format (prog_bfd, bfd_object))
{
sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n",
STATE_MY_NAME (sd),
default: return "(error)";
}
}
-
-
sim_io_printf (sd, "\n");
}
}
-
+
static sim_event_handler handle_watchpoint;
schedule_watchpoint (sd, point);
else
do_watchpoint_delete (sd, point->ident, invalid_watchpoint);
-
+
if (point->interrupt_nr == watch->nr_interrupts)
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
else
break;
arg++;
}
-
+
(*point)->arg0 = strtoul (arg, &arg, 0);
if (arg[0] == ',')
(*point)->arg0 = strtoul (arg, NULL, 0);
else
switch (opt)
{
-
+
case OPTION_WATCH_DELETE:
if (isdigit ((int) arg[0]))
{
}
sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg);
return SIM_RC_FAIL;
-
+
case OPTION_WATCH_INFO:
{
do_watchpoint_info (sd);
return SIM_RC_OK;
}
-
+
default:
sim_io_eprintf (sd, "Unknown watch option %d\n", opt);
return SIM_RC_FAIL;
-
+
}
-
+
}
path name along with the syscall request, and cache the file
name somewhere (or otherwise tweak this as desired). */
unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
-
+
if (count != 1)
return EINVAL;
if (*p == 0)