/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_UTILS_ARM_CONSTANTS_ARM_H_
#define ART_COMPILER_UTILS_ARM_CONSTANTS_ARM_H_

#include <stdint.h>

#include <iosfwd>

#include "arch/arm/registers_arm.h"
#include "base/casts.h"
#include "base/logging.h"
#include "globals.h"

namespace art {
namespace arm {

// Defines constants and accessor classes to assemble, disassemble and
// simulate ARM instructions.
//
// Section references in the code refer to the "ARM Architecture Reference
// Manual" from July 2005 (available at http://www.arm.com/miscPDFs/14128.pdf)
//
// Constants for specific fields are defined in their respective named enums.
// General constants are in an anonymous enum in class Instr.

// 4 bits option for the dmb instruction.
// Order and values follows those of the ARM Architecture Reference Manual.
enum DmbOptions {
  SY = 0xf,
  ST = 0xe,
  ISH = 0xb,
  ISHST = 0xa,
  NSH = 0x7,
  NSHST = 0x6
};

enum ScaleFactor {
  TIMES_1 = 0,
  TIMES_2 = 1,
  TIMES_4 = 2,
  TIMES_8 = 3
};

// Values for double-precision floating point registers.
enum DRegister {  // private marker to avoid generate-operator-out.py from processing.
  D0  = 0,
  D1  = 1,
  D2  = 2,
  D3  = 3,
  D4  = 4,
  D5  = 5,
  D6  = 6,
  D7  = 7,
  D8  = 8,
  D9  = 9,
  D10 = 10,
  D11 = 11,
  D12 = 12,
  D13 = 13,
  D14 = 14,
  D15 = 15,
  D16 = 16,
  D17 = 17,
  D18 = 18,
  D19 = 19,
  D20 = 20,
  D21 = 21,
  D22 = 22,
  D23 = 23,
  D24 = 24,
  D25 = 25,
  D26 = 26,
  D27 = 27,
  D28 = 28,
  D29 = 29,
  D30 = 30,
  D31 = 31,
  kNumberOfDRegisters = 32,
  kNumberOfOverlappingDRegisters = 16,
  kNoDRegister = -1,
};
std::ostream& operator<<(std::ostream& os, const DRegister& rhs);


// Values for the condition field as defined in section A3.2.
enum Condition {  // private marker to avoid generate-operator-out.py from processing.
  kNoCondition = -1,
  EQ = 0,   // equal
  NE = 1,   // not equal
  CS = 2,   // carry set/unsigned higher or same
  CC = 3,   // carry clear/unsigned lower
  MI = 4,   // minus/negative
  PL = 5,   // plus/positive or zero
  VS = 6,   // overflow
  VC = 7,   // no overflow
  HI = 8,   // unsigned higher
  LS = 9,   // unsigned lower or same
  GE = 10,  // signed greater than or equal
  LT = 11,  // signed less than
  GT = 12,  // signed greater than
  LE = 13,  // signed less than or equal
  AL = 14,  // always (unconditional)
  kSpecialCondition = 15,  // special condition (refer to section A3.2.1)
  kMaxCondition = 16,
};
std::ostream& operator<<(std::ostream& os, const Condition& rhs);


// Opcodes for Data-processing instructions (instructions with a type 0 and 1)
// as defined in section A3.4
enum Opcode {
  kNoOperand = -1,
  AND = 0,   // Logical AND
  EOR = 1,   // Logical Exclusive OR
  SUB = 2,   // Subtract
  RSB = 3,   // Reverse Subtract
  ADD = 4,   // Add
  ADC = 5,   // Add with Carry
  SBC = 6,   // Subtract with Carry
  RSC = 7,   // Reverse Subtract with Carry
  TST = 8,   // Test
  TEQ = 9,   // Test Equivalence
  CMP = 10,  // Compare
  CMN = 11,  // Compare Negated
  ORR = 12,  // Logical (inclusive) OR
  MOV = 13,  // Move
  BIC = 14,  // Bit Clear
  MVN = 15,  // Move Not
  kMaxOperand = 16
};
std::ostream& operator<<(std::ostream& os, const Opcode& rhs);

// Shifter types for Data-processing operands as defined in section A5.1.2.
enum Shift {
  kNoShift = -1,
  LSL = 0,  // Logical shift left
  LSR = 1,  // Logical shift right
  ASR = 2,  // Arithmetic shift right
  ROR = 3,  // Rotate right
  RRX = 4,  // Rotate right with extend.
  kMaxShift
};
std::ostream& operator<<(std::ostream& os, const Shift& rhs);

// Constants used for the decoding or encoding of the individual fields of
// instructions. Based on the "Figure 3-1 ARM instruction set summary".
enum InstructionFields {  // private marker to avoid generate-operator-out.py from processing.
  kConditionShift = 28,
  kConditionBits = 4,
  kTypeShift = 25,
  kTypeBits = 3,
  kLinkShift = 24,
  kLinkBits = 1,
  kUShift = 23,
  kUBits = 1,
  kOpcodeShift = 21,
  kOpcodeBits = 4,
  kSShift = 20,
  kSBits = 1,
  kRnShift = 16,
  kRnBits = 4,
  kRdShift = 12,
  kRdBits = 4,
  kRsShift = 8,
  kRsBits = 4,
  kRmShift = 0,
  kRmBits = 4,

