diff --git a/src/asahi/compiler/agx_opcodes.py b/src/asahi/compiler/agx_opcodes.py new file mode 100644 index 00000000000..d7b0d866807 --- /dev/null +++ b/src/asahi/compiler/agx_opcodes.py @@ -0,0 +1,185 @@ +""" +Copyright (C) 2021 Alyssa Rosenzweig + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +opcodes = {} +immediates = {} + +class Opcode(object): + def __init__(self, name, dests, srcs, imms, is_float, can_eliminate, encoding_16, encoding_32): + self.name = name + self.dests = dests + self.srcs = srcs + self.imms = imms + self.is_float = is_float + self.can_eliminate = can_eliminate + self.encoding_16 = encoding_16 + self.encoding_32 = encoding_32 + +class Immediate(object): + def __init__(self, name, ctype): + self.name = name + self.ctype = ctype + +class Encoding(object): + def __init__(self, description): + (exact, mask, length_short, length_long) = description + + # Convenience + if length_long is None: + length_long = length_short + + self.exact = exact + self.mask = mask + self.length_short = length_short + self.extensible = length_short != length_long + + if self.extensible: + assert(length_long == length_short + (4 if length_short > 8 else 2)) + +def op(name, encoding_32, dests = 1, srcs = 0, imms = [], is_float = False, can_eliminate = True, encoding_16 = None): + encoding_16 = Encoding(encoding_16) if encoding_16 is not None else None + encoding_32 = Encoding(encoding_32) if encoding_32 is not None else None + + opcodes[name] = Opcode(name, dests, srcs, imms, is_float, can_eliminate, encoding_16, encoding_32) + +def immediate(name, ctype = "uint32_t"): + imm = Immediate(name, ctype) + immediates[name] = imm + return imm + +L = (1 << 15) +_ = None + +FORMAT = immediate("format", "enum agx_format") +IMM = immediate("imm") +WRITEOUT = immediate("writeout") +INDEX = immediate("index") +COMPONENT = immediate("component") +CHANNELS = immediate("channels") +TRUTH_TABLE = immediate("truth_table") +ROUND = immediate("round") +SHIFT = immediate("shift") +MASK = immediate("mask") +BFI_MASK = immediate("bfi_mask") +LOD_MODE = immediate("lod_mode", "enum agx_lod_mode") +DIM = immediate("dim", "enum agx_dim") +SCOREBOARD = immediate("scoreboard") +ICOND = immediate("icond") +FCOND = immediate("fcond") + +FUNOP = lambda x: (x << 28) +FUNOP_MASK = FUNOP((1 << 14) - 1) + +def funop(name, opcode): + op(name, (0x0A | L | (opcode << 28), + 0x3F | L | (((1 << 14) - 1) << 28), 6, _), + srcs = 1, is_float = True) + +# Listing of opcodes +funop("floor", 0b000000) +funop("srsqrt", 0b000001) +funop("dfdx", 0b000100) +funop("dfdy", 0b000110) +funop("rcp", 0b001000) +funop("rsqrt", 0b001001) +funop("sin_pt_1", 0b001010) +funop("log2", 0b001100) +funop("exp2", 0b001101) +funop("sin_pt_2", 0b001110) +funop("ceil", 0b010000) +funop("trunc", 0b100000) +funop("roundeven", 0b110000) + +op("fadd", + encoding_16 = (0x26 | L, 0x3F | L, 6, _), + encoding_32 = (0x2A | L, 0x3F | L, 6, _), + srcs = 2, is_float = True) + +op("fma", + encoding_16 = (0x36, 0x3F, 6, 8), + encoding_32 = (0x3A, 0x3F, 6, 8), + srcs = 3, is_float = True) + +op("fmul", + encoding_16 = ((0x16 | L), (0x3F | L), 6, _), + encoding_32 = ((0x1A | L), (0x3F | L), 6, _), + srcs = 2, is_float = True) + +op("mov_imm", + encoding_32 = (0x62, 0xFF, 6, 8), + encoding_16 = (0x62, 0xFF, 4, 6), + imms = [IMM]) + +op("iadd", + encoding_32 = (0x0E, 0x3F | L, 8, _), + srcs = 2, imms = [SHIFT]) + +op("imad", + encoding_32 = (0x1E, 0x3F | L, 8, _), + srcs = 3, imms = [SHIFT]) + +op("bfi", + encoding_32 = (0x2E, 0x7F | (0x3 << 26), 8, _), + srcs = 3, imms = [BFI_MASK]) + +op("bfeil", + encoding_32 = (0x2E | L, 0x7F | L | (0x3 << 26), 8, _), + srcs = 3, imms = [BFI_MASK]) + +op("asr", + encoding_32 = (0x2E | L | (0x1 << 26), 0x7F | L | (0x3 << 26), 8, _), + srcs = 2) + +op("icmpsel", + encoding_32 = (0x12, 0x7F, 8, 10), + srcs = 4, imms = [ICOND]) + +op("fcmpsel", + encoding_32 = (0x02, 0x7F, 8, 10), + srcs = 4, imms = [FCOND]) + +# sources are coordinates, LOD, texture, sampler, offset +# TODO: anything else? +op("texture_sample", + encoding_32 = (0x32, 0x7F, 8, 10), # XXX WRONG SIZE + srcs = 5, imms = [DIM, LOD_MODE, MASK, SCOREBOARD]) + +# sources are base, index +op("device_load", + encoding_32 = (0x05, 0x7F, 6, 8), + srcs = 2, imms = [FORMAT, MASK, SCOREBOARD]) + +op("wait", (0x38, 0xFF, 2, _), dests = 0, + can_eliminate = False, imms = [SCOREBOARD]) + +op("bitop", (0x7E, 0x7F, 6, _), srcs = 2, imms = [TRUTH_TABLE]) +op("blend", (0x09, 0x7F, 8, _), dests = 0, srcs = 1, imms = [FORMAT], can_eliminate = False) +op("convert", (0x3E | L, 0x7F | L | (0x3 << 38), 6, _), srcs = 2, imms = [ROUND]) +op("ld_vary", (0x21, 0x3F, 8, _), srcs = 1, imms = [CHANNELS]) +op("st_vary", None, dests = 0, srcs = 2, can_eliminate = False) +op("stop", (0x88, 0xFFFF, 2, _), dests = 0, can_eliminate = False) +op("trap", (0x08, 0xFFFF, 2, _), dests = 0, can_eliminate = False) +op("writeout", (0x48, 0xFF, 4, _), dests = 0, imms = [WRITEOUT], can_eliminate = False) + +op("p_combine", _, srcs = 4) +op("p_extract", _, srcs = 1, imms = [COMPONENT])