blob: e062ae8c43665d4a45556531dfaada77506f4fe6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef INSTRUCTIONS_H
#define INSTRUCTIONS_H
#include <vector>
#include <magma_util/instruction_writer.h>
#include <magma_util/macros.h>
class Packet {
public:
static uint32_t parity(uint32_t v) {
// Based on http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
// Modified for odd parity
v ^= v >> 28;
v ^= v >> 24;
v ^= v >> 20;
v ^= v >> 16;
v ^= v >> 12;
v ^= v >> 8;
v ^= v >> 4;
v &= 0xf;
return (0x9669 >> v) & 1;
}
};
// For writing registers
class Packet4 : public Packet {
public:
static constexpr uint32_t kPacketType = 0x40000000;
static void write(magma::InstructionWriter* writer, uint32_t register_index, uint32_t value) {
DASSERT(!(register_index & 0xFFFC0000));
uint8_t count = 1;
uint32_t header = kPacketType;
header |= count;
header |= (parity(count) << 7);
header |= (register_index << 8);
header |= (parity(register_index) << 27);
writer->Write32(header);
writer->Write32(value);
}
};
// For a range of tasks determined by OpCode.
class Packet7 : public Packet {
public:
static constexpr uint32_t kPacketType = 0x70000000;
enum class OpCode {
CpRegisterToMemory = 62,
CpMeInit = 72,
};
static void write(magma::InstructionWriter* writer, OpCode opcode,
const std::vector<uint32_t>& packet) {
uint16_t count = static_cast<uint16_t>(packet.size());
DASSERT(count == packet.size());
DASSERT(!(count & 0x8000));
uint32_t op = static_cast<uint32_t>(opcode);
DASSERT(!(op & 0x80));
uint32_t header = kPacketType;
header |= count;
header |= (parity(count) << 15);
header |= (op << 16);
header |= (parity(op) << 23);
writer->Write32(header);
for (uint32_t value : packet) {
writer->Write32(value);
}
}
};
#endif // INSTRUCTIONS_H