/* Prologue value handling for GDB.
   Copyright 2003-2005, 2007-2012 Free Software Foundation, Inc.

   This file is part of GDB.

   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 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   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, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "gdb_string.h"
#include "gdb_assert.h"
#include "prologue-value.h"
#include "regcache.h"


/* Constructors.  */

pv_t
pv_unknown (void)
{
  pv_t v = { pvk_unknown, 0, 0 };

  return v;
}


pv_t
pv_constant (CORE_ADDR k)
{
  pv_t v;

  v.kind = pvk_constant;
  v.reg = -1;                   /* for debugging */
  v.k = k;

  return v;
}


pv_t
pv_register (int reg, CORE_ADDR k)
{
  pv_t v;

  v.kind = pvk_register;
  v.reg = reg;
  v.k = k;

  return v;
}



/* Arithmetic operations.  */

/* If one of *A and *B is a constant, and the other isn't, swap the
   values as necessary to ensure that *B is the constant.  This can
   reduce the number of cases we need to analyze in the functions
   below.  */
static void
constant_last (pv_t *a, pv_t *b)
{
  if (a->kind == pvk_constant
      && b->kind != pvk_constant)
    {
      pv_t temp = *a;
      *a = *b;
      *b = temp;
    }
}


pv_t
pv_add (pv_t a, pv_t b)
{
  constant_last (&a, &b);

  /* We can add a constant to a register.  */
  if (a.kind == pvk_register
      && b.kind == pvk_constant)
    return pv_register (a.reg, a.k + b.k);

  /* We can add a constant to another constant.  */
  else if (a.kind == pvk_constant
           && b.kind == pvk_constant)
    return pv_constant (a.k + b.k);

  /* Anything else we don't know how to add.  We don't have a
     representation for, say, the sum of two registers, or a multiple
     of a register's value (adding a register to itself).  */
  else
    return pv_unknown ();
}


pv_t
pv_add_constant (pv_t v, CORE_ADDR k)
{
  /* Rather than thinking of all the cases we can and can't handle,
     we'll just let pv_add take care of that for us.  */
  return pv_add (v, pv_constant (k));
}


pv_t
pv_subtract (pv_t a, pv_t b)
{
  /* This isn't quite the same as negating B and adding it to A, since
     we don't have a representation for the negation of anything but a
     constant.  For example, we can't negate { pvk_register, R1, 10 },
     but we do know that { pvk_register, R1, 10 } minus { pvk_register,
     R1, 5 } is { pvk_constant, <ignored>, 5 }.

     This means, for example, that we could subtract two stack
     addresses; they're both relative to the original SP.  Since the
     frame pointer is set based on the SP, its value will be the
     original SP plus some constant (probably zero), so we can use its
     value just fine, too.  */

  constant_last (&a, &b);

  /* We can subtract two constants.  */
  if (a.kind == pvk_constant
      && b.kind == pvk_constant)
    return pv_constant (a.k - b.k);

  /* We can subtract a constant from a register.  */
  else if (a.kind == pvk_register
           && b.kind == pvk_constant)
    return pv_register (a.reg, a.k - b.k);

  /* We can subtract a register from itself, yielding a constant.  */
  else if (a.kind == pvk_register
           && b.kind == pvk_register
           && a.reg == b.reg)
    return pv_constant (a.k - b.k);

  /* We don't know how to subtract anything else.  */
  else
    return pv_unknown ();
}


pv_t
pv_logical_and (pv_t a, pv_t b)
{
  constant_last (&a, &b);

  /* We can 'and' two constants.  */
  if (a.kind == pvk_constant
      && b.kind == pvk_constant)
    return pv_constant (a.k & b.k);

  /* We can 'and' anything with the constant zero.  */
  else if (b.kind == pvk_constant
           && b.k == 0)
    return pv_constant (0);

  /* We can 'and' anything with ~0.  */
  else if (b.kind == pvk_constant
           && b.k == ~ (CORE_ADDR) 0)
    return a;

  /* We can 'and' a register with itself.  */
  else if (a.kind == pvk_register
           && b.kind == pvk_register
           && a.reg == b.reg
           && a.k == b.k)
    return a;

  /* Otherwise, we don't know.  */
  else
    return pv_unknown ();
}



/* Examining prologue values.  */

int
pv_is_identical (pv_t a, pv_t b)
{
  if (a.kind != b.kind)
    return 0;

  switch (a.kind)
    {
    case pvk_unknown:
      return 1;
    case pvk_constant:
      return (a.k == b.k);
    case pvk_register:
      return (a.reg == b.reg && a.k == b.k);
    default:
      gdb_assert_not_reached ("unexpected prologue value kind");
    }
}


