Exemple #1
0
PhysRegSaver::PhysRegSaver(Vout& v, RegSet regs)
    : m_v(v)
    , m_regs(regs)
{
    auto gpr = m_regs & abi().gp();
    auto xmm = m_regs & abi().simd();
    auto const sp = rsp();

    m_adjust = gpr.size() & 0x1 ? 8 : 0;

    if (!xmm.empty()) {
        v << lea{sp[-16 * xmm.size()], sp};

        int offset = 0;
        xmm.forEach([&] (PhysReg r) {
            v << storeups{r, sp[offset]};
            offset += 16;
        });
    }

    gpr.forEach([&] (PhysReg r) {
        v << push{r};
    });

    if (m_adjust) {
        v << lea{sp[-m_adjust], sp};
    }
}
Exemple #2
0
Vauto::~Vauto() {
  for (auto& b : unit().blocks) {
    if (!b.code.empty()) {
      // Found at least one nonempty block.  Finish up.
      if (!main().closed()) main() << fallthru{};

      // Prevent spurious printir traces.
      Trace::Bump bumper{Trace::printir, 10};

      switch (arch()) {
        case Arch::X64:
          optimizeX64(unit(), abi(m_kind));
          emitX64(unit(), m_text, nullptr);
          break;
        case Arch::ARM:
          finishARM(unit(), m_text, abi(m_kind), nullptr);
          break;
      }
      return;
    }
  }
}
Exemple #3
0
PhysRegSaver::~PhysRegSaver() {
    auto& v = m_v;
    auto const sp = rsp();

    if (m_adjust) {
        v << lea{sp[m_adjust], sp};
    }

    auto gpr = m_regs & abi().gp();
    auto xmm = m_regs & abi().simd();

    gpr.forEachR([&] (PhysReg r) {
        v << pop{r};
    });

    if (!xmm.empty()) {
        int offset = 0;
        xmm.forEach([&] (PhysReg r) {
            v << loadups{sp[offset], r};
            offset += 16;
        });
        v << lea{sp[offset], sp};
    }
}
Exemple #4
0
bool GccToolChain::fromMap(const QVariantMap &data)
{
    if (!ToolChain::fromMap(data))
        return false;

    m_compilerCommand = Utils::FileName::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString());
    m_targetAbi = Abi(data.value(QLatin1String(targetAbiKeyC)).toString());
    QStringList abiList = data.value(QLatin1String(supportedAbisKeyC)).toStringList();
    m_supportedAbis.clear();
    foreach (const QString &a, abiList) {
        ProjectExplorer::Abi abi(a);
        if (!abi.isValid())
            continue;
        m_supportedAbis.append(abi);
    }
Exemple #5
0
PhysReg r_svcreq_sf() {
  return abi().sf.choose();
}
Exemple #6
0
int main(void)
{
	printf("%s\n", abi());
	return 0;
}
Exemple #7
0
PhysReg r_svcreq_sf() { return abi().sf.findFirst(); }
Exemple #8
0
jit::vector<VMoveInfo>
doVregMoves(Vunit& unit, MovePlan& moves) {
  constexpr auto N = 64;
  assertx(abi().all().size() <= N);
  jit::vector<VMoveInfo> howTo;
  CycleInfo cycles[N];
  size_t num_cycles = 0;
  PhysReg::Map<int> outDegree;
  PhysReg::Map<int> index;

  for (auto reg : moves) {
    // Ignore moves from a register to itself
    if (reg == moves[reg]) moves[reg] = InvalidReg;
    index[reg] = -1;
  }

  // Iterate over the nodes filling in outDegree[] and cycles[] as we go
  int nextIndex = 0;
  for (auto reg : moves) {
    // skip registers we've visited already.
    if (index[reg] >= 0) continue;

    // Begin walking a path from reg.
    for (auto node = reg;;) {
      assertx(nextIndex < N);
      index[node] = nextIndex++;
      auto next = moves[node];
      if (next != InvalidReg) {
        ++outDegree[next];
        if (index[next] < 0) {
          // There is an edge from node to next, and next has not been
          // visited.  Extend current path to include next, then loop.
          node = next;
          continue;
        }
        // next already visited; check if next is on current path.
        if (index[next] >= index[reg]) {
          // found a cycle.
          assert(num_cycles < N);
          cycles[num_cycles++] = { next, nextIndex - index[next] };
        }
      }
      break;
    }
  }

  // Handle all moves that aren't part of a cycle. Only nodes with outdegree
  // zero are put into the queue, which is how nodes in a cycle get excluded.
  {
    PhysReg q[N];
    int qBack = 0;
    auto enque = [&](PhysReg r) { assertx(qBack < N); q[qBack++] = r; };
    for (auto node : outDegree) {
      if (outDegree[node] == 0) enque(node);
    }
    for (int i = 0; i < qBack; ++i) {
      auto node = q[i];
      if (moves[node] == InvalidReg) continue;
      auto nextNode = moves[node];
      howTo.push_back({VMoveInfo::Kind::Move, nextNode, node});
      --outDegree[nextNode];
      if (outDegree[nextNode] == 0) enque(nextNode);
    }
  }

  // Deal with any cycles we encountered
  for (size_t i = 0; i < num_cycles; ++i) {
    auto const& cycle = cycles[i];
    // can't use xchg if one of the registers is SIMD
    bool hasSIMDReg = cycleHasSIMDReg(cycle, moves);
    if (cycle.length == 2 && !hasSIMDReg) {
      auto v = cycle.node;
      auto w = moves[v];
      howTo.push_back({VMoveInfo::Kind::Xchg, w, v});
    } else if (cycle.length == 3 && !hasSIMDReg) {
      auto v = cycle.node;
      auto w = moves[v];
      howTo.push_back({VMoveInfo::Kind::Xchg, w, v});
      auto x = moves[w];
      howTo.push_back({VMoveInfo::Kind::Xchg, x, w});
    } else {
      auto t = unit.makeReg();
      auto v = cycle.node;
      howTo.push_back({VMoveInfo::Kind::Move, v, t});
      auto w = v;
      auto x = moves[w];
      while (x != v) {
        howTo.push_back({VMoveInfo::Kind::Move, x, w});
        w = x;
        x = moves[w];
      }
      howTo.push_back({VMoveInfo::Kind::Move, t, w});
    }
  }
  return howTo;
}
Exemple #9
0
int PhysReg::getNumSIMD() {
  return abi().simd().size();
}
Exemple #10
0
int PhysReg::getNumGP() {
  return abi().gp().size();
}