summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeon/R600InstrInfo.cpp
blob: 2bd59fd5e1bcd5d7817fbf1ec70b33d0da637b90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// R600 Implementation of TargetInstrInfo.
//
//===----------------------------------------------------------------------===//

#include "R600InstrInfo.h"
#include "AMDGPUTargetMachine.h"
#include "R600RegisterInfo.h"

using namespace llvm;

R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm)
  : AMDGPUInstrInfo(tm),
    RI(tm, *this),
    TM(tm)
  { }

const R600RegisterInfo &R600InstrInfo::getRegisterInfo() const
{
  return RI;
}

bool R600InstrInfo::isTrig(const MachineInstr &MI) const
{
  return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG;
}

void
R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator MI, DebugLoc DL,
                           unsigned DestReg, unsigned SrcReg,
                           bool KillSrc) const
{

  unsigned subRegMap[4] = {AMDIL::sel_x, AMDIL::sel_y, AMDIL::sel_z, AMDIL::sel_w};

  if (AMDIL::R600_Reg128RegClass.contains(DestReg)
      && AMDIL::R600_Reg128RegClass.contains(SrcReg)) {
    for (unsigned i = 0; i < 4; i++) {
      BuildMI(MBB, MI, DL, get(AMDIL::MOV))
              .addReg(RI.getSubReg(DestReg, subRegMap[i]), RegState::Define)
              .addReg(RI.getSubReg(SrcReg, subRegMap[i]))
              .addReg(DestReg, RegState::Define | RegState::Implicit);
    }
  } else {

    /* We can't copy vec4 registers */
    assert(!AMDIL::R600_Reg128RegClass.contains(DestReg)
           && !AMDIL::R600_Reg128RegClass.contains(SrcReg));

    BuildMI(MBB, MI, DL, get(AMDIL::MOV), DestReg)
      .addReg(SrcReg, getKillRegState(KillSrc));
  }
}

unsigned R600InstrInfo::getISAOpcode(unsigned opcode) const
{
  switch (opcode) {
    default: return AMDGPUInstrInfo::getISAOpcode(opcode);
    case AMDIL::CUSTOM_ADD_i32:
      return AMDIL::ADD_INT;
    case AMDIL::CUSTOM_XOR_i32:
      return AMDIL::XOR_INT;
    case AMDIL::MOVE_f32:
    case AMDIL::MOVE_i32:
      return AMDIL::MOV;
    case AMDIL::SHR_i32:
      return getASHRop();
    case AMDIL::USHR_i32:
      return getLSHRop();
  }
}

unsigned R600InstrInfo::getASHRop() const
{
	unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();
	if (gen < AMDILDeviceInfo::HD5XXX) {
		return AMDIL::ASHR_r600;
	} else {
		return AMDIL::ASHR_eg;
	}
}

unsigned R600InstrInfo::getLSHRop() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();
  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::LSHR_r600;
  } else {
    return AMDIL::LSHR_eg;
  }
}

unsigned R600InstrInfo::getMULHI_UINT() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();

  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::MULHI_UINT_r600;
  } else {
    return AMDIL::MULHI_UINT_eg;
  }
}

unsigned R600InstrInfo::getMULLO_UINT() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();

  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::MULLO_UINT_r600;
  } else {
    return AMDIL::MULLO_UINT_eg;
  }
}

unsigned R600InstrInfo::getRECIP_UINT() const
{
  const AMDILDevice * dev = TM.getSubtarget<AMDILSubtarget>().device();

  if (dev->getGeneration() < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::RECIP_UINT_r600;
  } else if (dev->getDeviceFlag() != OCL_DEVICE_CAYMAN) {
    return AMDIL::RECIP_UINT_eg;
  } else {
    return AMDIL::RECIP_UINT_cm;
  }
}