| Index: src/IceAssemblerMIPS32.h
|
| diff --git a/src/IceAssemblerMIPS32.h b/src/IceAssemblerMIPS32.h
|
| index 9d78a5b93516f5d7b316ad9aadb3146fac34f6f7..eefb1b2004e7f0e55c73013bba50967dd4b17d15 100644
|
| --- a/src/IceAssemblerMIPS32.h
|
| +++ b/src/IceAssemblerMIPS32.h
|
| @@ -1,13 +1,5 @@
|
| //===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===//
|
| //
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -//
|
| -// Modified by the Subzero authors.
|
| -//
|
| -//===----------------------------------------------------------------------===//
|
| -//
|
| // The Subzero Code Generator
|
| //
|
| // This file is distributed under the University of Illinois Open Source
|
| @@ -26,10 +18,15 @@
|
| #include "IceAssembler.h"
|
| #include "IceDefs.h"
|
| #include "IceFixups.h"
|
| +#include "IceInstMIPS32.h"
|
| +#include "IceTargetLowering.h"
|
|
|
| namespace Ice {
|
| namespace MIPS32 {
|
|
|
| +using IValueT = uint32_t;
|
| +using IOffsetT = int32_t;
|
| +
|
| class AssemblerMIPS32 : public Assembler {
|
| AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
|
| AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
|
| @@ -41,34 +38,113 @@ public:
|
| assert(!use_far_branches);
|
| (void)use_far_branches;
|
| }
|
| - ~AssemblerMIPS32() override = default;
|
| + ~AssemblerMIPS32() override {
|
| + if (BuildDefs::asserts()) {
|
| + for (const Label *Label : CfgNodeLabels) {
|
| + Label->finalCheck();
|
| + }
|
| + for (const Label *Label : LocalLabels) {
|
| + Label->finalCheck();
|
| + }
|
| + }
|
| + }
|
| +
|
| + void trap();
|
| +
|
| + void nop();
|
| +
|
| + void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
|
| + const uint32_t Imm, const char *InsnName);
|
| +
|
| + void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
|
| + const uint32_t Sa, const char *InsnName);
|
| +
|
| + void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
|
| + const Operand *OpRt, const char *InsnName);
|
| +
|
| + void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
|
| + const Operand *OpRt, IOffsetT Offset);
|
| +
|
| + void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
|
| +
|
| + void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
|
| +
|
| + void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
|
| +
|
| + void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
|
| +
|
| + void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
|
| +
|
| + void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
|
| +
|
| + void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
|
| +
|
| + void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
|
| +
|
| + void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
|
| +
|
| + void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
|
| +
|
| + void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
|
| +
|
| + void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
|
| +
|
| + void move(const Operand *OpRd, const Operand *OpRs);
|
| +
|
| + void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
|
| +
|
| + void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
|
| +
|
| + void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
|
| +
|
| + void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
|
| +
|
| + void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
|
| +
|
| + void ret(void);
|
| +
|
| + void b(Label *TargetLabel);
|
| +
|
| + void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
|
| + const Operand *OpRt, Label *TargetLabel);
|
| +
|
| + void bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
|
| + Label *TargetLabel);
|
|
|
| void alignFunction() override {
|
| - llvm::report_fatal_error("Not yet implemented.");
|
| + const SizeT Align = 1 << getBundleAlignLog2Bytes();
|
| + SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
|
| + constexpr SizeT InstSize = sizeof(IValueT);
|
| + assert(BytesNeeded % InstMIPS32::InstSize == 0);
|
| + while (BytesNeeded > 0) {
|
| + trap();
|
| + BytesNeeded -= InstSize;
|
| + }
|
| }
|
|
|
| SizeT getBundleAlignLog2Bytes() const override { return 4; }
|
|
|
| const char *getAlignDirective() const override { return ".p2alignl"; }
|
|
|
| - llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
|
| - // TODO(reed kotler) . Find out what this should be.
|
| - static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0};
|
| - return llvm::ArrayRef<uint8_t>(Padding, 4);
|
| - }
|
| + llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
|
|
|
| - void padWithNop(intptr_t Padding) override {
|
| - (void)Padding;
|
| - llvm::report_fatal_error("Not yet implemented.");
|
| - }
|
| + void padWithNop(intptr_t Padding) override;
|
| +
|
| + void bind(Label *label);
|
| +
|
| + void emitTextInst(const std::string &Text, SizeT InstSize);
|
|
|
| Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
|
| - (void)NodeNumber;
|
| - llvm_unreachable("Not yet implemented.");
|
| + assert(NodeNumber < CfgNodeLabels.size());
|
| + return CfgNodeLabels[NodeNumber];
|
| }
|
|
|
| - void bindCfgNodeLabel(const CfgNode *) override {
|
| - llvm::report_fatal_error("Not yet implemented.");
|
| + Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
|
| + return getOrCreateLabel(NodeNumber, CfgNodeLabels);
|
| + }
|
| +
|
| + Label *getOrCreateLocalLabel(SizeT Number) {
|
| + return getOrCreateLabel(Number, LocalLabels);
|
| }
|
|
|
| bool fixupIsPCRel(FixupKind Kind) const override {
|
| @@ -82,6 +158,22 @@ public:
|
|
|
| private:
|
| ENABLE_MAKE_UNIQUE;
|
| +
|
| + using LabelVector = std::vector<Label *>;
|
| + LabelVector CfgNodeLabels;
|
| + LabelVector LocalLabels;
|
| +
|
| + // Returns the offset encoded in the branch instruction Inst.
|
| + static IOffsetT decodeBranchOffset(IValueT Inst);
|
| +
|
| + Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
|
| +
|
| + void bindCfgNodeLabel(const CfgNode *) override;
|
| +
|
| + void emitInst(IValueT Value) {
|
| + AssemblerBuffer::EnsureCapacity _(&Buffer);
|
| + Buffer.emit<IValueT>(Value);
|
| + }
|
| };
|
|
|
| } // end of namespace MIPS32
|
|
|