R600MCCodeEmitter.cpp revision 2ad8608cb3e6a8d2f375ad2295504167b082711f
1//===- R600MCCodeEmitter.cpp - Code Emitter for R600->Cayman GPU families -===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This code emitters outputs bytecode that is understood by the r600g driver 11// in the Mesa [1] project. The bytecode is very similar to the hardware's ISA, 12// except that the size of the instruction fields are rounded up to the 13// nearest byte. 14// 15// [1] http://www.mesa3d.org/ 16// 17//===----------------------------------------------------------------------===// 18 19#include "R600Defines.h" 20#include "MCTargetDesc/AMDGPUMCTargetDesc.h" 21#include "MCTargetDesc/AMDGPUMCCodeEmitter.h" 22#include "llvm/MC/MCCodeEmitter.h" 23#include "llvm/MC/MCContext.h" 24#include "llvm/MC/MCInst.h" 25#include "llvm/MC/MCInstrInfo.h" 26#include "llvm/MC/MCRegisterInfo.h" 27#include "llvm/MC/MCSubtargetInfo.h" 28#include "llvm/Support/raw_ostream.h" 29 30#include <stdio.h> 31 32#define SRC_BYTE_COUNT 11 33#define DST_BYTE_COUNT 5 34 35using namespace llvm; 36 37namespace { 38 39class R600MCCodeEmitter : public AMDGPUMCCodeEmitter { 40 R600MCCodeEmitter(const R600MCCodeEmitter &); // DO NOT IMPLEMENT 41 void operator=(const R600MCCodeEmitter &); // DO NOT IMPLEMENT 42 const MCInstrInfo &MCII; 43 const MCSubtargetInfo &STI; 44 MCContext &Ctx; 45 46public: 47 48 R600MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 49 MCContext &ctx) 50 : MCII(mcii), STI(sti), Ctx(ctx) { } 51 52 /// EncodeInstruction - Encode the instruction and write it to the OS. 53 virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 54 SmallVectorImpl<MCFixup> &Fixups) const; 55 56 /// getMachineOpValue - Reutrn the encoding for an MCOperand. 57 virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 58 SmallVectorImpl<MCFixup> &Fixups) const; 59private: 60 61 void EmitALUInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups, 62 raw_ostream &OS) const; 63 void EmitSrc(const MCInst &MI, unsigned OpIdx, raw_ostream &OS) const; 64 void EmitDst(const MCInst &MI, raw_ostream &OS) const; 65 void EmitALU(const MCInst &MI, unsigned numSrc, 66 SmallVectorImpl<MCFixup> &Fixups, 67 raw_ostream &OS) const; 68 void EmitTexInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups, 69 raw_ostream &OS) const; 70 void EmitFCInstr(const MCInst &MI, raw_ostream &OS) const; 71 72 void EmitNullBytes(unsigned int byteCount, raw_ostream &OS) const; 73 74 void EmitByte(unsigned int byte, raw_ostream &OS) const; 75 76 void EmitTwoBytes(uint32_t bytes, raw_ostream &OS) const; 77 78 void Emit(uint32_t value, raw_ostream &OS) const; 79 void Emit(uint64_t value, raw_ostream &OS) const; 80 81 unsigned getHWRegIndex(unsigned reg) const; 82 unsigned getHWRegChan(unsigned reg) const; 83 unsigned getHWReg(unsigned regNo) const; 84 85 bool isFCOp(unsigned opcode) const; 86 bool isTexOp(unsigned opcode) const; 87 bool isFlagSet(const MCInst &MI, unsigned Operand, unsigned Flag) const; 88 89 /// getHWRegIndexGen - Get the register's hardware index. Implemented in 90 /// R600HwRegInfo.include. 91 unsigned getHWRegIndexGen(unsigned int Reg) const; 92 93 /// getHWRegChanGen - Get the register's channel. Implemented in 94 /// R600HwRegInfo.include. 95 unsigned getHWRegChanGen(unsigned int Reg) const; 96}; 97 98} // End anonymous namespace 99 100enum RegElement { 101 ELEMENT_X = 0, 102 ELEMENT_Y, 103 ELEMENT_Z, 104 ELEMENT_W 105}; 106 107enum InstrTypes { 108 INSTR_ALU = 0, 109 INSTR_TEX, 110 INSTR_FC, 111 INSTR_NATIVE, 112 INSTR_VTX 113}; 114 115enum FCInstr { 116 FC_IF = 0, 117 FC_IF_INT, 118 FC_ELSE, 119 FC_ENDIF, 120 FC_BGNLOOP, 121 FC_ENDLOOP, 122 FC_BREAK, 123 FC_BREAK_NZ_INT, 124 FC_CONTINUE, 125 FC_BREAK_Z_INT, 126 FC_BREAK_NZ 127}; 128 129enum TextureTypes { 130 TEXTURE_1D = 1, 131 TEXTURE_2D, 132 TEXTURE_3D, 133 TEXTURE_CUBE, 134 TEXTURE_RECT, 135 TEXTURE_SHADOW1D, 136 TEXTURE_SHADOW2D, 137 TEXTURE_SHADOWRECT, 138 TEXTURE_1D_ARRAY, 139 TEXTURE_2D_ARRAY, 140 TEXTURE_SHADOW1D_ARRAY, 141 TEXTURE_SHADOW2D_ARRAY 142}; 143 144MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII, 145 const MCSubtargetInfo &STI, 146 MCContext &Ctx) { 147 return new R600MCCodeEmitter(MCII, STI, Ctx); 148} 149 150void R600MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, 151 SmallVectorImpl<MCFixup> &Fixups) const { 152 if (isTexOp(MI.getOpcode())) { 153 EmitTexInstr(MI, Fixups, OS); 154 } else if (isFCOp(MI.getOpcode())){ 155 EmitFCInstr(MI, OS); 156 } else if (MI.getOpcode() == AMDGPU::RETURN || 157 MI.getOpcode() == AMDGPU::BUNDLE || 158 MI.getOpcode() == AMDGPU::KILL) { 159 return; 160 } else { 161 switch(MI.getOpcode()) { 162 case AMDGPU::RAT_WRITE_CACHELESS_eg: 163 { 164 uint64_t inst = getBinaryCodeForInstr(MI, Fixups); 165 // XXX: Set End Of Program bit when necessary 166 // inst |= (((uint64_t)1) << 53); 167 EmitByte(INSTR_NATIVE, OS); 168 Emit(inst, OS); 169 break; 170 } 171 case AMDGPU::VTX_READ_PARAM_i32_eg: 172 case AMDGPU::VTX_READ_PARAM_f32_eg: 173 case AMDGPU::VTX_READ_GLOBAL_i32_eg: 174 case AMDGPU::VTX_READ_GLOBAL_f32_eg: 175 case AMDGPU::VTX_READ_GLOBAL_v4i32_eg: 176 case AMDGPU::VTX_READ_GLOBAL_v4f32_eg: 177 { 178 uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups); 179 uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset 180 181 EmitByte(INSTR_VTX, OS); 182 Emit(InstWord01, OS); 183 Emit(InstWord2, OS); 184 break; 185 } 186 187 default: 188 EmitALUInstr(MI, Fixups, OS); 189 break; 190 } 191 } 192} 193 194void R600MCCodeEmitter::EmitALUInstr(const MCInst &MI, 195 SmallVectorImpl<MCFixup> &Fixups, 196 raw_ostream &OS) const { 197 const MCInstrDesc &MCDesc = MCII.get(MI.getOpcode()); 198 unsigned NumOperands = MI.getNumOperands(); 199 200 if(MCDesc.findFirstPredOperandIdx() > -1) 201 NumOperands--; 202 203 if (GET_FLAG_OPERAND_IDX(MCDesc.TSFlags) != 0) 204 NumOperands--; 205 206 if(MI.getOpcode() == AMDGPU::PRED_X) 207 NumOperands = 2; 208 209 // XXX Check if instruction writes a result 210 if (NumOperands < 1) { 211 return; 212 } 213 214 // Emit instruction type 215 EmitByte(0, OS); 216 217 unsigned int OpIndex; 218 for (OpIndex = 1; OpIndex < NumOperands; OpIndex++) { 219 // Literal constants are always stored as the last operand. 220 if (MI.getOperand(OpIndex).isImm() || MI.getOperand(OpIndex).isFPImm()) { 221 break; 222 } 223 EmitSrc(MI, OpIndex, OS); 224 } 225 226 // Emit zeros for unused sources 227 for ( ; OpIndex < 4; OpIndex++) { 228 EmitNullBytes(SRC_BYTE_COUNT, OS); 229 } 230 231 EmitDst(MI, OS); 232 233 EmitALU(MI, NumOperands - 1, Fixups, OS); 234} 235 236void R600MCCodeEmitter::EmitSrc(const MCInst &MI, unsigned OpIdx, 237 raw_ostream &OS) const { 238 const MCOperand &MO = MI.getOperand(OpIdx); 239 union { 240 float f; 241 uint32_t i; 242 } Value; 243 Value.i = 0; 244 // Emit the source select (2 bytes). For GPRs, this is the register index. 245 // For other potential instruction operands, (e.g. constant registers) the 246 // value of the source select is defined in the r600isa docs. 247 if (MO.isReg()) { 248 unsigned reg = MO.getReg(); 249 EmitTwoBytes(getHWReg(reg), OS); 250 if (reg == AMDGPU::ALU_LITERAL_X) { 251 unsigned ImmOpIndex = MI.getNumOperands() - 1; 252 MCOperand ImmOp = MI.getOperand(ImmOpIndex); 253 if (ImmOp.isFPImm()) { 254 Value.f = ImmOp.getFPImm(); 255 } else { 256 assert(ImmOp.isImm()); 257 Value.i = ImmOp.getImm(); 258 } 259 } 260 } else { 261 // XXX: Handle other operand types. 262 EmitTwoBytes(0, OS); 263 } 264 265 // Emit the source channel (1 byte) 266 if (MO.isReg()) { 267 EmitByte(getHWRegChan(MO.getReg()), OS); 268 } else { 269 EmitByte(0, OS); 270 } 271 272 // XXX: Emit isNegated (1 byte) 273 if ((!(isFlagSet(MI, OpIdx, MO_FLAG_ABS))) 274 && (isFlagSet(MI, OpIdx, MO_FLAG_NEG) || 275 (MO.isReg() && 276 (MO.getReg() == AMDGPU::NEG_ONE || MO.getReg() == AMDGPU::NEG_HALF)))){ 277 EmitByte(1, OS); 278 } else { 279 EmitByte(0, OS); 280 } 281 282 // Emit isAbsolute (1 byte) 283 if (isFlagSet(MI, OpIdx, MO_FLAG_ABS)) { 284 EmitByte(1, OS); 285 } else { 286 EmitByte(0, OS); 287 } 288 289 // XXX: Emit relative addressing mode (1 byte) 290 EmitByte(0, OS); 291 292 // Emit kc_bank, This will be adjusted later by r600_asm 293 EmitByte(0, OS); 294 295 // Emit the literal value, if applicable (4 bytes). 296 Emit(Value.i, OS); 297 298} 299 300void R600MCCodeEmitter::EmitDst(const MCInst &MI, raw_ostream &OS) const { 301 302 const MCOperand &MO = MI.getOperand(0); 303 if (MO.isReg() && MO.getReg() != AMDGPU::PREDICATE_BIT) { 304 // Emit the destination register index (1 byte) 305 EmitByte(getHWReg(MO.getReg()), OS); 306 307 // Emit the element of the destination register (1 byte) 308 EmitByte(getHWRegChan(MO.getReg()), OS); 309 310 // Emit isClamped (1 byte) 311 if (isFlagSet(MI, 0, MO_FLAG_CLAMP)) { 312 EmitByte(1, OS); 313 } else { 314 EmitByte(0, OS); 315 } 316 317 // Emit writemask (1 byte). 318 if (isFlagSet(MI, 0, MO_FLAG_MASK)) { 319 EmitByte(0, OS); 320 } else { 321 EmitByte(1, OS); 322 } 323 324 // XXX: Emit relative addressing mode 325 EmitByte(0, OS); 326 } else { 327 // XXX: Handle other operand types. Are there any for destination regs? 328 EmitNullBytes(DST_BYTE_COUNT, OS); 329 } 330} 331 332void R600MCCodeEmitter::EmitALU(const MCInst &MI, unsigned numSrc, 333 SmallVectorImpl<MCFixup> &Fixups, 334 raw_ostream &OS) const { 335 const MCInstrDesc &MCDesc = MCII.get(MI.getOpcode()); 336 337 // Emit the instruction (2 bytes) 338 EmitTwoBytes(getBinaryCodeForInstr(MI, Fixups), OS); 339 340 // Emit IsLast (for this instruction group) (1 byte) 341 if (isFlagSet(MI, 0, MO_FLAG_NOT_LAST)) { 342 EmitByte(0, OS); 343 } else { 344 EmitByte(1, OS); 345 } 346 347 // Emit isOp3 (1 byte) 348 if (numSrc == 3) { 349 EmitByte(1, OS); 350 } else { 351 EmitByte(0, OS); 352 } 353 354 // XXX: Emit push modifier 355 if(isFlagSet(MI, 1, MO_FLAG_PUSH)) { 356 EmitByte(1, OS); 357 } else { 358 EmitByte(0, OS); 359 } 360 361 // XXX: Emit predicate (1 byte) 362 int PredIdx = MCDesc.findFirstPredOperandIdx(); 363 if (PredIdx > -1) 364 switch(MI.getOperand(PredIdx).getReg()) { 365 case AMDGPU::PRED_SEL_ZERO: 366 EmitByte(2, OS); 367 break; 368 case AMDGPU::PRED_SEL_ONE: 369 EmitByte(3, OS); 370 break; 371 default: 372 EmitByte(0, OS); 373 break; 374 } 375 else { 376 EmitByte(0, OS); 377 } 378 379 380 // XXX: Emit bank swizzle. (1 byte) Do we need this? It looks like 381 // r600_asm.c sets it. 382 EmitByte(0, OS); 383 384 // XXX: Emit bank_swizzle_force (1 byte) Not sure what this is for. 385 EmitByte(0, OS); 386 387 // XXX: Emit OMOD (1 byte) Not implemented. 388 EmitByte(0, OS); 389 390 // XXX: Emit index_mode. I think this is for indirect addressing, so we 391 // don't need to worry about it. 392 EmitByte(0, OS); 393} 394 395void R600MCCodeEmitter::EmitTexInstr(const MCInst &MI, 396 SmallVectorImpl<MCFixup> &Fixups, 397 raw_ostream &OS) const { 398 399 unsigned opcode = MI.getOpcode(); 400 bool hasOffsets = (opcode == AMDGPU::TEX_LD); 401 unsigned op_offset = hasOffsets ? 3 : 0; 402 int64_t sampler = MI.getOperand(op_offset+2).getImm(); 403 int64_t textureType = MI.getOperand(op_offset+3).getImm(); 404 unsigned srcSelect[4] = {0, 1, 2, 3}; 405 406 // Emit instruction type 407 EmitByte(1, OS); 408 409 // Emit instruction 410 EmitByte(getBinaryCodeForInstr(MI, Fixups), OS); 411 412 // XXX: Emit resource id r600_shader.c uses sampler + 1. Why? 413 EmitByte(sampler + 1 + 1, OS); 414 415 // Emit source register 416 EmitByte(getHWReg(MI.getOperand(1).getReg()), OS); 417 418 // XXX: Emit src isRelativeAddress 419 EmitByte(0, OS); 420 421 // Emit destination register 422 EmitByte(getHWReg(MI.getOperand(0).getReg()), OS); 423 424 // XXX: Emit dst isRealtiveAddress 425 EmitByte(0, OS); 426 427 // XXX: Emit dst select 428 EmitByte(0, OS); // X 429 EmitByte(1, OS); // Y 430 EmitByte(2, OS); // Z 431 EmitByte(3, OS); // W 432 433 // XXX: Emit lod bias 434 EmitByte(0, OS); 435 436 // XXX: Emit coord types 437 unsigned coordType[4] = {1, 1, 1, 1}; 438 439 if (textureType == TEXTURE_RECT 440 || textureType == TEXTURE_SHADOWRECT) { 441 coordType[ELEMENT_X] = 0; 442 coordType[ELEMENT_Y] = 0; 443 } 444 445 if (textureType == TEXTURE_1D_ARRAY 446 || textureType == TEXTURE_SHADOW1D_ARRAY) { 447 if (opcode == AMDGPU::TEX_SAMPLE_C_L || opcode == AMDGPU::TEX_SAMPLE_C_LB) { 448 coordType[ELEMENT_Y] = 0; 449 } else { 450 coordType[ELEMENT_Z] = 0; 451 srcSelect[ELEMENT_Z] = ELEMENT_Y; 452 } 453 } else if (textureType == TEXTURE_2D_ARRAY 454 || textureType == TEXTURE_SHADOW2D_ARRAY) { 455 coordType[ELEMENT_Z] = 0; 456 } 457 458 for (unsigned i = 0; i < 4; i++) { 459 EmitByte(coordType[i], OS); 460 } 461 462 // XXX: Emit offsets 463 if (hasOffsets) 464 for (unsigned i = 2; i < 5; i++) 465 EmitByte(MI.getOperand(i).getImm()<<1, OS); 466 else 467 EmitNullBytes(3, OS); 468 469 // Emit sampler id 470 EmitByte(sampler, OS); 471 472 // XXX:Emit source select 473 if ((textureType == TEXTURE_SHADOW1D 474 || textureType == TEXTURE_SHADOW2D 475 || textureType == TEXTURE_SHADOWRECT 476 || textureType == TEXTURE_SHADOW1D_ARRAY) 477 && opcode != AMDGPU::TEX_SAMPLE_C_L 478 && opcode != AMDGPU::TEX_SAMPLE_C_LB) { 479 srcSelect[ELEMENT_W] = ELEMENT_Z; 480 } 481 482 for (unsigned i = 0; i < 4; i++) { 483 EmitByte(srcSelect[i], OS); 484 } 485} 486 487void R600MCCodeEmitter::EmitFCInstr(const MCInst &MI, raw_ostream &OS) const { 488 489 // Emit instruction type 490 EmitByte(INSTR_FC, OS); 491 492 // Emit SRC 493 unsigned NumOperands = MI.getNumOperands(); 494 if (NumOperands > 0) { 495 assert(NumOperands == 1); 496 EmitSrc(MI, 0, OS); 497 } else { 498 EmitNullBytes(SRC_BYTE_COUNT, OS); 499 } 500 501 // Emit FC Instruction 502 enum FCInstr instr; 503 switch (MI.getOpcode()) { 504 case AMDGPU::BREAK_LOGICALZ_f32: 505 instr = FC_BREAK; 506 break; 507 case AMDGPU::BREAK_LOGICALNZ_f32: 508 instr = FC_BREAK_NZ; 509 break; 510 case AMDGPU::BREAK_LOGICALNZ_i32: 511 instr = FC_BREAK_NZ_INT; 512 break; 513 case AMDGPU::BREAK_LOGICALZ_i32: 514 instr = FC_BREAK_Z_INT; 515 break; 516 case AMDGPU::CONTINUE_LOGICALNZ_f32: 517 case AMDGPU::CONTINUE_LOGICALNZ_i32: 518 instr = FC_CONTINUE; 519 break; 520 case AMDGPU::IF_LOGICALNZ_f32: 521 instr = FC_IF; 522 case AMDGPU::IF_LOGICALNZ_i32: 523 instr = FC_IF_INT; 524 break; 525 case AMDGPU::IF_LOGICALZ_f32: 526 abort(); 527 break; 528 case AMDGPU::ELSE: 529 instr = FC_ELSE; 530 break; 531 case AMDGPU::ENDIF: 532 instr = FC_ENDIF; 533 break; 534 case AMDGPU::ENDLOOP: 535 instr = FC_ENDLOOP; 536 break; 537 case AMDGPU::WHILELOOP: 538 instr = FC_BGNLOOP; 539 break; 540 default: 541 abort(); 542 break; 543 } 544 EmitByte(instr, OS); 545} 546 547void R600MCCodeEmitter::EmitNullBytes(unsigned int ByteCount, 548 raw_ostream &OS) const { 549 550 for (unsigned int i = 0; i < ByteCount; i++) { 551 EmitByte(0, OS); 552 } 553} 554 555void R600MCCodeEmitter::EmitByte(unsigned int Byte, raw_ostream &OS) const { 556 OS.write((uint8_t) Byte & 0xff); 557} 558 559void R600MCCodeEmitter::EmitTwoBytes(unsigned int Bytes, 560 raw_ostream &OS) const { 561 OS.write((uint8_t) (Bytes & 0xff)); 562 OS.write((uint8_t) ((Bytes >> 8) & 0xff)); 563} 564 565void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const { 566 for (unsigned i = 0; i < 4; i++) { 567 OS.write((uint8_t) ((Value >> (8 * i)) & 0xff)); 568 } 569} 570 571void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const { 572 for (unsigned i = 0; i < 8; i++) { 573 EmitByte((Value >> (8 * i)) & 0xff, OS); 574 } 575} 576 577unsigned R600MCCodeEmitter::getHWRegIndex(unsigned reg) const { 578 switch(reg) { 579 case AMDGPU::ZERO: return 248; 580 case AMDGPU::ONE: 581 case AMDGPU::NEG_ONE: return 249; 582 case AMDGPU::ONE_INT: return 250; 583 case AMDGPU::HALF: 584 case AMDGPU::NEG_HALF: return 252; 585 case AMDGPU::ALU_LITERAL_X: return 253; 586 case AMDGPU::PREDICATE_BIT: 587 case AMDGPU::PRED_SEL_OFF: 588 case AMDGPU::PRED_SEL_ZERO: 589 case AMDGPU::PRED_SEL_ONE: 590 return 0; 591 default: return getHWRegIndexGen(reg); 592 } 593} 594 595unsigned R600MCCodeEmitter::getHWRegChan(unsigned reg) const { 596 switch(reg) { 597 case AMDGPU::ZERO: 598 case AMDGPU::ONE: 599 case AMDGPU::ONE_INT: 600 case AMDGPU::NEG_ONE: 601 case AMDGPU::HALF: 602 case AMDGPU::NEG_HALF: 603 case AMDGPU::ALU_LITERAL_X: 604 case AMDGPU::PREDICATE_BIT: 605 case AMDGPU::PRED_SEL_OFF: 606 case AMDGPU::PRED_SEL_ZERO: 607 case AMDGPU::PRED_SEL_ONE: 608 return 0; 609 default: return getHWRegChanGen(reg); 610 } 611} 612unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const { 613 unsigned HWReg; 614 615 HWReg = getHWRegIndex(RegNo); 616 if (AMDGPUMCRegisterClasses[AMDGPU::R600_CReg32RegClassID].contains(RegNo)) { 617 HWReg += 512; 618 } 619 return HWReg; 620} 621 622uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI, 623 const MCOperand &MO, 624 SmallVectorImpl<MCFixup> &Fixup) const { 625 if (MO.isReg()) { 626 return getHWReg(MO.getReg()); 627 } else { 628 return MO.getImm(); 629 } 630} 631 632//===----------------------------------------------------------------------===// 633// Encoding helper functions 634//===----------------------------------------------------------------------===// 635 636bool R600MCCodeEmitter::isFCOp(unsigned opcode) const { 637 switch(opcode) { 638 default: return false; 639 case AMDGPU::BREAK_LOGICALZ_f32: 640 case AMDGPU::BREAK_LOGICALNZ_i32: 641 case AMDGPU::BREAK_LOGICALZ_i32: 642 case AMDGPU::BREAK_LOGICALNZ_f32: 643 case AMDGPU::CONTINUE_LOGICALNZ_f32: 644 case AMDGPU::IF_LOGICALNZ_i32: 645 case AMDGPU::IF_LOGICALZ_f32: 646 case AMDGPU::ELSE: 647 case AMDGPU::ENDIF: 648 case AMDGPU::ENDLOOP: 649 case AMDGPU::IF_LOGICALNZ_f32: 650 case AMDGPU::WHILELOOP: 651 return true; 652 } 653} 654 655bool R600MCCodeEmitter::isTexOp(unsigned opcode) const { 656 switch(opcode) { 657 default: return false; 658 case AMDGPU::TEX_LD: 659 case AMDGPU::TEX_GET_TEXTURE_RESINFO: 660 case AMDGPU::TEX_SAMPLE: 661 case AMDGPU::TEX_SAMPLE_C: 662 case AMDGPU::TEX_SAMPLE_L: 663 case AMDGPU::TEX_SAMPLE_C_L: 664 case AMDGPU::TEX_SAMPLE_LB: 665 case AMDGPU::TEX_SAMPLE_C_LB: 666 case AMDGPU::TEX_SAMPLE_G: 667 case AMDGPU::TEX_SAMPLE_C_G: 668 case AMDGPU::TEX_GET_GRADIENTS_H: 669 case AMDGPU::TEX_GET_GRADIENTS_V: 670 case AMDGPU::TEX_SET_GRADIENTS_H: 671 case AMDGPU::TEX_SET_GRADIENTS_V: 672 return true; 673 } 674} 675 676bool R600MCCodeEmitter::isFlagSet(const MCInst &MI, unsigned Operand, 677 unsigned Flag) const { 678 const MCInstrDesc &MCDesc = MCII.get(MI.getOpcode()); 679 unsigned FlagIndex = GET_FLAG_OPERAND_IDX(MCDesc.TSFlags); 680 if (FlagIndex == 0) { 681 return false; 682 } 683 assert(MI.getOperand(FlagIndex).isImm()); 684 return !!((MI.getOperand(FlagIndex).getImm() >> 685 (NUM_MO_FLAGS * Operand)) & Flag); 686} 687#define R600RegisterInfo R600MCCodeEmitter 688#include "R600HwRegInfo.include" 689#undef R600RegisterInfo 690 691#include "AMDGPUGenMCCodeEmitter.inc" 692