// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"  // Needed here to get TARGET_ARCH_MIPS.
#if defined(TARGET_ARCH_MIPS)

#include "vm/constants_mips.h"
#include "vm/cpu.h"
#include "vm/instructions.h"
#include "vm/object.h"

namespace dart {

CallPattern::CallPattern(uword pc, const Code& code)
    : end_(reinterpret_cast<uword*>(pc)),
      target_address_pool_index_(-1),
      args_desc_load_end_(-1),
      args_desc_(Array::Handle()),
      ic_data_load_end_(-1),
      ic_data_(ICData::Handle()),
      object_pool_(Array::Handle(code.ObjectPool())) {
  ASSERT(code.ContainsInstructionAt(pc));
  ASSERT(Back(2) == 0x0020f809);  // Last instruction: jalr RA, TMP(=R1)
  Register reg;
  // First end is 0 so that we begin from the delay slot of the jalr.
  ic_data_load_end_ =
      DecodeLoadWordFromPool(2, &reg, &target_address_pool_index_);
  ASSERT(reg == TMP);
}


uword CallPattern::Back(int n) const {
  ASSERT(n > 0);
  return *(end_ - n);
}


// Decodes a load sequence ending at end. Returns the register being loaded and
// the loaded object.
// Returns the location of the load sequence, counting the number of
// instructions back from the end of the call pattern.
int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) {
  ASSERT(end > 0);
  uword i = Back(end + 1);
  Instr* instr = Instr::At(reinterpret_cast<uword>(&i));
  if (instr->OpcodeField() == LW) {
    int index = 0;
    end = DecodeLoadWordFromPool(end, reg, &index);
    *obj = object_pool_.At(index);
  } else {
    int value = 0;
    end = DecodeLoadWordImmediate(end, reg, &value);
    *obj = reinterpret_cast<RawObject*>(value);
  }
  return end;
}


// Decodes a load sequence ending at end. Returns the register being loaded and
// the loaded immediate value.
// Returns the location of the load sequence, counting the number of
// instructions back from the end of the call pattern.
int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) {
  ASSERT(end > 0);
  int imm = 0;
  uword i = Back(++end);
  Instr* instr = Instr::At(reinterpret_cast<uword>(&i));
  ASSERT(instr->OpcodeField() == ORI);
  imm = instr->UImmField();
  *reg = instr->RtField();

  i = Back(++end);
  instr = Instr::At(reinterpret_cast<uword>(&i));
  ASSERT(instr->OpcodeField() == LUI);
  ASSERT(instr->RtField() == *reg);
  imm |= (instr->UImmField() << 16);
  *value = imm;
  return end;
}


// Decodes a load sequence ending at end. Returns the register being loaded and
// the index in the pool being read from.
// Returns the location of the load sequence, counting the number of
// instructions back from the end of the call pattern.
int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) {
  ASSERT(end > 0);
  uword i = Back(++end);
  Instr* instr = Instr::At(reinterpret_cast<uword>(&i));
  int offset = 0;
  if ((instr->OpcodeField() == LW) && (instr->RsField() == PP)) {
    offset = instr->SImmField();
    *reg = instr->RtField();
  } else {
    ASSERT(instr->OpcodeField() == LW);
    offset = instr->SImmField();
    *reg = instr->RtField();

    i = Back(++end);
    instr = Instr::At(reinterpret_cast<uword>(&i));
    ASSERT(instr->OpcodeField() == SPECIAL);
    ASSERT(instr->FunctionField() == ADDU);
    ASSERT(instr->RdField() == *reg);
    ASSERT(instr->RsField() == *reg);
    ASSERT(instr->RtField() == PP);

    i = Back(++end);
    instr = Instr::At(reinterpret_cast<uword>(&i));
    ASSERT(instr->OpcodeField() == LUI);
    ASSERT(instr->RtField() == *reg);
    // Offset is signed, so add the upper 16 bits.
    offset += (instr->UImmField() << 16);
  }
  offset += kHeapObjectTag;
  ASSERT(Utils::IsAligned(offset, 4));
  *index = (offset - Array::data_offset())/4;
  return end;
}


