Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- /dev/null +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -0,0 +1,172 @@ +//===-- MipsMCCodeEmitter.h - Convert Mips 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 defines the MipsMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// +// + +#ifndef MIPS_MC_CODE_EMITTER_H +#define MIPS_MC_CODE_EMITTER_H + +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/Support/DataTypes.h" +#include + +using namespace llvm; + +//Forward declarations. +namespace llvm { +class MCContext; +class MCExpr; +class MCInst; +class MCInstrInfo; +class MCFixup; +class MCOperand; +class MCSubtargetInfo; +class raw_ostream; +} + +namespace { + +// Struct used to store the register usage for a translation unit. +// In theory Operating Systems can inspect the .reginfo section or +// .Mips.Options to decide what registers need to be saved or which +// coprocessors the program uses. +struct MipsRegInfo { + uint32_t ri_gprmask; + uint32_t ri_cprmask[4]; + union { + int32_t ri_gp_value_32; // ELF32 (ARCH=Mips32 or ABI=n32) + int64_t ri_gp_value_64; // ELF64 (ARCH=Mips64 and ABI=n64) + }; +}; + +class MipsMCCodeEmitter : public MCCodeEmitter { + MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; + void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; + const MCInstrInfo &MCII; + MCContext &Ctx; + bool IsLittleEndian; + mutable MipsRegInfo RegInfo; + + bool isMicroMips(const MCSubtargetInfo &STI) const; + +public: + MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) : + MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) { } + + ~MipsMCCodeEmitter() {} + + void EmitByte(unsigned char C, raw_ostream &OS) const; + + void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, + raw_ostream &OS) const; + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchJumpOpValue - Return binary encoding of the jump + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTargetOpValue - Return binary encoding of the branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTargetOpValue - Return binary encoding of the microMIPS branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getMachineOpValue - Return binary encoding of operand. If the machin + // operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getLSAImmEncoding - Return binary encoding of LSA immediate. + unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned + getExprOpValue(const MCExpr *Expr,SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // Returns mask of General Purpose Registers used by the TU (one bit for each + // register; register 31 being the most significant bit). This should only be + // called after all instructions are encoded otherwise this information will + // probably be incomplete. + uint32_t getRI_gprmask() { return RegInfo.ri_gprmask; }; + + // Returns mask of Coprocessor Registers used by the TU (one bit for each + // register; register 31 being the most significant bit). This should only be + // called after all instructions are encoded otherwise this information will + // probably be incomplete. + uint32_t getRI_cprmask(int CoPro) { + if (CoPro < 0 || CoPro > 3) { + assert (0 && "Invalid CoPro"); + return (uint32_t)-1; + } + + return RegInfo.ri_cprmask[CoPro]; + }; + + // Returns the value of $gp. It is set to 0 at this stage and the static + // linker is responsible to compute its final value. + int32_t getRI_gpValue32() { return RegInfo.ri_gp_value_32; }; + + // Returns the value of $gp. It is set to 0 at this stage and the static + // linker is responsible to compute its final value. + int64_t getRI_gpValue64() { return RegInfo.ri_gp_value_64; }; + +}; // class MipsMCCodeEmitter +} // namespace + +#endif Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -11,155 +11,54 @@ // //===----------------------------------------------------------------------===// // + #define DEBUG_TYPE "mccodeemitter" -#include "MCTargetDesc/MipsBaseInfo.h" + +#include "MipsMCCodeEmitter.h" #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCExpr.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/ADT/SmallVector.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/MCFixup.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/raw_ostream.h" +#include + +#define GET_REGINFO_ENUM +#include "MipsGenRegisterInfo.inc" +#undef GET_REGINFO_ENUM #define GET_INSTRMAP_INFO +#define GET_INSTRINFO_ENUM #include "MipsGenInstrInfo.inc" - -using namespace llvm; - -namespace { -class MipsMCCodeEmitter : public MCCodeEmitter { - MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; - const MCInstrInfo &MCII; - MCContext &Ctx; - bool IsLittleEndian; - - bool isMicroMips(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits() & Mips::FeatureMicroMips; - } - -public: - MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) : - MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) { } - - ~MipsMCCodeEmitter() {} - - void EmitByte(unsigned char C, raw_ostream &OS) const { - OS << (char)C; - } - - void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, - raw_ostream &OS) const { - // Output the instruction encoding in little endian byte order. - // Little-endian byte ordering: - // mips32r2: 4 | 3 | 2 | 1 - // microMIPS: 2 | 1 | 4 | 3 - if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { - EmitInstruction(Val>>16, 2, STI, OS); - EmitInstruction(Val, 2, STI, OS); - } else { - for (unsigned i = 0; i < Size; ++i) { - unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; - EmitByte((Val >> Shift) & 0xff, OS); - } - } - } - - void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getBinaryCodeForInstr - TableGen'erated function for getting the - // binary encoding for an instruction. - uint64_t getBinaryCodeForInstr(const MCInst &MI, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchJumpOpValue - Return binary encoding of the jump - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValue - Return binary encoding of the branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValue - Return binary encoding of the microMIPS branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getMachineOpValue - Return binary encoding of operand. If the machin - // operand requires relocation, record the relocation and return zero. - unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - // getLSAImmEncoding - Return binary encoding of LSA immediate. - unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned - getExprOpValue(const MCExpr *Expr,SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - -}; // class MipsMCCodeEmitter -} // namespace - -MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx) +#undef GET_INSTRMAP_INFO +#undef GET_INSTRINFO_ENUM + +#define GET_SUBTARGETINFO_ENUM +#include "MipsGenSubtargetInfo.inc" +#undef GET_SUBTARGETINFO_ENUM + +namespace llvm { +MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { return new MipsMCCodeEmitter(MCII, Ctx, false); } -MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx) +MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { return new MipsMCCodeEmitter(MCII, Ctx, true); } - +} // End of namespace llvm. // If the D instruction has a shift amount that is greater // than 31 (checked in calling routine), lower it to a D32 instruction @@ -226,6 +125,34 @@ return; } +bool MipsMCCodeEmitter:: +isMicroMips(const MCSubtargetInfo &STI) const { + return STI.getFeatureBits() & Mips::FeatureMicroMips; +} + +void MipsMCCodeEmitter:: +EmitByte(unsigned char C, raw_ostream &OS) const { + OS << (char)C; +} + +void MipsMCCodeEmitter:: +EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, + raw_ostream &OS) const { + // Output the instruction encoding in little endian byte order. + // Little-endian byte ordering: + // mips32r2: 4 | 3 | 2 | 1 + // microMIPS: 2 | 1 | 4 | 3 + if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { + EmitInstruction(Val>>16, 2, STI, OS); + EmitInstruction(Val, 2, STI, OS); + } else { + for (unsigned i = 0; i < Size; ++i) { + unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; + EmitByte((Val >> Shift) & 0xff, OS); + } + } +} + /// EncodeInstruction - Emit the instruction. /// Size the instruction with Desc.getSize(). void MipsMCCodeEmitter:: @@ -281,6 +208,54 @@ if (!Size) llvm_unreachable("Desc.getSize() returns 0"); + const MCRegisterInfo *MCRegInfo = Ctx.getRegisterInfo(); + + // Capture the register usage for this instruction and update RegInfo. + for (unsigned NumOp = 0; NumOp < TmpInst.getNumOperands(); ++NumOp) { + MCOperand &Op = TmpInst.getOperand(NumOp); + + if (!Op.isReg()) + continue; + + int16_t RegClass = Desc.OpInfo[NumOp].RegClass; + unsigned RegClassID = Ctx.getRegisterInfo()->getRegClass(RegClass).getID(); + unsigned EncVal = MCRegInfo->getEncodingValue(Op.getReg()); + + switch (RegClassID) { + default: + // At the moment we don't support other coprocessors other than copro1. + // If we ever support others, we should update this switch statement with + // the new register classes. + break; + case (Mips::GPR32RegClassID): + case (Mips::GPR64RegClassID): + RegInfo.ri_gprmask |= (1 << EncVal); + break; + // FPU can be configured in several distinct ways. We have to distinguish + // between operands that represent only one FP register from operands that + // are implicitly two FP registers (one even + one odd). + + // FGR32 - Operand representing a single-precision FP register. + // FGR64 - Operand representing a 64-bit register on an FPU with 64-bit + // wide registers. + // MSA registers clobber part of the FP registers. + case (Mips::FGR32RegClassID): + case (Mips::FGR64RegClassID): + case (Mips::MSA128BRegClassID): + case (Mips::MSA128HRegClassID): + case (Mips::MSA128WRegClassID): + case (Mips::MSA128DRegClassID): + RegInfo.ri_cprmask[1] |= (1 << EncVal); + break; + // 64-bit register on an FPU configured with mfp32. Two FP register + // affected (even + odd). + case (Mips::AFGR64RegClassID): + RegInfo.ri_cprmask[1] |= (1 << EncVal); + RegInfo.ri_cprmask[1] |= (1 << (EncVal + 1)); + break; + } + } + EmitInstruction(Binary, Size, STI, OS); } Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "InstPrinter/MipsInstPrinter.h" +#include "MipsMCCodeEmitter.h" #include "MipsMCTargetDesc.h" #include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" @@ -186,6 +187,8 @@ MCStreamer &OS = getStreamer(); Triple T(STI.getTargetTriple()); uint64_t Features = STI.getFeatureBits(); + MCCodeEmitter &Emitter = MCA.getEmitter(); + MipsMCCodeEmitter &MipsMCE = static_cast(Emitter); if (T.isArch64Bit() && (Features & Mips::FeatureN64)) { const MCSectionELF *Sec = Context.getELFSection( @@ -197,25 +200,25 @@ OS.EmitIntValue(40, 1); // size OS.EmitIntValue(0, 2); // section OS.EmitIntValue(0, 4); // info - OS.EmitIntValue(0, 4); // ri_gprmask + OS.EmitIntValue(MipsMCE.getRI_gprmask(), 4); // ri_gprmask OS.EmitIntValue(0, 4); // pad - OS.EmitIntValue(0, 4); // ri_cpr[0]mask - OS.EmitIntValue(0, 4); // ri_cpr[1]mask - OS.EmitIntValue(0, 4); // ri_cpr[2]mask - OS.EmitIntValue(0, 4); // ri_cpr[3]mask - OS.EmitIntValue(0, 8); // ri_gp_value + OS.EmitIntValue(MipsMCE.getRI_cprmask(0), 4); // ri_cpr[0]mask + OS.EmitIntValue(MipsMCE.getRI_cprmask(1), 4); // ri_cpr[1]mask + OS.EmitIntValue(MipsMCE.getRI_cprmask(2), 4); // ri_cpr[2]mask + OS.EmitIntValue(MipsMCE.getRI_cprmask(3), 4); // ri_cpr[3]mask + OS.EmitIntValue(MipsMCE.getRI_gpValue64(), 8); // ri_gp_value } else { const MCSectionELF *Sec = Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, SectionKind::getMetadata()); OS.SwitchSection(Sec); - OS.EmitIntValue(0, 4); // ri_gprmask - OS.EmitIntValue(0, 4); // ri_cpr[0]mask - OS.EmitIntValue(0, 4); // ri_cpr[1]mask - OS.EmitIntValue(0, 4); // ri_cpr[2]mask - OS.EmitIntValue(0, 4); // ri_cpr[3]mask - OS.EmitIntValue(0, 4); // ri_gp_value + OS.EmitIntValue(MipsMCE.getRI_gprmask(), 4); // ri_gprmask + OS.EmitIntValue(MipsMCE.getRI_cprmask(0), 4); // ri_cpr[0]mask + OS.EmitIntValue(MipsMCE.getRI_cprmask(1), 4); // ri_cpr[1]mask + OS.EmitIntValue(MipsMCE.getRI_cprmask(2), 4); // ri_cpr[2]mask + OS.EmitIntValue(MipsMCE.getRI_cprmask(3), 4); // ri_cpr[3]mask + OS.EmitIntValue(MipsMCE.getRI_gpValue32(), 4); // ri_gp_value } } Index: test/MC/Mips/mips-reginfo-fp32.s =================================================================== --- /dev/null +++ test/MC/Mips/mips-reginfo-fp32.s @@ -0,0 +1,34 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -filetype=obj -o - | \ +# RUN: llvm-readobj -s -section-data | \ +# RUN: FileCheck %s + +# CHECK: Section { +# CHECK: Index: +# CHECK: Name: .reginfo (12) +# CHECK: Type: SHT_MIPS_REGINFO (0x70000006) +# CHECK: Flags [ (0x2) +# CHECK: SHF_ALLOC (0x2) +# CHECK: ] +# CHECK: Size: 24 +# CHECK: SectionData ( +# CHECK: 0000: 01010101 00000000 C0007535 00000000 +# CHECK: 0010: 00000000 00000000 +# CHECK: ) +# CHECK: } + +.text + add $0,$0,$0 + add $8,$0,$0 + add $16,$0,$0 + add $24,$0,$0 + +# abs.s - Reads and writes from/to $f0. + abs.s $f0,$f0 +# round.w.d - Reads $f4 and $f5 and writes to $f2. + round.w.d $f2,$f4 +# ceil.w.s - Reads $f8 and writes to $f10. + ceil.w.s $f10, $f8 +# cvt.s.d - Reads from $f12 and $f13 and writes to $f14 + cvt.s.d $f14, $f12 +# abs.d - Reads from $f30 and $f31 and writes to $f30 and $f31. + abs.d $f30,$f30 Index: test/MC/Mips/mips-reginfo-fp64.s =================================================================== --- /dev/null +++ test/MC/Mips/mips-reginfo-fp64.s @@ -0,0 +1,60 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa,+fp64 -filetype=obj -o - | \ +# RUN: llvm-readobj -s -section-data | \ +# RUN: FileCheck %s -check-prefix=ELF32 + +# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64r2 -mattr=+msa,+fp64,-n64,+n32 -filetype=obj -o - | \ +# RUN: llvm-readobj -s -section-data | \ +# RUN: FileCheck %s -check-prefix=ELF32 + +# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64r2 -mattr=+msa,+fp64,+n64 -filetype=obj -o - | \ +# RUN: llvm-readobj -s -section-data | \ +# RUN: FileCheck %s -check-prefix=ELF64 + +# ELF32: Section { +# ELF32: Name: .reginfo (12) +# ELF32: Type: SHT_MIPS_REGINFO (0x70000006) +# ELF32: Flags [ (0x2) +# ELF32: SHF_ALLOC (0x2) +# ELF32: ] +# ELF32: Size: 24 +# ELF32: SectionData ( +# ELF32: 0000: 01010101 00000000 4C005515 00000000 +# ELF32: 0010: 00000000 00000000 +# ELF32: ) +# ELF32: } + +# ELF64: Section { +# ELF64: Name: .MIPS.options (12) +# ELF64: Type: SHT_MIPS_OPTIONS (0x7000000D) +# ELF64: Flags [ (0x8000002) +# ELF64: SHF_ALLOC (0x2) +# ELF64: SHF_MIPS_NOSTRIP (0x8000000) +# ELF64: ] +# ELF64: Size: 40 +# ELF64: SectionData ( +# ELF64: 0000: 01280000 00000000 01010101 00000000 +# ELF64: 0010: 00000000 4C005515 00000000 00000000 +# ELF64: 0020: 00000000 00000000 +# ELF64: ) +# ELF64: } + +.text + add $0,$0,$0 + add $8,$0,$0 + add $16,$0,$0 + add $24,$0,$0 + +# abs.s - Reads and writes from/to $f0. + abs.s $f0,$f0 +# round.w.d - Reads $f4 and writes to $f2. + round.w.d $f2,$f4 +# ceil.w.s - Reads $f8 and writes to $f10. + ceil.w.s $f10, $f8 +# cvt.s.d - Reads from $f12 and writes to $f14. + cvt.s.d $f14, $f12 +# abs.d - Reads from $f30 and writes to $f30. + abs.d $f30,$f30 + +# Read and write from/to $f26 and $f27 + add_a.b $w26,$w26,$w26 + add_a.b $w27,$w27,$w27