//===-- Teak/TeakMCCodeEmitter.cpp - Convert Teak code to machine code -------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the TeakMCCodeEmitter class. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mccodeemitter" #include "../Teak.h" #include "../TeakMachineFunctionInfo.h" #include "../TeakSubtarget.h" #include "../TeakTargetMachine.h" #include "MCTargetDesc/TeakMCTargetDesc.h" #include "MCTargetDesc/TeakFixupKinds.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); namespace { class TeakMCCodeEmitter : public MCCodeEmitter { TeakMCCodeEmitter(const TeakMCCodeEmitter &) = delete; void operator=(const TeakMCCodeEmitter &) = delete; const MCInstrInfo &MCII; const MCContext &CTX; public: TeakMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : MCII(mcii), CTX(ctx) {} ~TeakMCCodeEmitter() {} // getBinaryCodeForInstr - TableGen'erated function for getting the // binary encoding for an instruction. uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; unsigned getMemSrcValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; void EmitByte(unsigned char C, raw_ostream &OS) const { OS << (char)C; } void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const { // Output the constant in little endian byte order. for (unsigned i = 0; i != Size; ++i) { EmitByte(Val & 255, OS); Val >>= 8; } } void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; }; } // end anonymous namespace MCCodeEmitter *llvm::createTeakMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { return new TeakMCCodeEmitter(MCII, Ctx); } /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned TeakMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { return 0; } unsigned TeakMCCodeEmitter::getMemSrcValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { unsigned Bits = 0; // const MCOperand &RegMO = MI.getOperand(OpIdx); // const MCOperand &ImmMO = MI.getOperand(OpIdx + 1); // assert(ImmMO.getImm() >= 0); // Bits |= (getMachineOpValue(MI, RegMO, Fixups, STI) << 12); // Bits |= (unsigned)ImmMO.getImm() & 0xfff; return Bits; } static unsigned encodeRegisterOp(unsigned reg) { switch (reg) { case Teak::R0: return 0; case Teak::R1: return 1; case Teak::R2: return 2; case Teak::R3: return 3; case Teak::R4: return 4; case Teak::R5: return 5; case Teak::R7: return 6; case Teak::Y0: return 7; //case Teak::ST0: return 8; //case Teak::ST1: return 9; //case Teak::ST2: return 0xA; //case Teak::P0H: return 0xB; case Teak::PC: return 0xC; case Teak::SP: return 0xD; //case Teak::CFGI: return 0xE; //case Teak::CFGJ: return 0xF; case Teak::B0H: return 0x10; case Teak::B1H: return 0x11; case Teak::B0L: return 0x12; case Teak::B1L: return 0x13; case Teak::EXT0: return 0x14; case Teak::EXT1: return 0x15; case Teak::EXT2: return 0x16; case Teak::EXT3: return 0x17; case Teak::A0: return 0x18; case Teak::A1: return 0x19; case Teak::A0L: return 0x1A; case Teak::A1L: return 0x1B; case Teak::A0H: return 0x1C; case Teak::A1H: return 0x1D; case Teak::LC: return 0x1E; case Teak::SV: return 0x1F; default: dbgs() << "encodeRegisterOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeRegisterP0Op(unsigned reg) { switch (reg) { case Teak::R0: return 0; case Teak::R1: return 1; case Teak::R2: return 2; case Teak::R3: return 3; case Teak::R4: return 4; case Teak::R5: return 5; case Teak::R7: return 6; case Teak::Y0: return 7; //case Teak::ST0: return 8; //case Teak::ST1: return 9; //case Teak::ST2: return 0xA; case Teak::P0: return 0xB; case Teak::PC: return 0xC; case Teak::SP: return 0xD; //case Teak::CFGI: return 0xE; //case Teak::CFGJ: return 0xF; case Teak::B0H: return 0x10; case Teak::B1H: return 0x11; case Teak::B0L: return 0x12; case Teak::B1L: return 0x13; case Teak::EXT0: return 0x14; case Teak::EXT1: return 0x15; case Teak::EXT2: return 0x16; case Teak::EXT3: return 0x17; case Teak::A0: return 0x18; case Teak::A1: return 0x19; case Teak::A0L: return 0x1A; case Teak::A1L: return 0x1B; case Teak::A0H: return 0x1C; case Teak::A1H: return 0x1D; case Teak::LC: return 0x1E; case Teak::SV: return 0x1F; default: dbgs() << "encodeRegisterOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeAbOp(unsigned reg) { switch (reg) { case Teak::B0: return 0; case Teak::B1: return 1; case Teak::A0: return 2; case Teak::A1: return 3; default: dbgs() << "encodeAbOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeAxOp(unsigned reg) { switch (reg) { case Teak::A0: return 0; case Teak::A1: return 1; default: dbgs() << "encodeAxOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeAxlOp(unsigned reg) { switch (reg) { case Teak::A0L: return 0; case Teak::A1L: return 1; default: dbgs() << "encodeAxlOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeAxhOp(unsigned reg) { switch (reg) { case Teak::A0H: return 0; case Teak::A1H: return 1; default: dbgs() << "encodeAxhOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeBxOp(unsigned reg) { switch (reg) { case Teak::B0: return 0; case Teak::B1: return 1; default: dbgs() << "encodeBxOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeAbeOp(unsigned reg) { switch (reg) { case Teak::B0E: return 0; case Teak::B1E: return 1; case Teak::A0E: return 2; case Teak::A1E: return 3; default: dbgs() << "encodeAbeOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodePxOp(unsigned reg) { switch (reg) { case Teak::P0: return 0; case Teak::P1: return 1; default: dbgs() << "encodePxOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeR0123457Y0Op(unsigned reg) { switch (reg) { case Teak::R0: return 0; case Teak::R1: return 1; case Teak::R2: return 2; case Teak::R3: return 3; case Teak::R4: return 4; case Teak::R5: return 5; case Teak::R7: return 6; case Teak::Y0: return 7; default: dbgs() << "encodeR0123457Y0Op(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeRnOp(unsigned reg) { switch (reg) { case Teak::R0: return 0; case Teak::R1: return 1; case Teak::R2: return 2; case Teak::R3: return 3; case Teak::R4: return 4; case Teak::R5: return 5; case Teak::R6: return 6; case Teak::R7: return 7; default: dbgs() << "encodeRnOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeMemR0425Op(unsigned reg) { switch (reg) { case Teak::R0: return 0; case Teak::R4: return 1; case Teak::R2: return 2; case Teak::R5: return 3; default: dbgs() << "encodeMemR0425Op(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeArArpSttModOp(unsigned reg) { switch (reg) { case Teak::STT0: return 8; case Teak::STT1: return 9; case Teak::STT2: return 10; //reserved case Teak::MOD0: return 12; case Teak::MOD1: return 13; case Teak::MOD2: return 14; case Teak::MOD3: return 15; default: dbgs() << "encodeArArpSttModOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } static unsigned encodeSttModOp(unsigned reg) { switch(reg) { case Teak::STT0: return 0; case Teak::STT1: return 1; case Teak::STT2: return 2; //reserved case Teak::MOD0: return 4; case Teak::MOD1: return 5; case Teak::MOD2: return 6; case Teak::MOD3: return 7; default: dbgs() << "encodeSttModOp(" << reg << ")\n"; llvm_unreachable("Unsupported register"); break; } } void TeakMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); //if (Desc.getSize() != 4) { // llvm_unreachable("Unexpected instruction size!"); //} //dbgs() << "op: " << MI.getOpcode() << "\n"; switch(MI.getOpcode()) { case Teak::ADD_ab_ab: { unsigned dstReg = MI.getOperand(0).getReg(); unsigned reg = MI.getOperand(1).getReg(); if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(reg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(dstReg)) EmitConstant(0x86A0 | encodeRegisterOp(reg) | (encodeAxOp(dstReg) << 8), 2, OS); else if(TeakMCRegisterClasses[Teak::ABRegsRegClassID].contains(reg) && TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(dstReg)) EmitConstant(0xD2DA | (encodeAbOp(reg) << 10) | encodeBxOp(dstReg), 2, OS); else if(TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(reg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(dstReg)) EmitConstant(0x5DF0 | (encodeBxOp(reg) << 1) | encodeAxOp(dstReg), 2, OS); else llvm_unreachable("Unsupported registers"); break; } case Teak::ADD_regnobp016_a: if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0xD38B | (encodeAxOp(MI.getOperand(0).getReg()) << 4), 2, OS); else EmitConstant(0x86A0 | encodeRegisterP0Op(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::ADDL_regnob16_a: if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0x9466 | encodeAxOp(MI.getOperand(0).getReg()), 2, OS); else EmitConstant(0x94A0 | encodeRegisterOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::ADD_imm8u_a: EmitConstant(0xC600 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(1).getImm() & 0xFF), 2, OS); break; case Teak::ADD_imm16_a: EmitConstant(0x86C0 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::ADD_memimm16_a: EmitConstant(0xD4FB | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); if(MI.getOperand(1).isImm()) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; case Teak::ADD_memrn_a: EmitConstant(0x8680 | encodeRnOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::ADD_px_ab: { unsigned abReg = MI.getOperand(0).getReg(); unsigned pReg = MI.getOperand(1).getReg(); if (pReg == Teak::P0 && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(abReg)) EmitConstant(0x86A0 | encodeRegisterP0Op(pReg) | (encodeAxOp(abReg) << 8), 2, OS); else if (pReg == Teak::P1 && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(abReg)) EmitConstant(0xD782 | encodeAxOp(abReg), 2, OS); else EmitConstant(0x5DF8 | (encodePxOp(pReg) << 1) | encodeBxOp(abReg), 2, OS); break; } case Teak::ADDL_memrn_a: EmitConstant(0x9480 | encodeRnOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::ADDV_imm16_RegNoBRegs16: if(MI.getOperand(0).getReg() == Teak::R6) EmitConstant(0x47BB, 2, OS); else EmitConstant(0x87E0 | encodeRegisterOp(MI.getOperand(0).getReg()), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::ADDV_imm16_memrn: EmitConstant(0x86E0 | encodeRnOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::AND_ab_ab_a: EmitConstant(0x6770 | (encodeAbOp(MI.getOperand(1).getReg()) << 2) | (encodeAbOp(MI.getOperand(2).getReg()) << 0) | (encodeAxOp(MI.getOperand(0).getReg()) << 12), 2, OS); break; // case Teak::AND_imm8_a: // EmitConstant(0xC200 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(1).getImm() & 0xFF), 2, OS); // break; case Teak::AND_imm16_a: EmitConstant(0x82C0 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::AND_regnobp016_a: if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0xD389 | (encodeAxOp(MI.getOperand(0).getReg()) << 4), 2, OS); else EmitConstant(0x82A0 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | encodeRegisterP0Op(MI.getOperand(1).getReg()), 2, OS); break; case Teak::AND_memimm16_a: EmitConstant(0xD4F9 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); if(MI.getOperand(1).isImm()) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; case Teak::AND_memrn_a: EmitConstant(0x8280 | encodeRnOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::BKREP_reg16: { unsigned lcReg = MI.getOperand(0).getReg(); if (lcReg == Teak::R6) { EmitConstant(0x8FDC, 2, OS); EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_bkrep_r6))); } else { EmitConstant(0x5D00 | encodeRegisterOp(lcReg), 2, OS); EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_bkrep_reg))); } break; } case Teak::BRR_rel7: case Teak::BRRCond_rel7: EmitConstant(0x5000 | (MI.getOpcode() == Teak::BRR_rel7 ? 0 : MI.getOperand(1).getImm()), 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), MCFixupKind(Teak::fixup_teak_rel7))); break; case Teak::BR_imm18: { EmitConstant(0x4180 | MI.getOperand(1).getImm(), 2, OS); EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), MCFixupKind(Teak::fixup_teak_call_imm18))); break; } case Teak::CALLR_rel7: EmitConstant(0x1000 | MI.getOperand(1).getImm(), 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), MCFixupKind(Teak::fixup_teak_rel7))); break; case Teak::CALL_imm18: { EmitConstant(0x41C0 | MI.getOperand(1).getImm(), 2, OS); EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), MCFixupKind(Teak::fixup_teak_call_imm18))); break; } case Teak::CHNG_imm16_regnob16: case Teak::CHNG_imm16_abl: case Teak::CHNG_imm16_abh: { unsigned aReg = MI.getOperand(0).getReg(); if(MI.getOpcode() == Teak::CHNG_imm16_abl) aReg = teakGetAbLReg(aReg); else if(MI.getOpcode() == Teak::CHNG_imm16_abh) aReg = teakGetAbHReg(aReg); if(aReg == Teak::R6) EmitConstant(0x47BA, 2, OS); else EmitConstant(0x85E0 | encodeRegisterOp(aReg), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; } case Teak::CHNG_imm16_sttmod: { EmitConstant(0x0038 | encodeSttModOp(MI.getOperand(0).getReg()), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; } case Teak::CHNG_imm16_memrn: EmitConstant(0x84E0 | encodeRnOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::CLR_ab: if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(MI.getOperand(0).getReg())) EmitConstant(0x6760 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(1).getImm(), 2, OS); else EmitConstant(0x6F60 | (encodeBxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(1).getImm(), 2, OS); break; case Teak::CLRR_ab: if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(MI.getOperand(0).getReg())) EmitConstant(0x67C0 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(1).getImm(), 2, OS); else EmitConstant(0x6F70 | (encodeBxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(1).getImm(), 2, OS); break; case Teak::CMP_ab_ab: { unsigned bReg = MI.getOperand(0).getReg(); unsigned aReg = MI.getOperand(1).getReg(); if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(bReg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(aReg)) EmitConstant(0x8CA0 | encodeRegisterP0Op(bReg) | (encodeAxOp(aReg) << 8), 2, OS); else if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(bReg) && TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(aReg)) EmitConstant(0x4D8C | (encodeAxOp(bReg) << 1) | encodeBxOp(aReg), 2, OS); else if(bReg == Teak::B0 && aReg == Teak::B1) EmitConstant(0xD483, 2, OS); else if(bReg == Teak::B1 && aReg == Teak::B0) EmitConstant(0xD583, 2, OS); else if(TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(bReg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(aReg)) EmitConstant(0xDA9A | (encodeBxOp(bReg) << 10) | encodeAxOp(aReg), 2, OS); else llvm_unreachable("Unsupported registers"); break; } case Teak::CMP_regnobp016_a: if(MI.getOperand(0).getReg() == Teak::R6) EmitConstant(0xD38E | (encodeAxOp(MI.getOperand(1).getReg()) << 4), 2, OS); else EmitConstant(0x8CA0 | encodeRegisterP0Op(MI.getOperand(0).getReg()) | (encodeAxOp(MI.getOperand(1).getReg()) << 8), 2, OS); break; case Teak::CMPU_regnob016_a: if(MI.getOperand(0).getReg() == Teak::R6) EmitConstant(0x8A63 | (encodeAxOp(MI.getOperand(1).getReg()) << 3), 2, OS); else EmitConstant(0x9EA0 | encodeRegisterOp(MI.getOperand(0).getReg()) | (encodeAxOp(MI.getOperand(1).getReg()) << 8), 2, OS); break; case Teak::CMP_imm8u_a: EmitConstant(0xCC00 | (encodeAxOp(MI.getOperand(1).getReg()) << 8) | (MI.getOperand(0).getImm() & 0xFF), 2, OS); break; case Teak::CMP_imm16_a: EmitConstant(0x8CC0 | (encodeAxOp(MI.getOperand(1).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::CMPV_imm16_RegNoBRegs16: if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0x47BE, 2, OS); else EmitConstant(0x8DE0 | encodeRegisterOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::CMP_memimm16_a: EmitConstant(0xD4FE | (encodeAxOp(MI.getOperand(1).getReg()) << 8), 2, OS); if(MI.getOperand(0).isImm()) EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(0).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; case Teak::CMP_memrn_a: EmitConstant(0x8C80 | encodeRnOp(MI.getOperand(0).getReg()) | (encodeAxOp(MI.getOperand(1).getReg()) << 8), 2, OS); break; case Teak::CMPU_memrn_a: EmitConstant(0x9E80 | encodeRnOp(MI.getOperand(0).getReg()) | (encodeAxOp(MI.getOperand(1).getReg()) << 8), 2, OS); break; case Teak::COPY_a: EmitConstant(0x67F0 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(2).getImm(), 2, OS); break; case Teak::DEC_a: EmitConstant(0x67E0 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(2).getImm(), 2, OS); break; case Teak::INC_a: EmitConstant(0x67D0 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(2).getImm(), 2, OS); break; case Teak::MODR_inc1: EmitConstant(0x0080 | encodeRnOp(MI.getOperand(0).getReg()) | (TeakStepZIDS::AddOne << 3), 2, OS); break; case Teak::MODR_dec1: EmitConstant(0x0080 | encodeRnOp(MI.getOperand(0).getReg()) | (TeakStepZIDS::SubOne << 3), 2, OS); break; case Teak::MODR_inc2: EmitConstant(0x4990 | encodeRnOp(MI.getOperand(0).getReg()), 2, OS); break; case Teak::MODR_dec2: EmitConstant(0x5DA0 | encodeRnOp(MI.getOperand(0).getReg()), 2, OS); break; case Teak::MOV_imm16_regnob16: case Teak::MOV_imm16neg_ab: case Teak::MOV_imm16_ab: case Teak::MOV_imm16_abh: { unsigned reg = MI.getOperand(0).getReg(); if(MI.getOpcode() == Teak::MOV_imm16_ab) reg = teakGetAbLReg(reg); else if(MI.getOpcode() == Teak::MOV_imm16_abh) reg = teakGetAbHReg(reg); if(reg == Teak::R6) EmitConstant(0x0023, 2, OS); else if(TeakMCRegisterClasses[Teak::RegNoBRegs16RegClassID].contains(reg) || TeakMCRegisterClasses[Teak::RegNoBRegs40RegClassID].contains(reg)) EmitConstant(0x5E00 | encodeRegisterOp(reg), 2, OS); else EmitConstant(0x5E20 | (encodeBxOp(reg) << 8), 2, OS); if(MI.getOperand(1).isImm() || MI.getOpcode() == Teak::MOV_imm16_abh) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; } case Teak::MOV_imm8s: { unsigned reg = MI.getOperand(0).getReg(); int64_t imm = MI.getOperand(1).getImm(); if (reg == Teak::A0H || reg == Teak::A1H) EmitConstant(0x2500 | (encodeAxhOp(reg) << 12) | (imm & 0xFF), 2, OS); else if (reg == Teak::EXT0) EmitConstant(0x2900 | (imm & 0xFF), 2, OS); else if (reg == Teak::EXT1) EmitConstant(0x2D00 | (imm & 0xFF), 2, OS); else if (reg == Teak::EXT2) EmitConstant(0x3900 | (imm & 0xFF), 2, OS); else if (reg == Teak::EXT3) EmitConstant(0x3D00 | (imm & 0xFF), 2, OS); else if (reg == Teak::R0 || reg == Teak::R1 || reg == Teak::R2 || reg == Teak::R3 || reg == Teak::R4 || reg == Teak::R5 || reg == Teak::R7 || reg == Teak::Y0) { EmitConstant(0x2300 | (encodeR0123457Y0Op(reg) << 10) | (imm & 0xFF), 2, OS); } else if(reg == Teak::SV) EmitConstant(0x0500 | (imm & 0xFF), 2, OS); else llvm_unreachable("mov imm8s unsupported register"); break; } case Teak::MOV_imm8u: EmitConstant(0x2100 | (encodeAxlOp(MI.getOperand(0).getReg()) << 12) | (MI.getOperand(1).getImm() & 0xFF), 2, OS); break; case Teak::MOV_ab_ab: EmitConstant(0xD290 | (encodeAbOp(MI.getOperand(1).getReg()) << 10) | (encodeAbOp(MI.getOperand(0).getReg()) << 5), 2, OS); break; case Teak::MOV_regnobp016_regnob16: case Teak::MOV_regnobp016_ab: case Teak::MOV_regnobp016_abl: case Teak::MOV_p0_ab: { unsigned dstReg = MI.getOperand(0).getReg(); if(MI.getOpcode() == Teak::MOV_regnobp016_abl) dstReg = teakGetAbLReg(dstReg); if(MI.getOperand(1).getReg() == Teak::P0 && !TeakMCRegisterClasses[Teak::ABRegsRegClassID].contains(dstReg)) llvm_unreachable("Register P0 can only be moved to ABx!"); if(MI.getOperand(1).getReg() == Teak::R6) { if(TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(dstReg)) EmitConstant(0xD481 | (encodeBxOp(dstReg) << 8), 2, OS); else EmitConstant(0x5F00 | encodeRegisterOp(dstReg), 2, OS); } else if(dstReg == Teak::R6) EmitConstant(0x5F60 | encodeRegisterOp(MI.getOperand(1).getReg()), 2, OS); else { if(TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(dstReg)) EmitConstant(0x5EC0 | encodeRegisterP0Op(MI.getOperand(1).getReg()) | (encodeBxOp(dstReg) << 5), 2, OS); else EmitConstant(0x5800 | encodeRegisterP0Op(MI.getOperand(1).getReg()) | (encodeRegisterOp(dstReg) << 5), 2, OS); } break; } case Teak::MOV_regnob16_memrn: case Teak::MOV_regnob16_memrn_postinc: case Teak::MOV_regnob16_memrn_postdec: case Teak::MOV_abl_memrn: { TeakStepZIDS::Steps step = TeakStepZIDS::Zero; if (MI.getOpcode() == Teak::MOV_regnob16_memrn_postdec) step = TeakStepZIDS::SubOne; else if (MI.getOpcode() == Teak::MOV_regnob16_memrn_postinc) step = TeakStepZIDS::AddOne; int opOffset = step == TeakStepZIDS::Zero ? 0 : 1; unsigned reg = MI.getOperand(opOffset).getReg(); if(MI.getOpcode() == Teak::MOV_abl_memrn) reg = teakGetAbLReg(reg); if(reg == Teak::R6) EmitConstant(0x1B00 | encodeRnOp(MI.getOperand(opOffset + 1).getReg()) | (step << 3), 2, OS); else EmitConstant(0x1800 | encodeRnOp(MI.getOperand(opOffset + 1).getReg()) | (step << 3) | (encodeRegisterOp(reg) << 5), 2, OS); break; } case Teak::MOV_memimm16_a: { EmitConstant(0xD4B8 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); if(MI.getOperand(1).isImm()) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; } case Teak::MOV_memrn_regnob16: case Teak::MOV_memrn_regnob16_postinc: case Teak::MOV_memrn_regnob16_postdec: case Teak::MOV_memrn_ab: case Teak::MOV_memrn_ab1: { unsigned dstReg = MI.getOperand(0).getReg(); TeakStepZIDS::Steps step = TeakStepZIDS::Zero; if (MI.getOpcode() == Teak::MOV_memrn_regnob16_postdec) step = TeakStepZIDS::SubOne; else if (MI.getOpcode() == Teak::MOV_memrn_regnob16_postinc) step = TeakStepZIDS::AddOne; if(MI.getOpcode() == Teak::MOV_memrn_ab1) dstReg = teakGetAbLReg(dstReg); if(dstReg == Teak::R6) EmitConstant(0x1B20 | encodeRnOp(MI.getOperand(1).getReg()) | (step << 3), 2, OS); else if(TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(dstReg)) EmitConstant(0x98C0 | encodeRnOp(MI.getOperand(1).getReg()) | (step << 3) | (encodeBxOp(dstReg) << 8), 2, OS); else EmitConstant(0x1C00 | encodeRnOp(MI.getOperand(1).getReg()) | (step << 3) | (encodeRegisterOp(dstReg) << 5), 2, OS); break; } case Teak::MOV_memr0425_ab: EmitConstant(0x4BC0 | (encodeMemR0425Op(MI.getOperand(1).getReg()) << 2) | (encodeAbOp(MI.getOperand(0).getReg()) << 4), 2, OS); break; case Teak::MOV_ab_memr0425: EmitConstant(0x4DC0 | (encodeMemR0425Op(MI.getOperand(1).getReg()) << 2) | (encodeAbOp(MI.getOperand(0).getReg()) << 4), 2, OS); break; case Teak::MOV_r7offset7s_a: EmitConstant(0xD880 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(2).getImm() & 0x7F), 2, OS); break; case Teak::MOV_r7offset16_a: EmitConstant(0xD498 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(2).getImm() & 0xFFFF, 2, OS); break; case Teak::MOV_al_r7offset7s: EmitConstant(0xDC80 | (encodeAxlOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(2).getImm() & 0x7F), 2, OS); break; case Teak::MOV_al_r7offset16: EmitConstant(0xD49C | (encodeAxlOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(2).getImm() & 0xFFFF, 2, OS); break; case Teak::MOV_al_memimm16: case Teak::MOV_al2_memimm16: { unsigned reg = teakGetAbLReg(MI.getOperand(0).getReg()); EmitConstant(0xD4BC | (encodeAxlOp(reg) << 8), 2, OS); if(MI.getOperand(1).isImm()) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; } case Teak::MPYI_y0_imm8s: EmitConstant(0x0800 | (MI.getOperand(2).getImm() & 0xFF), 2, OS); break; case Teak::MPY_y0_regnob16: if(MI.getOperand(2).getReg() == Teak::R6) EmitConstant(0x5EA0, 2, OS); else EmitConstant(0x8040 | encodeRegisterOp(MI.getOperand(2).getReg()), 2, OS); break; case Teak::NEG_a: EmitConstant(0x6790 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(2).getImm(), 2, OS); break; case Teak::NOP: EmitConstant(0, 2, OS); break; case Teak::NOT_a: EmitConstant(0x6780 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(2).getImm(), 2, OS); break; case Teak::OR_ab_ab_a: { unsigned dstReg = MI.getOperand(0).getReg(); unsigned bReg = MI.getOperand(1).getReg(); unsigned aReg = MI.getOperand(2).getReg(); if(TeakMCRegisterClasses[Teak::ABRegsRegClassID].contains(bReg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(aReg)) EmitConstant(0xD291 | (encodeAbOp(bReg) << 10) | (encodeAxOp(aReg) << 6) | (encodeAxOp(dstReg) << 5), 2, OS); else if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(bReg) && TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(aReg)) EmitConstant(0xD4A4 | (encodeAxOp(bReg) << 8) | (encodeBxOp(aReg) << 1) | encodeAxOp(dstReg), 2, OS); else if(bReg == Teak::B0 && TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(aReg)) EmitConstant(0xD3C4 | (encodeBxOp(aReg) << 1) | encodeAxOp(dstReg), 2, OS); else if(bReg == Teak::B1 && TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(aReg)) EmitConstant(0xD7C4 | (encodeBxOp(aReg) << 1) | encodeAxOp(dstReg), 2, OS); else llvm_unreachable("Unsupported registers"); break; } case Teak::OR_imm8u_a: EmitConstant(0xC000 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(1).getImm() & 0xFF), 2, OS); break; case Teak::OR_imm16_a: EmitConstant(0x80C0 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::OR_regnobp016_a: //case Teak::OR_regnobp016_al: { unsigned dstReg = MI.getOperand(0).getReg(); // if(dstReg == Teak::A0L) // dstReg = Teak::A0; // else if(dstReg == Teak::A1L) // dstReg = Teak::A1; if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0xD388 | (encodeAxOp(dstReg) << 4), 2, OS); else EmitConstant(0x80A0 | (encodeAxOp(dstReg) << 8) | encodeRegisterP0Op(MI.getOperand(1).getReg()), 2, OS); break; } case Teak::OR_memimm16_a: EmitConstant(0xD4F8 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); if(MI.getOperand(1).isImm()) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; case Teak::OR_memrn_a: EmitConstant(0x8080 | encodeRnOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::OR_r7offset7s_a: EmitConstant(0x4000 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(2).getImm() & 0x7F), 2, OS); break; case Teak::OR_r7offset16_a: EmitConstant(0xD4D8 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(2).getImm() & 0xFFFF, 2, OS); break; case Teak::RND_a: EmitConstant(0x67A0 | (encodeAxOp(MI.getOperand(0).getReg()) << 12) | MI.getOperand(2).getImm(), 2, OS); break; case Teak::RST_imm16_regnob16: case Teak::RST_imm16_abl: { unsigned aReg = MI.getOperand(0).getReg(); if(MI.getOpcode() == Teak::RST_imm16_abl) aReg = teakGetAbLReg(aReg); if(aReg == Teak::R6) EmitConstant(0x47B9, 2, OS); else EmitConstant(0x83E0 | encodeRegisterOp(aReg), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; } case Teak::RST_imm16_sttmod: { EmitConstant(0x4388 | encodeSttModOp(MI.getOperand(0).getReg()), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; } case Teak::RST_imm16_memrn: EmitConstant(0x82E0 | encodeRnOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::SET_imm16_regnob16: case Teak::SET_imm16_abl: case Teak::SET_imm16_abh: { unsigned aReg = MI.getOperand(0).getReg(); if(MI.getOpcode() == Teak::SET_imm16_abl) aReg = teakGetAbLReg(aReg); else if(MI.getOpcode() == Teak::SET_imm16_abh) aReg = teakGetAbHReg(aReg); if(aReg == Teak::R6) EmitConstant(0x47B8, 2, OS); else EmitConstant(0x81E0 | encodeRegisterOp(aReg), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; } case Teak::SET_imm16_sttmod: { EmitConstant(0x43C8 | encodeSttModOp(MI.getOperand(0).getReg()), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; } case Teak::SET_imm16_memrn: EmitConstant(0x80E0 | encodeRnOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::SHFC_arith_ab_ab_sv: EmitConstant(0xD280 | (encodeAbOp(MI.getOperand(1).getReg()) << 10) | (encodeAbOp(MI.getOperand(0).getReg()) << 5) | MI.getOperand(3).getImm(), 2, OS); break; case Teak::SHFI_arith_ab_ab: EmitConstant(0x9240 | (encodeAbOp(MI.getOperand(1).getReg()) << 10) | (encodeAbOp(MI.getOperand(0).getReg()) << 7) | (MI.getOperand(2).getImm() & 0x3F), 2, OS); break; case Teak::SUB_regnobp016_a: if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0xD38F | (encodeAxOp(MI.getOperand(0).getReg()) << 4), 2, OS); else EmitConstant(0x8EA0 | encodeRegisterP0Op(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::SUBL_regnob16_a: if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0x5E22 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); else EmitConstant(0x98A0 | encodeRegisterOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::SUB_imm8u_a: EmitConstant(0xCE00 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(1).getImm() & 0xFF), 2, OS); break; case Teak::SUB_imm16_a: EmitConstant(0x8EC0 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::SUBV_imm16_RegNoBRegs16: if(MI.getOperand(0).getReg() == Teak::R6) EmitConstant(0x47BF, 2, OS); else EmitConstant(0x8FE0 | encodeRegisterOp(MI.getOperand(0).getReg()), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::SUBV_imm16_memrn: EmitConstant(0x8EE0 | encodeRnOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::SUB_ab_ab: { unsigned dstReg = MI.getOperand(0).getReg(); unsigned reg = MI.getOperand(1).getReg(); if(TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(reg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(dstReg)) EmitConstant(0x8EA0 | encodeRegisterOp(reg) | (encodeAxOp(dstReg) << 8), 2, OS); else if(TeakMCRegisterClasses[Teak::ABRegsRegClassID].contains(reg) && TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(dstReg)) EmitConstant(0x8A61 | (encodeAbOp(reg) << 3) | (encodeBxOp(dstReg) << 8), 2, OS); else if(TeakMCRegisterClasses[Teak::BRegsRegClassID].contains(reg) && TeakMCRegisterClasses[Teak::ARegsRegClassID].contains(dstReg)) EmitConstant(0x8861 | (encodeBxOp(reg) << 4) | (encodeAxOp(dstReg) << 3), 2, OS); else llvm_unreachable("Unsupported registers"); break; } case Teak::SWAP_ab: { unsigned aReg = MI.getOperand(2).getReg(); unsigned bReg = MI.getOperand(3).getReg(); unsigned swapOp = (encodeAxOp(aReg) << 1) | encodeBxOp(bReg); EmitConstant(0x4980 | swapOp, 2, OS); break; } case Teak::TST0_imm16_RegNoBRegs16: if (MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0x47BC, 2, OS); else EmitConstant(0x89E0 | encodeRegisterOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::TST0_imm16_memrn: EmitConstant(0x88E0 | encodeRnOp(MI.getOperand(1).getReg()), 2, OS); EmitConstant(MI.getOperand(0).getImm() & 0xFFFF, 2, OS); break; case Teak::PUSH_regnob16: { unsigned reg = MI.getOperand(0).getReg(); if(reg == Teak::R6) EmitConstant(0xD4D7, 2, OS); else if(TeakMCRegisterClasses[Teak::RegNoBRegs16RegClassID].contains(reg)) EmitConstant(0x5E40 | encodeRegisterOp(reg), 2, OS); else llvm_unreachable("Unsupported register"); break; } case Teak::PUSH_ararpsttmod: EmitConstant(0xD3D0 | encodeArArpSttModOp(MI.getOperand(0).getReg()), 2, OS); break; case Teak::PUSH_abe: EmitConstant(0xD7C8 | (encodeAbeOp(MI.getOperand(0).getReg()) << 1), 2, OS); break; case Teak::POP_regnob16: { unsigned reg = MI.getOperand(0).getReg(); if(reg == Teak::R6) EmitConstant(0x0024, 2, OS); else if(TeakMCRegisterClasses[Teak::RegNoBRegs16RegClassID].contains(reg)) EmitConstant(0x5E60 | encodeRegisterOp(reg), 2, OS); else llvm_unreachable("Unsupported register"); break; } case Teak::POP_ararpsttmod: EmitConstant(0x80C7 | (encodeArArpSttModOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::POP_abe: EmitConstant(0x47B4 | encodeAbeOp(MI.getOperand(0).getReg()), 2, OS); break; case Teak::RET: EmitConstant(0x4580 | MI.getOperand(0).getImm(), 2, OS); break; case Teak::RawAsmOp: EmitConstant(MI.getOperand(0).getImm(), 2, OS); break; case Teak::RawAsmOpExtended: EmitConstant(MI.getOperand(0).getImm(), 2, OS); EmitConstant(MI.getOperand(1).getImm(), 2, OS); break; case Teak::XOR_imm8u_a: EmitConstant(0xC400 | (encodeAxOp(MI.getOperand(0).getReg()) << 8) | (MI.getOperand(1).getImm() & 0xFF), 2, OS); break; case Teak::XOR_imm16_a: EmitConstant(0x84C0 | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); break; case Teak::XOR_memimm16_a: EmitConstant(0xD4FA | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); if(MI.getOperand(1).isImm()) EmitConstant(MI.getOperand(1).getImm() & 0xFFFF, 2, OS); else { EmitConstant(0, 2, OS); Fixups.push_back(MCFixup::create(0, MI.getOperand(1).getExpr(), MCFixupKind(Teak::fixup_teak_ptr_imm16))); } break; case Teak::XOR_memrn_a: EmitConstant(0x8480 | encodeRnOp(MI.getOperand(1).getReg()) | (encodeAxOp(MI.getOperand(0).getReg()) << 8), 2, OS); break; case Teak::XOR_regnobp016_a: case Teak::XOR_a_a: { unsigned dstReg = MI.getOperand(0).getReg(); if(MI.getOperand(1).getReg() == Teak::R6) EmitConstant(0xD38A | (encodeAxOp(dstReg) << 4), 2, OS); else EmitConstant(0x84A0 | (encodeAxOp(dstReg) << 8) | encodeRegisterP0Op(MI.getOperand(1).getReg()), 2, OS); break; } default: dbgs() << "Unsupported opcode " << MI.getOpcode() << "!\n"; llvm_unreachable("Unsupported opcode"); EmitConstant(0, 2, OS); break; } ++MCNumEmitted; } #include "TeakGenMCCodeEmitter.inc"