  // Immediate instruction fields encoding.
  kRotateShift = 8,
  kRotateBits = 4,
  kImmed8Shift = 0,
  kImmed8Bits = 8,

  // Shift instruction register fields encodings.
  kShiftImmShift = 7,
  kShiftRegisterShift = 8,
  kShiftImmBits = 5,
  kShiftShift = 5,
  kShiftBits = 2,

  // Load/store instruction offset field encoding.
  kOffset12Shift = 0,
  kOffset12Bits = 12,
  kOffset12Mask = 0x00000fff,

  // Mul instruction register fields encodings.
  kMulRdShift = 16,
  kMulRdBits = 4,
  kMulRnShift = 12,
  kMulRnBits = 4,

  kBranchOffsetMask = 0x00ffffff
};

// Size (in bytes) of registers.
const int kRegisterSize = 4;

// List of registers used in load/store multiple.
typedef uint16_t RegList;

// The class Instr enables access to individual fields defined in the ARM
// architecture instruction set encoding as described in figure A3-1.
//
// Example: Test whether the instruction at ptr does set the condition code
// bits.
//
// bool InstructionSetsConditionCodes(uint8_t* ptr) {
//   Instr* instr = Instr::At(ptr);
//   int type = instr->TypeField();
//   return ((type == 0) || (type == 1)) && instr->HasS();
// }
//
class Instr {
 public:
  enum {
    kInstrSize = 4,
    kInstrSizeLog2 = 2,
    kPCReadOffset = 8
  };

  bool IsBreakPoint() {
    return IsBkpt();
  }

  // Get the raw instruction bits.
  int32_t InstructionBits() const {
    return *reinterpret_cast<const int32_t*>(this);
  }

  // Set the raw instruction bits to value.
  void SetInstructionBits(int32_t value) {
    *reinterpret_cast<int32_t*>(this) = value;
  }

  // Read one particular bit out of the instruction bits.
  int Bit(int nr) const {
    return (InstructionBits() >> nr) & 1;
  }

  // Read a bit field out of the instruction bits.
  int Bits(int shift, int count) const {
    return (InstructionBits() >> shift) & ((1 << count) - 1);
  }


  // Accessors for the different named fields used in the ARM encoding.
  // The naming of these accessor corresponds to figure A3-1.
  // Generally applicable fields
  Condition ConditionField() const {
    return static_cast<Condition>(Bits(kConditionShift, kConditionBits));
  }
  int TypeField() const { return Bits(kTypeShift, kTypeBits); }

