Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  */
  23.  
  24. #include "ir3.h"
  25.  
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include <stdbool.h>
  31. #include <errno.h>
  32.  
  33. #include "freedreno_util.h"
  34. #include "instr-a3xx.h"
  35.  
  36. #define CHUNK_SZ 1020
  37.  
  38. struct ir3_heap_chunk {
  39.         struct ir3_heap_chunk *next;
  40.         uint32_t heap[CHUNK_SZ];
  41. };
  42.  
  43. static void grow_heap(struct ir3 *shader)
  44. {
  45.         struct ir3_heap_chunk *chunk = calloc(1, sizeof(*chunk));
  46.         chunk->next = shader->chunk;
  47.         shader->chunk = chunk;
  48.         shader->heap_idx = 0;
  49. }
  50.  
  51. /* simple allocator to carve allocations out of an up-front allocated heap,
  52.  * so that we can free everything easily in one shot.
  53.  */
  54. void * ir3_alloc(struct ir3 *shader, int sz)
  55. {
  56.         void *ptr;
  57.  
  58.         sz = align(sz, 4) / 4;
  59.  
  60.         if ((shader->heap_idx + sz) > CHUNK_SZ)
  61.                 grow_heap(shader);
  62.  
  63.         ptr = &shader->chunk->heap[shader->heap_idx];
  64.         shader->heap_idx += sz;
  65.  
  66.         return ptr;
  67. }
  68.  
  69. struct ir3 * ir3_create(void)
  70. {
  71.         struct ir3 *shader =
  72.                         calloc(1, sizeof(struct ir3));
  73.         grow_heap(shader);
  74.         return shader;
  75. }
  76.  
  77. void ir3_destroy(struct ir3 *shader)
  78. {
  79.         while (shader->chunk) {
  80.                 struct ir3_heap_chunk *chunk = shader->chunk;
  81.                 shader->chunk = chunk->next;
  82.                 free(chunk);
  83.         }
  84.         free(shader->instrs);
  85.         free(shader->baryfs);
  86.         free(shader);
  87. }
  88.  
  89. #define iassert(cond) do { \
  90.         if (!(cond)) { \
  91.                 assert(cond); \
  92.                 return -1; \
  93.         } } while (0)
  94.  
  95. static uint32_t reg(struct ir3_register *reg, struct ir3_info *info,
  96.                 uint32_t repeat, uint32_t valid_flags)
  97. {
  98.         reg_t val = { .dummy32 = 0 };
  99.  
  100.         if (reg->flags & ~valid_flags) {
  101.                 debug_printf("INVALID FLAGS: %x vs %x\n",
  102.                                 reg->flags, valid_flags);
  103.         }
  104.  
  105.         if (!(reg->flags & IR3_REG_R))
  106.                 repeat = 0;
  107.  
  108.         if (reg->flags & IR3_REG_IMMED) {
  109.                 val.iim_val = reg->iim_val;
  110.         } else {
  111.                 unsigned components;
  112.  
  113.                 if (reg->flags & IR3_REG_RELATIV) {
  114.                         components = reg->size;
  115.                         val.dummy10 = reg->offset;
  116.                 } else {
  117.                         components = util_last_bit(reg->wrmask);
  118.                         val.comp = reg->num & 0x3;
  119.                         val.num  = reg->num >> 2;
  120.                 }
  121.  
  122.                 int16_t max = (reg->num + repeat + components - 1) >> 2;
  123.  
  124.                 if (reg->flags & IR3_REG_CONST) {
  125.                         info->max_const = MAX2(info->max_const, max);
  126.                 } else if (val.num == 63) {
  127.                         /* ignore writes to dummy register r63.x */
  128.                 } else if ((max != REG_A0) && (max != REG_P0)) {
  129.                         if (reg->flags & IR3_REG_HALF) {
  130.                                 info->max_half_reg = MAX2(info->max_half_reg, max);
  131.                         } else {
  132.                                 info->max_reg = MAX2(info->max_reg, max);
  133.                         }
  134.                 }
  135.         }
  136.  
  137.         return val.dummy32;
  138. }
  139.  
  140. static int emit_cat0(struct ir3_instruction *instr, void *ptr,
  141.                 struct ir3_info *info)
  142. {
  143.         instr_cat0_t *cat0 = ptr;
  144.  
  145.         cat0->immed    = instr->cat0.immed;
  146.         cat0->repeat   = instr->repeat;
  147.         cat0->ss       = !!(instr->flags & IR3_INSTR_SS);
  148.         cat0->inv      = instr->cat0.inv;
  149.         cat0->comp     = instr->cat0.comp;
  150.         cat0->opc      = instr->opc;
  151.         cat0->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  152.         cat0->sync     = !!(instr->flags & IR3_INSTR_SY);
  153.         cat0->opc_cat  = 0;
  154.  
  155.         return 0;
  156. }
  157.  
  158. static uint32_t type_flags(type_t type)
  159. {
  160.         return (type_size(type) == 32) ? 0 : IR3_REG_HALF;
  161. }
  162.  
  163. static int emit_cat1(struct ir3_instruction *instr, void *ptr,
  164.                 struct ir3_info *info)
  165. {
  166.         struct ir3_register *dst = instr->regs[0];
  167.         struct ir3_register *src = instr->regs[1];
  168.         instr_cat1_t *cat1 = ptr;
  169.  
  170.         iassert(instr->regs_count == 2);
  171.         iassert(!((dst->flags ^ type_flags(instr->cat1.dst_type)) & IR3_REG_HALF));
  172.         iassert((src->flags & IR3_REG_IMMED) ||
  173.                         !((src->flags ^ type_flags(instr->cat1.src_type)) & IR3_REG_HALF));
  174.  
  175.         if (src->flags & IR3_REG_IMMED) {
  176.                 cat1->iim_val = src->iim_val;
  177.                 cat1->src_im  = 1;
  178.         } else if (src->flags & IR3_REG_RELATIV) {
  179.                 cat1->off       = reg(src, info, instr->repeat,
  180.                                 IR3_REG_R | IR3_REG_CONST | IR3_REG_HALF | IR3_REG_RELATIV);
  181.                 cat1->src_rel   = 1;
  182.                 cat1->src_rel_c = !!(src->flags & IR3_REG_CONST);
  183.         } else {
  184.                 cat1->src  = reg(src, info, instr->repeat,
  185.                                 IR3_REG_R | IR3_REG_CONST | IR3_REG_HALF);
  186.                 cat1->src_c     = !!(src->flags & IR3_REG_CONST);
  187.         }
  188.  
  189.         cat1->dst      = reg(dst, info, instr->repeat,
  190.                         IR3_REG_RELATIV | IR3_REG_EVEN |
  191.                         IR3_REG_R | IR3_REG_POS_INF | IR3_REG_HALF);
  192.         cat1->repeat   = instr->repeat;
  193.         cat1->src_r    = !!(src->flags & IR3_REG_R);
  194.         cat1->ss       = !!(instr->flags & IR3_INSTR_SS);
  195.         cat1->ul       = !!(instr->flags & IR3_INSTR_UL);
  196.         cat1->dst_type = instr->cat1.dst_type;
  197.         cat1->dst_rel  = !!(dst->flags & IR3_REG_RELATIV);
  198.         cat1->src_type = instr->cat1.src_type;
  199.         cat1->even     = !!(dst->flags & IR3_REG_EVEN);
  200.         cat1->pos_inf  = !!(dst->flags & IR3_REG_POS_INF);
  201.         cat1->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  202.         cat1->sync     = !!(instr->flags & IR3_INSTR_SY);
  203.         cat1->opc_cat  = 1;
  204.  
  205.         return 0;
  206. }
  207.  
  208. static int emit_cat2(struct ir3_instruction *instr, void *ptr,
  209.                 struct ir3_info *info)
  210. {
  211.         struct ir3_register *dst = instr->regs[0];
  212.         struct ir3_register *src1 = instr->regs[1];
  213.         struct ir3_register *src2 = instr->regs[2];
  214.         instr_cat2_t *cat2 = ptr;
  215.         unsigned absneg = ir3_cat2_absneg(instr->opc);
  216.  
  217.         iassert((instr->regs_count == 2) || (instr->regs_count == 3));
  218.  
  219.         if (src1->flags & IR3_REG_RELATIV) {
  220.                 iassert(src1->num < (1 << 10));
  221.                 cat2->rel1.src1      = reg(src1, info, instr->repeat,
  222.                                 IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
  223.                                 IR3_REG_HALF | absneg);
  224.                 cat2->rel1.src1_c    = !!(src1->flags & IR3_REG_CONST);
  225.                 cat2->rel1.src1_rel  = 1;
  226.         } else if (src1->flags & IR3_REG_CONST) {
  227.                 iassert(src1->num < (1 << 12));
  228.                 cat2->c1.src1   = reg(src1, info, instr->repeat,
  229.                                 IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
  230.                 cat2->c1.src1_c = 1;
  231.         } else {
  232.                 iassert(src1->num < (1 << 11));
  233.                 cat2->src1 = reg(src1, info, instr->repeat,
  234.                                 IR3_REG_IMMED | IR3_REG_R | IR3_REG_HALF |
  235.                                 absneg);
  236.         }
  237.         cat2->src1_im  = !!(src1->flags & IR3_REG_IMMED);
  238.         cat2->src1_neg = !!(src1->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
  239.         cat2->src1_abs = !!(src1->flags & (IR3_REG_FABS | IR3_REG_SABS));
  240.         cat2->src1_r   = !!(src1->flags & IR3_REG_R);
  241.  
  242.         if (src2) {
  243.                 iassert((src2->flags & IR3_REG_IMMED) ||
  244.                                 !((src1->flags ^ src2->flags) & IR3_REG_HALF));
  245.  
  246.                 if (src2->flags & IR3_REG_RELATIV) {
  247.                         iassert(src2->num < (1 << 10));
  248.                         cat2->rel2.src2      = reg(src2, info, instr->repeat,
  249.                                         IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
  250.                                         IR3_REG_HALF | absneg);
  251.                         cat2->rel2.src2_c    = !!(src2->flags & IR3_REG_CONST);
  252.                         cat2->rel2.src2_rel  = 1;
  253.                 } else if (src2->flags & IR3_REG_CONST) {
  254.                         iassert(src2->num < (1 << 12));
  255.                         cat2->c2.src2   = reg(src2, info, instr->repeat,
  256.                                         IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
  257.                         cat2->c2.src2_c = 1;
  258.                 } else {
  259.                         iassert(src2->num < (1 << 11));
  260.                         cat2->src2 = reg(src2, info, instr->repeat,
  261.                                         IR3_REG_IMMED | IR3_REG_R | IR3_REG_HALF |
  262.                                         absneg);
  263.                 }
  264.  
  265.                 cat2->src2_im  = !!(src2->flags & IR3_REG_IMMED);
  266.                 cat2->src2_neg = !!(src2->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
  267.                 cat2->src2_abs = !!(src2->flags & (IR3_REG_FABS | IR3_REG_SABS));
  268.                 cat2->src2_r   = !!(src2->flags & IR3_REG_R);
  269.         }
  270.  
  271.         cat2->dst      = reg(dst, info, instr->repeat,
  272.                         IR3_REG_R | IR3_REG_EI | IR3_REG_HALF);
  273.         cat2->repeat   = instr->repeat;
  274.         cat2->ss       = !!(instr->flags & IR3_INSTR_SS);
  275.         cat2->ul       = !!(instr->flags & IR3_INSTR_UL);
  276.         cat2->dst_half = !!((src1->flags ^ dst->flags) & IR3_REG_HALF);
  277.         cat2->ei       = !!(dst->flags & IR3_REG_EI);
  278.         cat2->cond     = instr->cat2.condition;
  279.         cat2->full     = ! (src1->flags & IR3_REG_HALF);
  280.         cat2->opc      = instr->opc;
  281.         cat2->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  282.         cat2->sync     = !!(instr->flags & IR3_INSTR_SY);
  283.         cat2->opc_cat  = 2;
  284.  
  285.         return 0;
  286. }
  287.  
  288. static int emit_cat3(struct ir3_instruction *instr, void *ptr,
  289.                 struct ir3_info *info)
  290. {
  291.         struct ir3_register *dst = instr->regs[0];
  292.         struct ir3_register *src1 = instr->regs[1];
  293.         struct ir3_register *src2 = instr->regs[2];
  294.         struct ir3_register *src3 = instr->regs[3];
  295.         unsigned absneg = ir3_cat3_absneg(instr->opc);
  296.         instr_cat3_t *cat3 = ptr;
  297.         uint32_t src_flags = 0;
  298.  
  299.         switch (instr->opc) {
  300.         case OPC_MAD_F16:
  301.         case OPC_MAD_U16:
  302.         case OPC_MAD_S16:
  303.         case OPC_SEL_B16:
  304.         case OPC_SEL_S16:
  305.         case OPC_SEL_F16:
  306.         case OPC_SAD_S16:
  307.         case OPC_SAD_S32:  // really??
  308.                 src_flags |= IR3_REG_HALF;
  309.                 break;
  310.         default:
  311.                 break;
  312.         }
  313.  
  314.         iassert(instr->regs_count == 4);
  315.         iassert(!((src1->flags ^ src_flags) & IR3_REG_HALF));
  316.         iassert(!((src2->flags ^ src_flags) & IR3_REG_HALF));
  317.         iassert(!((src3->flags ^ src_flags) & IR3_REG_HALF));
  318.  
  319.         if (src1->flags & IR3_REG_RELATIV) {
  320.                 iassert(src1->num < (1 << 10));
  321.                 cat3->rel1.src1      = reg(src1, info, instr->repeat,
  322.                                 IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
  323.                                 IR3_REG_HALF | absneg);
  324.                 cat3->rel1.src1_c    = !!(src1->flags & IR3_REG_CONST);
  325.                 cat3->rel1.src1_rel  = 1;
  326.         } else if (src1->flags & IR3_REG_CONST) {
  327.                 iassert(src1->num < (1 << 12));
  328.                 cat3->c1.src1   = reg(src1, info, instr->repeat,
  329.                                 IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
  330.                 cat3->c1.src1_c = 1;
  331.         } else {
  332.                 iassert(src1->num < (1 << 11));
  333.                 cat3->src1 = reg(src1, info, instr->repeat,
  334.                                 IR3_REG_R | IR3_REG_HALF | absneg);
  335.         }
  336.  
  337.         cat3->src1_neg = !!(src1->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
  338.         cat3->src1_r   = !!(src1->flags & IR3_REG_R);
  339.  
  340.         cat3->src2     = reg(src2, info, instr->repeat,
  341.                         IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF | absneg);
  342.         cat3->src2_c   = !!(src2->flags & IR3_REG_CONST);
  343.         cat3->src2_neg = !!(src2->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
  344.         cat3->src2_r   = !!(src2->flags & IR3_REG_R);
  345.  
  346.  
  347.         if (src3->flags & IR3_REG_RELATIV) {
  348.                 iassert(src3->num < (1 << 10));
  349.                 cat3->rel2.src3      = reg(src3, info, instr->repeat,
  350.                                 IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_R |
  351.                                 IR3_REG_HALF | absneg);
  352.                 cat3->rel2.src3_c    = !!(src3->flags & IR3_REG_CONST);
  353.                 cat3->rel2.src3_rel  = 1;
  354.         } else if (src3->flags & IR3_REG_CONST) {
  355.                 iassert(src3->num < (1 << 12));
  356.                 cat3->c2.src3   = reg(src3, info, instr->repeat,
  357.                                 IR3_REG_CONST | IR3_REG_R | IR3_REG_HALF);
  358.                 cat3->c2.src3_c = 1;
  359.         } else {
  360.                 iassert(src3->num < (1 << 11));
  361.                 cat3->src3 = reg(src3, info, instr->repeat,
  362.                                 IR3_REG_R | IR3_REG_HALF | absneg);
  363.         }
  364.  
  365.         cat3->src3_neg = !!(src3->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT));
  366.         cat3->src3_r   = !!(src3->flags & IR3_REG_R);
  367.  
  368.         cat3->dst      = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
  369.         cat3->repeat   = instr->repeat;
  370.         cat3->ss       = !!(instr->flags & IR3_INSTR_SS);
  371.         cat3->ul       = !!(instr->flags & IR3_INSTR_UL);
  372.         cat3->dst_half = !!((src_flags ^ dst->flags) & IR3_REG_HALF);
  373.         cat3->opc      = instr->opc;
  374.         cat3->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  375.         cat3->sync     = !!(instr->flags & IR3_INSTR_SY);
  376.         cat3->opc_cat  = 3;
  377.  
  378.         return 0;
  379. }
  380.  
  381. static int emit_cat4(struct ir3_instruction *instr, void *ptr,
  382.                 struct ir3_info *info)
  383. {
  384.         struct ir3_register *dst = instr->regs[0];
  385.         struct ir3_register *src = instr->regs[1];
  386.         instr_cat4_t *cat4 = ptr;
  387.  
  388.         iassert(instr->regs_count == 2);
  389.  
  390.         if (src->flags & IR3_REG_RELATIV) {
  391.                 iassert(src->num < (1 << 10));
  392.                 cat4->rel.src      = reg(src, info, instr->repeat,
  393.                                 IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_FNEG |
  394.                                 IR3_REG_FABS | IR3_REG_R | IR3_REG_HALF);
  395.                 cat4->rel.src_c    = !!(src->flags & IR3_REG_CONST);
  396.                 cat4->rel.src_rel  = 1;
  397.         } else if (src->flags & IR3_REG_CONST) {
  398.                 iassert(src->num < (1 << 12));
  399.                 cat4->c.src   = reg(src, info, instr->repeat,
  400.                                 IR3_REG_CONST | IR3_REG_FNEG | IR3_REG_FABS |
  401.                                 IR3_REG_R | IR3_REG_HALF);
  402.                 cat4->c.src_c = 1;
  403.         } else {
  404.                 iassert(src->num < (1 << 11));
  405.                 cat4->src = reg(src, info, instr->repeat,
  406.                                 IR3_REG_IMMED | IR3_REG_FNEG | IR3_REG_FABS |
  407.                                 IR3_REG_R | IR3_REG_HALF);
  408.         }
  409.  
  410.         cat4->src_im   = !!(src->flags & IR3_REG_IMMED);
  411.         cat4->src_neg  = !!(src->flags & IR3_REG_FNEG);
  412.         cat4->src_abs  = !!(src->flags & IR3_REG_FABS);
  413.         cat4->src_r    = !!(src->flags & IR3_REG_R);
  414.  
  415.         cat4->dst      = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
  416.         cat4->repeat   = instr->repeat;
  417.         cat4->ss       = !!(instr->flags & IR3_INSTR_SS);
  418.         cat4->ul       = !!(instr->flags & IR3_INSTR_UL);
  419.         cat4->dst_half = !!((src->flags ^ dst->flags) & IR3_REG_HALF);
  420.         cat4->full     = ! (src->flags & IR3_REG_HALF);
  421.         cat4->opc      = instr->opc;
  422.         cat4->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  423.         cat4->sync     = !!(instr->flags & IR3_INSTR_SY);
  424.         cat4->opc_cat  = 4;
  425.  
  426.         return 0;
  427. }
  428.  
  429. static int emit_cat5(struct ir3_instruction *instr, void *ptr,
  430.                 struct ir3_info *info)
  431. {
  432.         struct ir3_register *dst = instr->regs[0];
  433.         struct ir3_register *src1 = instr->regs[1];
  434.         struct ir3_register *src2 = instr->regs[2];
  435.         struct ir3_register *src3 = instr->regs[3];
  436.         instr_cat5_t *cat5 = ptr;
  437.  
  438.         iassert(!((dst->flags ^ type_flags(instr->cat5.type)) & IR3_REG_HALF));
  439.  
  440.         if (src1) {
  441.                 cat5->full = ! (src1->flags & IR3_REG_HALF);
  442.                 cat5->src1 = reg(src1, info, instr->repeat, IR3_REG_HALF);
  443.         }
  444.  
  445.  
  446.         if (instr->flags & IR3_INSTR_S2EN) {
  447.                 if (src2) {
  448.                         iassert(!((src1->flags ^ src2->flags) & IR3_REG_HALF));
  449.                         cat5->s2en.src2 = reg(src2, info, instr->repeat, IR3_REG_HALF);
  450.                 }
  451.                 if (src3) {
  452.                         iassert(src3->flags & IR3_REG_HALF);
  453.                         cat5->s2en.src3 = reg(src3, info, instr->repeat, IR3_REG_HALF);
  454.                 }
  455.                 iassert(!(instr->cat5.samp | instr->cat5.tex));
  456.         } else {
  457.                 iassert(!src3);
  458.                 if (src2) {
  459.                         iassert(!((src1->flags ^ src2->flags) & IR3_REG_HALF));
  460.                         cat5->norm.src2 = reg(src2, info, instr->repeat, IR3_REG_HALF);
  461.                 }
  462.                 cat5->norm.samp = instr->cat5.samp;
  463.                 cat5->norm.tex  = instr->cat5.tex;
  464.         }
  465.  
  466.         cat5->dst      = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
  467.         cat5->wrmask   = dst->wrmask;
  468.         cat5->type     = instr->cat5.type;
  469.         cat5->is_3d    = !!(instr->flags & IR3_INSTR_3D);
  470.         cat5->is_a     = !!(instr->flags & IR3_INSTR_A);
  471.         cat5->is_s     = !!(instr->flags & IR3_INSTR_S);
  472.         cat5->is_s2en  = !!(instr->flags & IR3_INSTR_S2EN);
  473.         cat5->is_o     = !!(instr->flags & IR3_INSTR_O);
  474.         cat5->is_p     = !!(instr->flags & IR3_INSTR_P);
  475.         cat5->opc      = instr->opc;
  476.         cat5->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  477.         cat5->sync     = !!(instr->flags & IR3_INSTR_SY);
  478.         cat5->opc_cat  = 5;
  479.  
  480.         return 0;
  481. }
  482.  
  483. static int emit_cat6(struct ir3_instruction *instr, void *ptr,
  484.                 struct ir3_info *info)
  485. {
  486.         struct ir3_register *dst  = instr->regs[0];
  487.         struct ir3_register *src1 = instr->regs[1];
  488.         struct ir3_register *src2 = (instr->regs_count >= 3) ? instr->regs[2] : NULL;
  489.         instr_cat6_t *cat6 = ptr;
  490.  
  491.         iassert(instr->regs_count >= 2);
  492.  
  493.         if (instr->cat6.offset || instr->opc == OPC_LDG) {
  494.                 instr_cat6a_t *cat6a = ptr;
  495.  
  496.                 cat6->has_off = true;
  497.  
  498.                 cat6a->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
  499.                 cat6a->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
  500.                 cat6a->src1_im = !!(src1->flags & IR3_REG_IMMED);
  501.                 if (src2) {
  502.                         cat6a->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
  503.                         cat6a->src2_im = !!(src2->flags & IR3_REG_IMMED);
  504.                 }
  505.                 cat6a->off = instr->cat6.offset;
  506.         } else {
  507.                 instr_cat6b_t *cat6b = ptr;
  508.  
  509.                 cat6->has_off = false;
  510.  
  511.                 cat6b->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
  512.                 cat6b->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
  513.                 cat6b->src1_im = !!(src1->flags & IR3_REG_IMMED);
  514.                 if (src2) {
  515.                         cat6b->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
  516.                         cat6b->src2_im = !!(src2->flags & IR3_REG_IMMED);
  517.                 }
  518.         }
  519.  
  520.         cat6->type     = instr->cat6.type;
  521.         cat6->opc      = instr->opc;
  522.         cat6->jmp_tgt  = !!(instr->flags & IR3_INSTR_JP);
  523.         cat6->sync     = !!(instr->flags & IR3_INSTR_SY);
  524.         cat6->opc_cat  = 6;
  525.  
  526.         return 0;
  527. }
  528.  
  529. static int (*emit[])(struct ir3_instruction *instr, void *ptr,
  530.                 struct ir3_info *info) = {
  531.         emit_cat0, emit_cat1, emit_cat2, emit_cat3, emit_cat4, emit_cat5, emit_cat6,
  532. };
  533.  
  534. void * ir3_assemble(struct ir3 *shader, struct ir3_info *info,
  535.                 uint32_t gpu_id)
  536. {
  537.         uint32_t *ptr, *dwords;
  538.         uint32_t i;
  539.  
  540.         info->max_reg       = -1;
  541.         info->max_half_reg  = -1;
  542.         info->max_const     = -1;
  543.         info->instrs_count  = 0;
  544.  
  545.         /* need a integer number of instruction "groups" (sets of 16
  546.          * instructions on a4xx or sets of 4 instructions on a3xx),
  547.          * so pad out w/ NOPs if needed: (NOTE each instruction is 64bits)
  548.          */
  549.         if (gpu_id >= 400) {
  550.                 info->sizedwords = 2 * align(shader->instrs_count, 16);
  551.         } else {
  552.                 info->sizedwords = 2 * align(shader->instrs_count, 4);
  553.         }
  554.  
  555.         ptr = dwords = calloc(4, info->sizedwords);
  556.  
  557.         for (i = 0; i < shader->instrs_count; i++) {
  558.                 struct ir3_instruction *instr = shader->instrs[i];
  559.                 int ret = emit[instr->category](instr, dwords, info);
  560.                 if (ret)
  561.                         goto fail;
  562.                 info->instrs_count += 1 + instr->repeat;
  563.                 dwords += 2;
  564.         }
  565.  
  566.         return ptr;
  567.  
  568. fail:
  569.         free(ptr);
  570.         return NULL;
  571. }
  572.  
  573. static struct ir3_register * reg_create(struct ir3 *shader,
  574.                 int num, int flags)
  575. {
  576.         struct ir3_register *reg =
  577.                         ir3_alloc(shader, sizeof(struct ir3_register));
  578.         reg->wrmask = 1;
  579.         reg->flags = flags;
  580.         reg->num = num;
  581.         return reg;
  582. }
  583.  
  584. static void insert_instr(struct ir3 *shader,
  585.                 struct ir3_instruction *instr)
  586. {
  587. #ifdef DEBUG
  588.         static uint32_t serialno = 0;
  589.         instr->serialno = ++serialno;
  590. #endif
  591.         array_insert(shader->instrs, instr);
  592.  
  593.         if (is_input(instr))
  594.                 array_insert(shader->baryfs, instr);
  595. }
  596.  
  597. struct ir3_block * ir3_block_create(struct ir3 *shader,
  598.                 unsigned ntmp, unsigned nin, unsigned nout)
  599. {
  600.         struct ir3_block *block;
  601.         unsigned size;
  602.         char *ptr;
  603.  
  604.         size = sizeof(*block);
  605.         size += sizeof(block->temporaries[0]) * ntmp;
  606.         size += sizeof(block->inputs[0]) * nin;
  607.         size += sizeof(block->outputs[0]) * nout;
  608.  
  609.         ptr = ir3_alloc(shader, size);
  610.  
  611.         block = (void *)ptr;
  612.         ptr += sizeof(*block);
  613.  
  614.         block->temporaries = (void *)ptr;
  615.         block->ntemporaries = ntmp;
  616.         ptr += sizeof(block->temporaries[0]) * ntmp;
  617.  
  618.         block->inputs = (void *)ptr;
  619.         block->ninputs = nin;
  620.         ptr += sizeof(block->inputs[0]) * nin;
  621.  
  622.         block->outputs = (void *)ptr;
  623.         block->noutputs = nout;
  624.         ptr += sizeof(block->outputs[0]) * nout;
  625.  
  626.         block->shader = shader;
  627.  
  628.         return block;
  629. }
  630.  
  631. static struct ir3_instruction *instr_create(struct ir3_block *block, int nreg)
  632. {
  633.         struct ir3_instruction *instr;
  634.         unsigned sz = sizeof(*instr) + (nreg * sizeof(instr->regs[0]));
  635.         char *ptr = ir3_alloc(block->shader, sz);
  636.  
  637.         instr = (struct ir3_instruction *)ptr;
  638.         ptr  += sizeof(*instr);
  639.         instr->regs = (struct ir3_register **)ptr;
  640.  
  641. #ifdef DEBUG
  642.         instr->regs_max = nreg;
  643. #endif
  644.  
  645.         return instr;
  646. }
  647.  
  648. struct ir3_instruction * ir3_instr_create2(struct ir3_block *block,
  649.                 int category, opc_t opc, int nreg)
  650. {
  651.         struct ir3_instruction *instr = instr_create(block, nreg);
  652.         instr->block = block;
  653.         instr->category = category;
  654.         instr->opc = opc;
  655.         insert_instr(block->shader, instr);
  656.         return instr;
  657. }
  658.  
  659. struct ir3_instruction * ir3_instr_create(struct ir3_block *block,
  660.                 int category, opc_t opc)
  661. {
  662.         /* NOTE: we could be slightly more clever, at least for non-meta,
  663.          * and choose # of regs based on category.
  664.          */
  665.         return ir3_instr_create2(block, category, opc, 4);
  666. }
  667.  
  668. /* only used by old compiler: */
  669. struct ir3_instruction * ir3_instr_clone(struct ir3_instruction *instr)
  670. {
  671.         struct ir3_instruction *new_instr = instr_create(instr->block,
  672.                         instr->regs_count);
  673.         struct ir3_register **regs;
  674.         unsigned i;
  675.  
  676.         regs = new_instr->regs;
  677.         *new_instr = *instr;
  678.         new_instr->regs = regs;
  679.  
  680.         insert_instr(instr->block->shader, new_instr);
  681.  
  682.         /* clone registers: */
  683.         new_instr->regs_count = 0;
  684.         for (i = 0; i < instr->regs_count; i++) {
  685.                 struct ir3_register *reg = instr->regs[i];
  686.                 struct ir3_register *new_reg =
  687.                                 ir3_reg_create(new_instr, reg->num, reg->flags);
  688.                 *new_reg = *reg;
  689.         }
  690.  
  691.         return new_instr;
  692. }
  693.  
  694. struct ir3_register * ir3_reg_create(struct ir3_instruction *instr,
  695.                 int num, int flags)
  696. {
  697.         struct ir3_register *reg = reg_create(instr->block->shader, num, flags);
  698. #ifdef DEBUG
  699.         debug_assert(instr->regs_count < instr->regs_max);
  700. #endif
  701.         instr->regs[instr->regs_count++] = reg;
  702.         return reg;
  703. }
  704.