RawICData* CallPattern::IcData() {
  if (ic_data_.IsNull()) {
    Register reg;
    args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, &reg, &ic_data_);
    ASSERT(reg == S5);
  }
  return ic_data_.raw();
}


RawArray* CallPattern::ClosureArgumentsDescriptor() {
  if (args_desc_.IsNull()) {
    IcData();  // Loading of the ic_data must be decoded first, if not already.
    Register reg;
    DecodeLoadObject(args_desc_load_end_, &reg, &args_desc_);
    ASSERT(reg == S4);
  }
  return args_desc_.raw();
}


uword CallPattern::TargetAddress() const {
  ASSERT(target_address_pool_index_ >= 0);
  const Object& target_address =
      Object::Handle(object_pool_.At(target_address_pool_index_));
  ASSERT(target_address.IsSmi());
  // The address is stored in the object array as a RawSmi.
  return reinterpret_cast<uword>(target_address.raw());
}


void CallPattern::SetTargetAddress(uword target_address) const {
  ASSERT(Utils::IsAligned(target_address, 4));
  // The address is stored in the object array as a RawSmi.
  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
  object_pool_.SetAt(target_address_pool_index_, smi);
  // No need to flush the instruction cache, since the code is not modified.
}


void CallPattern::InsertAt(uword pc, uword target_address) {
  Instr* lui = Instr::At(pc + (0 * Instr::kInstrSize));
  Instr* ori = Instr::At(pc + (1 * Instr::kInstrSize));
  Instr* jr = Instr::At(pc + (2 * Instr::kInstrSize));
  Instr* nop = Instr::At(pc + (3 * Instr::kInstrSize));
  uint16_t target_lo = target_address & 0xffff;
  uint16_t target_hi = target_address >> 16;

  lui->SetImmInstrBits(LUI, ZR, TMP1, target_hi);
  ori->SetImmInstrBits(ORI, TMP1, TMP1, target_lo);
  jr->SetSpecialInstrBits(JALR, TMP1, ZR, RA);
  nop->SetInstructionBits(Instr::kNopInstruction);

  ASSERT(kFixedLengthInBytes == 4 * Instr::kInstrSize);
  CPU::FlushICache(pc, kFixedLengthInBytes);
}


JumpPattern::JumpPattern(uword pc) : pc_(pc) { }


bool JumpPattern::IsValid() const {
  Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize));
  Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize));
  Instr* jr = Instr::At(pc_ + (2 * Instr::kInstrSize));
  Instr* nop = Instr::At(pc_ + (3 * Instr::kInstrSize));
  return (lui->OpcodeField() == LUI) &&
         (ori->OpcodeField() == ORI) &&
         (jr->OpcodeField() == SPECIAL) &&
         (jr->FunctionField() == JR) &&
         (nop->InstructionBits() == Instr::kNopInstruction);
}


uword JumpPattern::TargetAddress() const {
  Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize));
  Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize));
  const uint16_t target_lo = ori->UImmField();
  const uint16_t target_hi = lui->UImmField();
  return (target_hi << 16) | target_lo;
}


void JumpPattern::SetTargetAddress(uword target_address) const {
  Instr* lui = Instr::At(pc_ + (0 * Instr::kInstrSize));
  Instr* ori = Instr::At(pc_ + (1 * Instr::kInstrSize));
  const int32_t lui_bits = lui->InstructionBits();
  const int32_t ori_bits = ori->InstructionBits();
  const uint16_t target_lo = target_address & 0xffff;
  const uint16_t target_hi = target_address >> 16;

  lui->SetInstructionBits((lui_bits & 0xffff0000) | target_hi);
  ori->SetInstructionBits((ori_bits & 0xffff0000) | target_lo);
}

}  // namespace dart

#endif  // defined TARGET_ARCH_MIPS