  Register RnField() const { return static_cast<Register>(
                                        Bits(kRnShift, kRnBits)); }
  Register RdField() const { return static_cast<Register>(
                                        Bits(kRdShift, kRdBits)); }

  // Fields used in Data processing instructions
  Opcode OpcodeField() const {
    return static_cast<Opcode>(Bits(kOpcodeShift, kOpcodeBits));
  }
  int SField() const { return Bits(kSShift, kSBits); }
  // with register
  Register RmField() const {
    return static_cast<Register>(Bits(kRmShift, kRmBits));
  }
  Shift ShiftField() const { return static_cast<Shift>(
                                        Bits(kShiftShift, kShiftBits)); }
  int RegShiftField() const { return Bit(4); }
  Register RsField() const {
    return static_cast<Register>(Bits(kRsShift, kRsBits));
  }
  int ShiftAmountField() const { return Bits(kShiftImmShift,
                                                    kShiftImmBits); }
  // with immediate
  int RotateField() const { return Bits(kRotateShift, kRotateBits); }
  int Immed8Field() const { return Bits(kImmed8Shift, kImmed8Bits); }

  // Fields used in Load/Store instructions
  int PUField() const { return Bits(23, 2); }
  int  BField() const { return Bit(22); }
  int  WField() const { return Bit(21); }
  int  LField() const { return Bit(20); }
  // with register uses same fields as Data processing instructions above
  // with immediate
  int Offset12Field() const { return Bits(kOffset12Shift,
                                                 kOffset12Bits); }
  // multiple
  int RlistField() const { return Bits(0, 16); }
  // extra loads and stores
  int SignField() const { return Bit(6); }
  int HField() const { return Bit(5); }
  int ImmedHField() const { return Bits(8, 4); }
  int ImmedLField() const { return Bits(0, 4); }

  // Fields used in Branch instructions
  int LinkField() const { return Bits(kLinkShift, kLinkBits); }
  int SImmed24Field() const { return ((InstructionBits() << 8) >> 8); }

  // Fields used in Supervisor Call instructions
  uint32_t SvcField() const { return Bits(0, 24); }

  // Field used in Breakpoint instruction
  uint16_t BkptField() const {
    return ((Bits(8, 12) << 4) | Bits(0, 4));
  }

  // Field used in 16-bit immediate move instructions
  uint16_t MovwField() const {
    return ((Bits(16, 4) << 12) | Bits(0, 12));
  }

  // Field used in VFP float immediate move instruction
  float ImmFloatField() const {
    uint32_t imm32 = (Bit(19) << 31) | (((1 << 5) - Bit(18)) << 25) |
                     (Bits(16, 2) << 23) | (Bits(0, 4) << 19);
    return bit_cast<float, uint32_t>(imm32);
  }

  // Field used in VFP double immediate move instruction
  double ImmDoubleField() const {
    uint64_t imm64 = (Bit(19)*(1LL << 63)) | (((1LL << 8) - Bit(18)) << 54) |
                     (Bits(16, 2)*(1LL << 52)) | (Bits(0, 4)*(1LL << 48));
    return bit_cast<double, uint64_t>(imm64);
  }

  // Test for data processing instructions of type 0 or 1.
  // See "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition",
  // section A5.1 "ARM instruction set encoding".
  bool IsDataProcessing() const {
    CHECK_NE(ConditionField(), kSpecialCondition);
    CHECK_EQ(Bits(26, 2), 0);  // Type 0 or 1.
    return ((Bits(20, 5) & 0x19) != 0x10) &&
      ((Bit(25) == 1) ||  // Data processing immediate.
       (Bit(4) == 0) ||  // Data processing register.
       (Bit(7) == 0));  // Data processing register-shifted register.
  }

