/* Auxiliary functions for pipeline descriptions pattern of Andes
   NDS32 cpu for GNU compiler
   Copyright (C) 2012-2021 Free Software Foundation, Inc.
   Contributed by Andes Technology Corporation.

   This file is part of GCC.

   GCC 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, or (at your
   option) any later version.

   GCC 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 GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  */

/* ------------------------------------------------------------------------ */

#define IN_TARGET_CODE 1

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "memmodel.h"
#include "tm_p.h"
#include "optabs.h"		/* For GEN_FCN.  */
#include "recog.h"
#include "tm-constrs.h"
#include "insn-attr.h"


namespace nds32 {

/* Get the rtx in the PATTERN field of an insn.  If INSN is not an insn,
   the funciton doesn't change anything and returns it directly.  */
rtx
extract_pattern_from_insn (rtx insn)
{
  if (INSN_P (insn))
    return PATTERN (insn);

  return insn;
}

/* Get the number of elements in a parallel rtx.  */
size_t
parallel_elements (rtx parallel_rtx)
{
  parallel_rtx = extract_pattern_from_insn (parallel_rtx);
  gcc_assert (GET_CODE (parallel_rtx) == PARALLEL);

  return XVECLEN (parallel_rtx, 0);
}

/* Extract an rtx from a parallel rtx with index NTH.  If NTH is a negative
   value, the function returns the last NTH rtx.  */
rtx
parallel_element (rtx parallel_rtx, int nth)
{
  parallel_rtx = extract_pattern_from_insn (parallel_rtx);
  gcc_assert (GET_CODE (parallel_rtx) == PARALLEL);

  int len = parallel_elements (parallel_rtx);

  if (nth >= 0)
    {
      if (nth >= len)
	return NULL_RTX;

      return XVECEXP (parallel_rtx, 0, nth);
    }
  else
    {
      if (len + nth < 0)
	return NULL_RTX;

      return XVECEXP (parallel_rtx, 0, len + nth);
    }
}

/* Functions to determine whether INSN is single-word, double-word
   or partial-word load/store insn.  */

bool
load_single_p (rtx_insn *insn)
{
  if (get_attr_type (insn) != TYPE_LOAD)
    return false;

  if (INSN_CODE (insn) == CODE_FOR_move_di ||
      INSN_CODE (insn) == CODE_FOR_move_df)
    return false;

  return true;
}

bool
store_single_p (rtx_insn *insn)
{
  if (get_attr_type (insn) != TYPE_STORE)
    return false;

  if (INSN_CODE (insn) == CODE_FOR_move_di ||
      INSN_CODE (insn) == CODE_FOR_move_df)
    return false;

  return true;
}

bool
load_double_p (rtx_insn *insn)
{
  if (get_attr_type (insn) != TYPE_LOAD)
    return false;

  if (INSN_CODE (insn) != CODE_FOR_move_di &&
      INSN_CODE (insn) != CODE_FOR_move_df)
    return false;

  return true;
}

bool
store_double_p (rtx_insn *insn)
{
  if (get_attr_type (insn) != TYPE_STORE)
    return false;

  if (INSN_CODE (insn) != CODE_FOR_move_di &&
      INSN_CODE (insn) != CODE_FOR_move_df)
    return false;

  return true;
}

bool
store_offset_reg_p (rtx_insn *insn)
{
  if (get_attr_type (insn) != TYPE_STORE)
    return false;

  rtx offset_rtx = extract_offset_rtx (insn);

  if (offset_rtx == NULL_RTX)
    return false;

  if (REG_P (offset_rtx))
    return true;

  return false;
}

/* Determine if INSN is a post update insn.  */
bool
post_update_insn_p (rtx_insn *insn)
{
  if (find_post_update_rtx (insn) == -1)
    return false;
  else
    return true;
}

/* Check if the address of MEM_RTX consists of a base register and an
   immediate offset.  */
bool
immed_offset_p (rtx mem_rtx)
{
  gcc_assert (MEM_P (mem_rtx));

  rtx addr_rtx = XEXP (mem_rtx, 0);

  /* (mem (reg)) is equivalent to (mem (plus (reg) (const_int 0))) */
  if (REG_P (addr_rtx))
    return true;

  /* (mem (plus (reg) (const_int))) */
  if (GET_CODE (addr_rtx) == PLUS
      && GET_CODE (XEXP (addr_rtx, 1)) == CONST_INT)
    return true;

  return false;
}

/* Find the post update rtx in INSN.  If INSN is a load/store multiple insn,
   the function returns the vector index of its parallel part.  If INSN is a
   single load/store insn, the function returns 0.  If INSN is not a post-
   update insn, the function returns -1.  */
int
find_post_update_rtx (rtx_insn *insn)
{
  rtx mem_rtx;
  int i, len;

  switch (get_attr_type (insn))
    {
    case TYPE_LOAD_MULTIPLE:
    case TYPE_STORE_MULTIPLE:
      /* Find a pattern in a parallel rtx:
	 (set (reg) (plus (reg) (const_int)))  */
      len = parallel_elements (insn);
      for (i = 0; i < len; ++i)
	{
	  rtx curr_insn = parallel_element (insn, i);

	  if (GET_CODE (curr_insn) == SET
	      && REG_P (SET_DEST (curr_insn))
	      && GET_CODE (SET_SRC (curr_insn)) == PLUS)
		return i;
	}
      return -1;

    case TYPE_LOAD:
    case TYPE_FLOAD:
    case TYPE_STORE:
    case TYPE_FSTORE:
      mem_rtx = extract_mem_rtx (insn);
      /* (mem (post_inc (reg)))  */
      switch (GET_CODE (XEXP (mem_rtx, 0)))
	{
	case POST_INC:
	case POST_DEC:
	case POST_MODIFY:
	  return 0;

	default:
	  return -1;
	}

    default:
      gcc_unreachable ();
    }
}

/* Extract the MEM rtx from a load/store insn.  */
rtx
extract_mem_rtx (rtx_insn *insn)
{
  rtx body = PATTERN (insn);

  switch (get_attr_type (insn))
    {
    case TYPE_LOAD:
    case TYPE_FLOAD:
      if (MEM_P (SET_SRC (body)))
	return SET_SRC (body);

      /* unaligned address: (unspec [(mem)])  */
      if (GET_CODE (SET_SRC (body)) == UNSPEC)
	{
	  gcc_assert (MEM_P (XVECEXP (SET_SRC (body), 0, 0)));
	  return XVECEXP (SET_SRC (body), 0, 0);
	}

      /* (sign_extend (mem)) */
      gcc_assert (MEM_P (XEXP (SET_SRC (body), 0)));
      return XEXP (SET_SRC (body), 0);

    case TYPE_STORE:
    case TYPE_FSTORE:
      if (MEM_P (SET_DEST (body)))
	return SET_DEST (body);

      /* unaligned address: (unspec [(mem)])  */
      if (GET_CODE (SET_DEST (body)) == UNSPEC)
	{
	  gcc_assert (MEM_P (XVECEXP (SET_DEST (body), 0, 0)));
	  return XVECEXP (SET_DEST (body), 0, 0);
	}

      /* (sign_extend (mem)) */
      gcc_assert (MEM_P (XEXP (SET_DEST (body), 0)));
      return XEXP (SET_DEST (body), 0);

    default:
      gcc_unreachable ();
    }
}

/* Extract the base register from load/store insns.  The function returns
   NULL_RTX if the address is not consist of any registers.  */
rtx
extract_base_reg (rtx_insn *insn)
{
  int post_update_rtx_index;
  rtx mem_rtx;
  rtx plus_rtx;

  /* Find the MEM rtx.  If we can find an insn updating the base register,
     the base register will be returned directly.  */
  switch (get_attr_type (insn))
    {
    case TYPE_LOAD_MULTIPLE:
      post_update_rtx_index = find_post_update_rtx (insn);

      if (post_update_rtx_index != -1)
        return SET_DEST (parallel_element (insn, post_update_rtx_index));

      mem_rtx = SET_SRC (parallel_element (insn, 0));
      break;

    case TYPE_STORE_MULTIPLE:
      post_update_rtx_index = find_post_update_rtx (insn);

      if (post_update_rtx_index != -1)
        return SET_DEST (parallel_element (insn, post_update_rtx_index));

      mem_rtx = SET_DEST (parallel_element (insn, 0));
      break;

    case TYPE_LOAD:
    case TYPE_FLOAD:
    case TYPE_STORE:
    case TYPE_FSTORE:
      mem_rtx = extract_mem_rtx (insn);
      break;

    default:
      gcc_unreachable ();
    }

  gcc_assert (MEM_P (mem_rtx));

  /* (mem (reg))  */
  if (REG_P (XEXP (mem_rtx, 0)))
    return XEXP (mem_rtx, 0);

  /* (mem (lo_sum (reg) (symbol_ref)) */
  if (GET_CODE (XEXP (mem_rtx, 0)) == LO_SUM)
    return XEXP (XEXP (mem_rtx, 0), 0);

  plus_rtx = XEXP (mem_rtx, 0);

  if (GET_CODE (plus_rtx) == SYMBOL_REF
      || GET_CODE (plus_rtx) == CONST)
    return NULL_RTX;

  /* (mem (plus (reg) (const_int))) or
     (mem (plus (mult (reg) (const_int 4)) (reg))) or
     (mem (post_inc (reg))) or
     (mem (post_dec (reg))) or
     (mem (post_modify (reg) (plus (reg) (reg))))  */
  gcc_assert (GET_CODE (plus_rtx) == PLUS
	      || GET_CODE (plus_rtx) == POST_INC
	      || GET_CODE (plus_rtx) == POST_DEC
	      || GET_CODE (plus_rtx) == POST_MODIFY);

  if (REG_P (XEXP (plus_rtx, 0)))
    return XEXP (plus_rtx, 0);

  gcc_assert (REG_P (XEXP (plus_rtx, 1)));
  return XEXP (plus_rtx, 1);
}

/* Extract the offset rtx from load/store insns.  The function returns
   NULL_RTX if offset is absent.  */
rtx
extract_offset_rtx (rtx_insn *insn)
{
  rtx mem_rtx;
  rtx plus_rtx;
  rtx offset_rtx;

  /* Find the MEM rtx.  The multiple load/store insns doens't have
     the offset field so we can return NULL_RTX here.  */
  switch (get_attr_type (insn))
    {
    case TYPE_LOAD_MULTIPLE:
    case TYPE_STORE_MULTIPLE:
      return NULL_RTX;

    case TYPE_LOAD:
    case TYPE_FLOAD:
    case TYPE_STORE:
    case TYPE_FSTORE:
      mem_rtx = extract_mem_rtx (insn);
      break;

    default:
      gcc_unreachable ();
    }

  gcc_assert (MEM_P (mem_rtx));

  /* (mem (reg))  */
  if (REG_P (XEXP (mem_rtx, 0)))
    return NULL_RTX;

  plus_rtx = XEXP (mem_rtx, 0);

  switch (GET_CODE (plus_rtx))
    {
    case SYMBOL_REF:
    case CONST:
    case POST_INC:
    case POST_DEC:
      return NULL_RTX;

    case PLUS:
      /* (mem (plus (reg) (const_int))) or
         (mem (plus (mult (reg) (const_int 4)) (reg))) */
      if (REG_P (XEXP (plus_rtx, 0)))
        offset_rtx = XEXP (plus_rtx, 1);
      else
	{
	  gcc_assert (REG_P (XEXP (plus_rtx, 1)));
	  offset_rtx = XEXP (plus_rtx, 0);
	}

      if (ARITHMETIC_P (offset_rtx))
	{
	  gcc_assert (GET_CODE (offset_rtx) == MULT);
	  gcc_assert (REG_P (XEXP (offset_rtx, 0)));
	  offset_rtx = XEXP (offset_rtx, 0);
	}
      break;

    case LO_SUM:
      /* (mem (lo_sum (reg) (symbol_ref)) */
      offset_rtx = XEXP (plus_rtx, 1);
      break;

    case POST_MODIFY:
      /* (mem (post_modify (reg) (plus (reg) (reg / const_int)))) */
      gcc_assert (REG_P (XEXP (plus_rtx, 0)));
      plus_rtx = XEXP (plus_rtx, 1);
      gcc_assert (GET_CODE (plus_rtx) == PLUS);
      offset_rtx = XEXP (plus_rtx, 0);
      break;

    default:
      gcc_unreachable ();
    }

  return offset_rtx;
}

/* Extract the register of the shift operand from an ALU_SHIFT rtx.  */
rtx
extract_shift_reg (rtx alu_shift_rtx)
{
  alu_shift_rtx = extract_pattern_from_insn (alu_shift_rtx);

  rtx alu_rtx = SET_SRC (alu_shift_rtx);
  rtx shift_rtx;

  /* Various forms of ALU_SHIFT can be made by the combiner.
     See the difference between add_slli and sub_slli in nds32.md.  */
  if (REG_P (XEXP (alu_rtx, 0)))
    shift_rtx = XEXP (alu_rtx, 1);
  else
    shift_rtx = XEXP (alu_rtx, 0);

  return XEXP (shift_rtx, 0);
}

/* Check if INSN is a movd44 insn.  */
bool
movd44_insn_p (rtx_insn *insn)
{
  if (get_attr_type (insn) == TYPE_ALU
      && (INSN_CODE (insn) == CODE_FOR_move_di
	  || INSN_CODE (insn) == CODE_FOR_move_df))
    {
      rtx body = PATTERN (insn);
      gcc_assert (GET_CODE (body) == SET);

      rtx src = SET_SRC (body);
      rtx dest = SET_DEST (body);

      if ((REG_P (src) || GET_CODE (src) == SUBREG)
	  && (REG_P (dest) || GET_CODE (dest) == SUBREG))
	return true;

      return false;
    }

  return false;
}

/* Extract the second result (odd reg) of a movd44 insn.  */
rtx
extract_movd44_odd_reg (rtx_insn *insn)
{
  gcc_assert (movd44_insn_p (insn));

  rtx def_reg = SET_DEST (PATTERN (insn));
  machine_mode mode;

  gcc_assert (REG_P (def_reg) || GET_CODE (def_reg) == SUBREG);
  switch (GET_MODE (def_reg))
    {
    case E_DImode:
      mode = SImode;
      break;

    case E_DFmode:
      mode = SFmode;
      break;

    default:
      gcc_unreachable ();
    }

  return gen_highpart (mode, def_reg);
}

/* Extract the rtx representing non-accumulation operands of a MAC insn.  */
rtx
extract_mac_non_acc_rtx (rtx_insn *insn)
{
  rtx exp = SET_SRC (PATTERN (insn));

  switch (get_attr_type (insn))
    {
    case TYPE_MAC:
    case TYPE_DMAC:
      if (REG_P (XEXP (exp, 0)))
	return XEXP (exp, 1);
      else
	return XEXP (exp, 0);

    default:
      gcc_unreachable ();
    }
}

/* Check if the DIV insn needs two write ports.  */
bool
divmod_p (rtx_insn *insn)
{
  gcc_assert (get_attr_type (insn) == TYPE_DIV);

  if (INSN_CODE (insn) == CODE_FOR_divmodsi4
      || INSN_CODE (insn) == CODE_FOR_udivmodsi4)
    return true;

  return false;
}

/* Extract the rtx representing the branch target to help recognize
   data hazards.  */
rtx
extract_branch_target_rtx (rtx_insn *insn)
{
  gcc_assert (CALL_P (insn) || JUMP_P (insn));

  rtx body = PATTERN (insn);

  if (GET_CODE (body) == SET)
    {
      /* RTXs in IF_THEN_ELSE are branch conditions.  */
      if (GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)
        return NULL_RTX;

      return SET_SRC (body);
    }

  if (GET_CODE (body) == CALL)
    return XEXP (body, 0);

  if (GET_CODE (body) == PARALLEL)
    {
      rtx first_rtx = parallel_element (body, 0);

      if (GET_CODE (first_rtx) == SET)
	return SET_SRC (first_rtx);

      if (GET_CODE (first_rtx) == CALL)
	return XEXP (first_rtx, 0);
    }

  /* Handle special cases of bltzal, bgezal and jralnez.  */
  if (GET_CODE (body) == COND_EXEC)
    {
      rtx addr_rtx = XEXP (body, 1);

      if (GET_CODE (addr_rtx) == SET)
	return SET_SRC (addr_rtx);

      if (GET_CODE (addr_rtx) == PARALLEL)
	{
	  rtx first_rtx = parallel_element (addr_rtx, 0);

	  if (GET_CODE (first_rtx) == SET)
	    {
	      rtx call_rtx = SET_SRC (first_rtx);
	      gcc_assert (GET_CODE (call_rtx) == CALL);

	      return XEXP (call_rtx, 0);
	    }

	  if (GET_CODE (first_rtx) == CALL)
	    return XEXP (first_rtx, 0);
	}
    }

  gcc_unreachable ();
}

/* Extract the rtx representing the branch condition to help recognize
   data hazards.  */
rtx
extract_branch_condition_rtx (rtx_insn *insn)
{
  gcc_assert (CALL_P (insn) || JUMP_P (insn));

  rtx body = PATTERN (insn);

  if (GET_CODE (body) == SET)
    {
      rtx if_then_else_rtx = SET_SRC (body);

      if (GET_CODE (if_then_else_rtx) == IF_THEN_ELSE)
        return XEXP (if_then_else_rtx, 0);

      return NULL_RTX;
    }

  if (GET_CODE (body) == COND_EXEC)
    return XEXP (body, 0);

  return NULL_RTX;
}

} // namespace nds32