int
pv_is_constant (pv_t a)
{
  return (a.kind == pvk_constant);
}


int
pv_is_register (pv_t a, int r)
{
  return (a.kind == pvk_register
          && a.reg == r);
}


int
pv_is_register_k (pv_t a, int r, CORE_ADDR k)
{
  return (a.kind == pvk_register
          && a.reg == r
          && a.k == k);
}


enum pv_boolean
pv_is_array_ref (pv_t addr, CORE_ADDR size,
                 pv_t array_addr, CORE_ADDR array_len,
                 CORE_ADDR elt_size,
                 int *i)
{
  /* Note that, since .k is a CORE_ADDR, and CORE_ADDR is unsigned, if
     addr is *before* the start of the array, then this isn't going to
     be negative...  */
  pv_t offset = pv_subtract (addr, array_addr);

  if (offset.kind == pvk_constant)
    {
      /* This is a rather odd test.  We want to know if the SIZE bytes
         at ADDR don't overlap the array at all, so you'd expect it to
         be an || expression: "if we're completely before || we're
         completely after".  But with unsigned arithmetic, things are
         different: since it's a number circle, not a number line, the
         right values for offset.k are actually one contiguous range.  */
      if (offset.k <= -size
          && offset.k >= array_len * elt_size)
        return pv_definite_no;
      else if (offset.k % elt_size != 0
               || size != elt_size)
        return pv_maybe;
      else
        {
          *i = offset.k / elt_size;
          return pv_definite_yes;
        }
    }
  else
    return pv_maybe;
}



/* Areas.  */


/* A particular value known to be stored in an area.

   Entries form a ring, sorted by unsigned offset from the area's base
   register's value.  Since entries can straddle the wrap-around point,
   unsigned offsets form a circle, not a number line, so the list
   itself is structured the same way --- there is no inherent head.
   The entry with the lowest offset simply follows the entry with the
   highest offset.  Entries may abut, but never overlap.  The area's
   'entry' pointer points to an arbitrary node in the ring.  */
struct area_entry
{
  /* Links in the doubly-linked ring.  */
  struct area_entry *prev, *next;

  /* Offset of this entry's address from the value of the base
     register.  */
  CORE_ADDR offset;

  /* The size of this entry.  Note that an entry may wrap around from
     the end of the address space to the beginning.  */
  CORE_ADDR size;

  /* The value stored here.  */
  pv_t value;
};


struct pv_area
{
  /* This area's base register.  */
  int base_reg;

  /* The mask to apply to addresses, to make the wrap-around happen at
     the right place.  */
  CORE_ADDR addr_mask;

  /* An element of the doubly-linked ring of entries, or zero if we
     have none.  */
  struct area_entry *entry;
};


