| /* |
| * Copyright © 2024 Imagination Technologies Ltd. |
| * |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| /** |
| * \file pco_binary.c |
| * |
| * \brief PCO binary-specific functions. |
| */ |
| |
| #include "pco.h" |
| #include "pco_internal.h" |
| #include "pco_isa.h" |
| #include "pco_map.h" |
| #include "util/u_dynarray.h" |
| |
| #include <assert.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| |
| /** |
| * \brief Encodes instruction group alignment. |
| * |
| * \param[in,out] buf Binary buffer. |
| * \param[in] igrp PCO instruction group. |
| */ |
| static inline unsigned pco_encode_align(struct util_dynarray *buf, |
| pco_igrp *igrp) |
| { |
| unsigned bytes_encoded = 0; |
| |
| if (igrp->enc.len.word_padding) { |
| util_dynarray_append(buf, uint8_t, 0xff); |
| bytes_encoded += 1; |
| } |
| |
| if (igrp->enc.len.align_padding) { |
| assert(!(igrp->enc.len.align_padding % 2)); |
| |
| unsigned align_words = igrp->enc.len.align_padding / 2; |
| util_dynarray_append(buf, uint8_t, 0xf0 | align_words); |
| bytes_encoded += 1; |
| |
| for (unsigned u = 0; u < igrp->enc.len.align_padding - 1; ++u) { |
| util_dynarray_append(buf, uint8_t, 0xff); |
| bytes_encoded += 1; |
| } |
| } |
| |
| return bytes_encoded; |
| } |
| |
| /** |
| * \brief Encodes a PCO instruction group into binary. |
| * |
| * \param[in,out] buf Binary buffer. |
| * \param[in] igrp PCO instruction group. |
| * \return The number of bytes encoded. |
| */ |
| static unsigned pco_encode_igrp(struct util_dynarray *buf, pco_igrp *igrp) |
| { |
| uint8_t *ptr; |
| unsigned bytes_encoded = 0; |
| |
| /* Header. */ |
| ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.hdr); |
| bytes_encoded += pco_igrp_hdr_map_encode(ptr, igrp); |
| |
| /* Instructions. */ |
| pco_foreach_phase_in_igrp_rev (igrp, p) { |
| ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.instrs[p]); |
| bytes_encoded += pco_instr_map_encode(ptr, igrp, p); |
| } |
| |
| /* I/O. */ |
| if (igrp->enc.len.lower_srcs) { |
| ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.lower_srcs); |
| bytes_encoded += pco_srcs_map_encode(ptr, igrp, false); |
| } |
| |
| if (igrp->enc.len.upper_srcs) { |
| ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.upper_srcs); |
| bytes_encoded += pco_srcs_map_encode(ptr, igrp, true); |
| } |
| |
| if (igrp->enc.len.iss) { |
| ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.iss); |
| bytes_encoded += pco_iss_map_encode(ptr, igrp); |
| } |
| |
| if (igrp->enc.len.dests) { |
| ptr = util_dynarray_grow(buf, uint8_t, igrp->enc.len.dests); |
| bytes_encoded += pco_dests_map_encode(ptr, igrp); |
| } |
| |
| /* Word/alignment padding. */ |
| bytes_encoded += pco_encode_align(buf, igrp); |
| |
| assert(bytes_encoded == igrp->enc.len.total); |
| |
| return bytes_encoded; |
| } |
| |
| /** |
| * \brief Encodes a PCO shader into binary. |
| * |
| * \param[in] ctx PCO compiler context. |
| * \param[in,out] shader PCO shader. |
| */ |
| void pco_encode_ir(pco_ctx *ctx, pco_shader *shader) |
| { |
| assert(shader->is_grouped); |
| |
| util_dynarray_init(&shader->binary, shader); |
| |
| unsigned bytes_encoded = 0; |
| pco_foreach_func_in_shader (func, shader) { |
| func->enc_offset = bytes_encoded; |
| pco_foreach_block_in_func (block, func) { |
| pco_foreach_igrp_in_block (igrp, block) { |
| bytes_encoded += pco_encode_igrp(&shader->binary, igrp); |
| } |
| } |
| } |
| |
| if (pco_should_print_binary(shader)) |
| pco_print_binary(shader, stdout, "after encoding"); |
| } |
| |
| /** |
| * \brief Returns the size in bytes of a PCO shader binary. |
| * |
| * \param[in] shader PCO shader. |
| * \return The size in bytes of the PCO shader binary. |
| */ |
| unsigned pco_shader_binary_size(pco_shader *shader) |
| { |
| if (!shader) |
| return 0; |
| |
| return shader->binary.size; |
| } |
| |
| /** |
| * \brief Returns the PCO shader binary data. |
| * |
| * \param[in] shader PCO shader. |
| * \return The PCO shader binary data. |
| */ |
| const void *pco_shader_binary_data(pco_shader *shader) |
| { |
| if (!shader) |
| return NULL; |
| return shader->binary.data; |
| } |