  // Tests for special encodings of type 0 instructions (extra loads and stores,
  // as well as multiplications, synchronization primitives, and miscellaneous).
  // Can only be called for a type 0 or 1 instruction.
  bool IsMiscellaneous() const {
    CHECK_EQ(Bits(26, 2), 0);  // Type 0 or 1.
    return ((Bit(25) == 0) && ((Bits(20, 5) & 0x19) == 0x10) && (Bit(7) == 0));
  }
  bool IsMultiplyOrSyncPrimitive() const {
    CHECK_EQ(Bits(26, 2), 0);  // Type 0 or 1.
    return ((Bit(25) == 0) && (Bits(4, 4) == 9));
  }

  // Test for Supervisor Call instruction.
  bool IsSvc() const {
    return ((InstructionBits() & 0xff000000) == 0xef000000);
  }

  // Test for Breakpoint instruction.
  bool IsBkpt() const {
    return ((InstructionBits() & 0xfff000f0) == 0xe1200070);
  }

  // VFP register fields.
  SRegister SnField() const {
    return static_cast<SRegister>((Bits(kRnShift, kRnBits) << 1) + Bit(7));
  }
  SRegister SdField() const {
    return static_cast<SRegister>((Bits(kRdShift, kRdBits) << 1) + Bit(22));
  }
  SRegister SmField() const {
    return static_cast<SRegister>((Bits(kRmShift, kRmBits) << 1) + Bit(5));
  }
  DRegister DnField() const {
    return static_cast<DRegister>(Bits(kRnShift, kRnBits) + (Bit(7) << 4));
  }
  DRegister DdField() const {
    return static_cast<DRegister>(Bits(kRdShift, kRdBits) + (Bit(22) << 4));
  }
  DRegister DmField() const {
    return static_cast<DRegister>(Bits(kRmShift, kRmBits) + (Bit(5) << 4));
  }

  // Test for VFP data processing or single transfer instructions of type 7.
  bool IsVFPDataProcessingOrSingleTransfer() const {
    CHECK_NE(ConditionField(), kSpecialCondition);
    CHECK_EQ(TypeField(), 7);
    return ((Bit(24) == 0) && (Bits(9, 3) == 5));
    // Bit(4) == 0: Data Processing
    // Bit(4) == 1: 8, 16, or 32-bit Transfer between ARM Core and VFP
  }

  // Test for VFP 64-bit transfer instructions of type 6.
  bool IsVFPDoubleTransfer() const {
    CHECK_NE(ConditionField(), kSpecialCondition);
    CHECK_EQ(TypeField(), 6);
    return ((Bits(21, 4) == 2) && (Bits(9, 3) == 5) &&
            ((Bits(4, 4) & 0xd) == 1));
  }

  // Test for VFP load and store instructions of type 6.
  bool IsVFPLoadStore() const {
    CHECK_NE(ConditionField(), kSpecialCondition);
    CHECK_EQ(TypeField(), 6);
    return ((Bits(20, 5) & 0x12) == 0x10) && (Bits(9, 3) == 5);
  }

  // Special accessors that test for existence of a value.
  bool HasS() const { return SField() == 1; }
  bool HasB() const { return BField() == 1; }
  bool HasW() const { return WField() == 1; }
  bool HasL() const { return LField() == 1; }
  bool HasSign() const { return SignField() == 1; }
  bool HasH() const { return HField() == 1; }
  bool HasLink() const { return LinkField() == 1; }

  // Instructions are read out of a code stream. The only way to get a
  // reference to an instruction is to convert a pointer. There is no way
  // to allocate or create instances of class Instr.
  // Use the At(pc) function to create references to Instr.
  static Instr* At(uintptr_t pc) { return reinterpret_cast<Instr*>(pc); }
  Instr* Next() { return this + kInstrSize; }

 private:
  // We need to prevent the creation of instances of class Instr.
  DISALLOW_IMPLICIT_CONSTRUCTORS(Instr);
};

}  // namespace arm
}  // namespace art

#endif  // ART_COMPILER_UTILS_ARM_CONSTANTS_ARM_H_