struct pv_area *
make_pv_area (int base_reg, int addr_bit)
{
  struct pv_area *a = (struct pv_area *) xmalloc (sizeof (*a));

  memset (a, 0, sizeof (*a));

  a->base_reg = base_reg;
  a->entry = 0;

  /* Remember that shift amounts equal to the type's width are
     undefined.  */
  a->addr_mask = ((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1;

  return a;
}


/* Delete all entries from AREA.  */
static void
clear_entries (struct pv_area *area)
{
  struct area_entry *e = area->entry;

  if (e)
    {
      /* This needs to be a do-while loop, in order to actually
         process the node being checked for in the terminating
         condition.  */
      do
        {
          struct area_entry *next = e->next;

          xfree (e);
          e = next;
        }
      while (e != area->entry);

      area->entry = 0;
    }
}


void
free_pv_area (struct pv_area *area)
{
  clear_entries (area);
  xfree (area);
}


static void
do_free_pv_area_cleanup (void *arg)
{
  free_pv_area ((struct pv_area *) arg);
}


struct cleanup *
make_cleanup_free_pv_area (struct pv_area *area)
{
  return make_cleanup (do_free_pv_area_cleanup, (void *) area);
}


int
pv_area_store_would_trash (struct pv_area *area, pv_t addr)
{
  /* It may seem odd that pvk_constant appears here --- after all,
     that's the case where we know the most about the address!  But
     pv_areas are always relative to a register, and we don't know the
     value of the register, so we can't compare entry addresses to
     constants.  */
  return (addr.kind == pvk_unknown
          || addr.kind == pvk_constant
          || (addr.kind == pvk_register && addr.reg != area->base_reg));
}


/* Return a pointer to the first entry we hit in AREA starting at
   OFFSET and going forward.

   This may return zero, if AREA has no entries.

   And since the entries are a ring, this may return an entry that
   entirely precedes OFFSET.  This is the correct behavior: depending
   on the sizes involved, we could still overlap such an area, with
   wrap-around.  */
static struct area_entry *
find_entry (struct pv_area *area, CORE_ADDR offset)
{
  struct area_entry *e = area->entry;

  if (! e)
    return 0;

  /* If the next entry would be better than the current one, then scan
     forward.  Since we use '<' in this loop, it always terminates.

     Note that, even setting aside the addr_mask stuff, we must not
     simplify this, in high school algebra fashion, to
     (e->next->offset < e->offset), because of the way < interacts
     with wrap-around.  We have to subtract offset from both sides to
     make sure both things we're comparing are on the same side of the
     discontinuity.  */
  while (((e->next->offset - offset) & area->addr_mask)
         < ((e->offset - offset) & area->addr_mask))
    e = e->next;

  /* If the previous entry would be better than the current one, then
     scan backwards.  */
  while (((e->prev->offset - offset) & area->addr_mask)
         < ((e->offset - offset) & area->addr_mask))
    e = e->prev;

  /* In case there's some locality to the searches, set the area's
     pointer to the entry we've found.  */
  area->entry = e;

  return e;
}


/* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY;
   return zero otherwise.  AREA is the area to which ENTRY belongs.  */
static int
overlaps (struct pv_area *area,
          struct area_entry *entry,
          CORE_ADDR offset,
          CORE_ADDR size)
{
  /* Think carefully about wrap-around before simplifying this.  */
  return (((entry->offset - offset) & area->addr_mask) < size
          || ((offset - entry->offset) & area->addr_mask) < entry->size);
}


void
pv_area_store (struct pv_area *area,
               pv_t addr,
               CORE_ADDR size,
               pv_t value)
{
  /* Remove any (potentially) overlapping entries.  */
  if (pv_area_store_would_trash (area, addr))
    clear_entries (area);
  else
    {
      CORE_ADDR offset = addr.k;
      struct area_entry *e = find_entry (area, offset);

      /* Delete all entries that we would overlap.  */
      while (e && overlaps (area, e, offset, size))
        {
          struct area_entry *next = (e->next == e) ? 0 : e->next;

          e->prev->next = e->next;
          e->next->prev = e->prev;

          xfree (e);
          e = next;
        }

      /* Move the area's pointer to the next remaining entry.  This
         will also zero the pointer if we've deleted all the entries.  */
      area->entry = e;
    }

  /* Now, there are no entries overlapping us, and area->entry is
     either zero or pointing at the closest entry after us.  We can
     just insert ourselves before that.

     But if we're storing an unknown value, don't bother --- that's
     the default.  */
  if (value.kind == pvk_unknown)
    return;
  else
    {
      CORE_ADDR offset = addr.k;
      struct area_entry *e = (struct area_entry *) xmalloc (sizeof (*e));

      e->offset = offset;
      e->size = size;
      e->value = value;

      if (area->entry)
        {
          e->prev = area->entry->prev;
          e->next = area->entry;
          e->prev->next = e->next->prev = e;
        }
      else
        {
          e->prev = e->next = e;
          area->entry = e;
        }
    }
}


pv_t
pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size)
{
  /* If we have no entries, or we can't decide how ADDR relates to the
     entries we do have, then the value is unknown.  */
  if (! area->entry
      || pv_area_store_would_trash (area, addr))
    return pv_unknown ();
  else
    {
      CORE_ADDR offset = addr.k;
      struct area_entry *e = find_entry (area, offset);

      /* If this entry exactly matches what we're looking for, then
         we're set.  Otherwise, say it's unknown.  */
      if (e->offset == offset && e->size == size)
        return e->value;
      else
        return pv_unknown ();
    }
}


int
pv_area_find_reg (struct pv_area *area,
                  struct gdbarch *gdbarch,
                  int reg,
                  CORE_ADDR *offset_p)
{
  struct area_entry *e = area->entry;

  if (e)
    do
      {
        if (e->value.kind == pvk_register
            && e->value.reg == reg
            && e->value.k == 0
            && e->size == register_size (gdbarch, reg))
          {
            if (offset_p)
              *offset_p = e->offset;
            return 1;
          }

        e = e->next;
      }
    while (e != area->entry);

  return 0;
}


void
pv_area_scan (struct pv_area *area,
              void (*func) (void *closure,
                            pv_t addr,
                            CORE_ADDR size,
                            pv_t value),
              void *closure)
{
  struct area_entry *e = area->entry;
  pv_t addr;

  addr.kind = pvk_register;
  addr.reg = area->base_reg;

  if (e)
    do
      {
        addr.k = e->offset;
        func (closure, addr, e->size, e->value);
        e = e->next;
      }
    while (e != area->entry);
}
