1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2014 Ilia Mirkin
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include <errno.h>
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "tgsi/tgsi_text.h"
26bf215546Sopenharmony_ci#include "util/u_debug.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "nv50_ir_driver.h"
29bf215546Sopenharmony_ci#include "nv50/nv50_context.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci/* these headers weren't really meant to be included together */
32bf215546Sopenharmony_ci#undef SB_DATA
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "nv30/nv30_state.h"
35bf215546Sopenharmony_ci#include "nv30/nvfx_shader.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistatic int
38bf215546Sopenharmony_cinv30_fp(int chipset, struct tgsi_token tokens[],
39bf215546Sopenharmony_ci        unsigned *size, unsigned **code) {
40bf215546Sopenharmony_ci   struct nv30_fragprog fp;
41bf215546Sopenharmony_ci   memset(&fp, 0, sizeof(fp));
42bf215546Sopenharmony_ci   fp.pipe.tokens = tokens;
43bf215546Sopenharmony_ci   tgsi_scan_shader(fp.pipe.tokens, &fp.info);
44bf215546Sopenharmony_ci   _nvfx_fragprog_translate(chipset >= 0x40 ? 0x4097 : 0x3097, &fp);
45bf215546Sopenharmony_ci   *size = fp.insn_len * 4;
46bf215546Sopenharmony_ci   *code = fp.insn;
47bf215546Sopenharmony_ci   return !fp.translated;
48bf215546Sopenharmony_ci}
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_cistatic int
51bf215546Sopenharmony_cinv30_vp(int chipset, struct tgsi_token tokens[],
52bf215546Sopenharmony_ci        unsigned *size, unsigned **code) {
53bf215546Sopenharmony_ci   struct nv30_vertprog vp;
54bf215546Sopenharmony_ci   memset(&vp, 0, sizeof(vp));
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   vp.pipe.tokens = tokens;
57bf215546Sopenharmony_ci   tgsi_scan_shader(vp.pipe.tokens, &vp.info);
58bf215546Sopenharmony_ci   _nvfx_vertprog_translate(chipset >= 0x40 ? 0x4097 : 0x3097, &vp);
59bf215546Sopenharmony_ci   *size = vp.nr_insns * 16;
60bf215546Sopenharmony_ci   *code = (unsigned *)vp.insns;
61bf215546Sopenharmony_ci   return !vp.translated;
62bf215546Sopenharmony_ci}
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_cistatic int
65bf215546Sopenharmony_cinv30_codegen(int chipset, int type, struct tgsi_token tokens[],
66bf215546Sopenharmony_ci             unsigned *size, unsigned **code) {
67bf215546Sopenharmony_ci   switch (type) {
68bf215546Sopenharmony_ci      case PIPE_SHADER_FRAGMENT:
69bf215546Sopenharmony_ci         return nv30_fp(chipset, tokens, size, code);
70bf215546Sopenharmony_ci      case PIPE_SHADER_VERTEX:
71bf215546Sopenharmony_ci         return nv30_vp(chipset, tokens, size, code);
72bf215546Sopenharmony_ci   }
73bf215546Sopenharmony_ci   _debug_printf("Unexpected shader type: %d\n", type);
74bf215546Sopenharmony_ci   return 1;
75bf215546Sopenharmony_ci}
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_cistatic int
78bf215546Sopenharmony_cidummy_assign_slots(struct nv50_ir_prog_info_out *info)
79bf215546Sopenharmony_ci{
80bf215546Sopenharmony_ci   unsigned i, n, c;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   n = 0;
83bf215546Sopenharmony_ci   for (i = 0; i < info->numInputs; ++i) {
84bf215546Sopenharmony_ci      for (c = 0; c < 4; ++c)
85bf215546Sopenharmony_ci         if (info->in[i].mask & (1 << c))
86bf215546Sopenharmony_ci            info->in[i].slot[c] = n++;
87bf215546Sopenharmony_ci   }
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   /* VertexID before InstanceID */
90bf215546Sopenharmony_ci   if (info->io.vertexId < info->numSysVals)
91bf215546Sopenharmony_ci      info->sv[info->io.vertexId].slot[0] = n++;
92bf215546Sopenharmony_ci   if (info->io.instanceId < info->numSysVals)
93bf215546Sopenharmony_ci      info->sv[info->io.instanceId].slot[0] = n++;
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   n = 0;
96bf215546Sopenharmony_ci   for (i = 0; i < info->numOutputs; ++i) {
97bf215546Sopenharmony_ci      for (c = 0; c < 4; ++c)
98bf215546Sopenharmony_ci         if (info->out[i].mask & (1 << c))
99bf215546Sopenharmony_ci            info->out[i].slot[c] = n++;
100bf215546Sopenharmony_ci   }
101bf215546Sopenharmony_ci   return 0;
102bf215546Sopenharmony_ci}
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_cistatic int
105bf215546Sopenharmony_cinouveau_codegen(int chipset, int type, struct tgsi_token tokens[],
106bf215546Sopenharmony_ci                unsigned *size, unsigned **code) {
107bf215546Sopenharmony_ci   struct nv50_ir_prog_info info = {0};
108bf215546Sopenharmony_ci   struct nv50_ir_prog_info_out info_out = {0};
109bf215546Sopenharmony_ci   int ret;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   info.type = type;
112bf215546Sopenharmony_ci   info.target = chipset;
113bf215546Sopenharmony_ci   info.bin.sourceRep = PIPE_SHADER_IR_TGSI;
114bf215546Sopenharmony_ci   info.bin.source = tokens;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   info.io.auxCBSlot = 15;
117bf215546Sopenharmony_ci   info.io.ucpBase = NV50_CB_AUX_UCP_OFFSET;
118bf215546Sopenharmony_ci   info.io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET;
119bf215546Sopenharmony_ci   info.io.msInfoCBSlot = 15;
120bf215546Sopenharmony_ci   info.io.msInfoBase = NV50_CB_AUX_MS_OFFSET;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   info.assignSlots = dummy_assign_slots;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   info.optLevel = debug_get_num_option("NV50_PROG_OPTIMIZE", 3);
125bf215546Sopenharmony_ci   info.dbgFlags = debug_get_num_option("NV50_PROG_DEBUG", 0);
126bf215546Sopenharmony_ci   info.omitLineNum = debug_get_num_option("NV50_PROG_DEBUG_OMIT_LINENUM", 0);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   ret = nv50_ir_generate_code(&info, &info_out);
129bf215546Sopenharmony_ci   if (ret) {
130bf215546Sopenharmony_ci      _debug_printf("Error compiling program: %d\n", ret);
131bf215546Sopenharmony_ci      return ret;
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   *size = info_out.bin.codeSize;
135bf215546Sopenharmony_ci   *code = info_out.bin.code;
136bf215546Sopenharmony_ci   return 0;
137bf215546Sopenharmony_ci}
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ciint
140bf215546Sopenharmony_cimain(int argc, char *argv[])
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   struct tgsi_token tokens[4096];
143bf215546Sopenharmony_ci   int i, chipset = 0, type = -1;
144bf215546Sopenharmony_ci   const char *filename = NULL;
145bf215546Sopenharmony_ci   FILE *f;
146bf215546Sopenharmony_ci   char text[65536] = {0};
147bf215546Sopenharmony_ci   unsigned size = 0, *code = NULL;
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   for (i = 1; i < argc; i++) {
150bf215546Sopenharmony_ci      if (!strcmp(argv[i], "-a"))
151bf215546Sopenharmony_ci         chipset = strtol(argv[++i], NULL, 16);
152bf215546Sopenharmony_ci      else
153bf215546Sopenharmony_ci         filename = argv[i];
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   if (!chipset) {
157bf215546Sopenharmony_ci      _debug_printf("Must specify a chipset (-a)\n");
158bf215546Sopenharmony_ci      return 1;
159bf215546Sopenharmony_ci   }
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   if (!filename) {
162bf215546Sopenharmony_ci      _debug_printf("Must specify a filename\n");
163bf215546Sopenharmony_ci      return 1;
164bf215546Sopenharmony_ci   }
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   if (!strcmp(filename, "-"))
167bf215546Sopenharmony_ci      f = stdin;
168bf215546Sopenharmony_ci   else
169bf215546Sopenharmony_ci      f = fopen(filename, "r");
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   if (!f) {
172bf215546Sopenharmony_ci      _debug_printf("Error opening file '%s': %s\n", filename, strerror(errno));
173bf215546Sopenharmony_ci      return 1;
174bf215546Sopenharmony_ci   }
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   if (!fread(text, 1, sizeof(text), f) || ferror(f)) {
177bf215546Sopenharmony_ci      _debug_printf("Error reading file '%s'\n", filename);
178bf215546Sopenharmony_ci      fclose(f);
179bf215546Sopenharmony_ci      return 1;
180bf215546Sopenharmony_ci   }
181bf215546Sopenharmony_ci   fclose(f);
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci   _debug_printf("Compiling for NV%X\n", chipset);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   if (!strncmp(text, "FRAG", 4))
186bf215546Sopenharmony_ci      type = PIPE_SHADER_FRAGMENT;
187bf215546Sopenharmony_ci   else if (!strncmp(text, "VERT", 4))
188bf215546Sopenharmony_ci      type = PIPE_SHADER_VERTEX;
189bf215546Sopenharmony_ci   else if (!strncmp(text, "GEOM", 4))
190bf215546Sopenharmony_ci      type = PIPE_SHADER_GEOMETRY;
191bf215546Sopenharmony_ci   else if (!strncmp(text, "COMP", 4))
192bf215546Sopenharmony_ci      type = PIPE_SHADER_COMPUTE;
193bf215546Sopenharmony_ci   else if (!strncmp(text, "TESS_CTRL", 9))
194bf215546Sopenharmony_ci      type = PIPE_SHADER_TESS_CTRL;
195bf215546Sopenharmony_ci   else if (!strncmp(text, "TESS_EVAL", 9))
196bf215546Sopenharmony_ci      type = PIPE_SHADER_TESS_EVAL;
197bf215546Sopenharmony_ci   else {
198bf215546Sopenharmony_ci      _debug_printf("Unrecognized TGSI header\n");
199bf215546Sopenharmony_ci      return 1;
200bf215546Sopenharmony_ci   }
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
203bf215546Sopenharmony_ci      _debug_printf("Failed to parse TGSI shader\n");
204bf215546Sopenharmony_ci      return 1;
205bf215546Sopenharmony_ci   }
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   if (chipset >= 0x50) {
208bf215546Sopenharmony_ci      i = nouveau_codegen(chipset, type, tokens, &size, &code);
209bf215546Sopenharmony_ci   } else if (chipset >= 0x30) {
210bf215546Sopenharmony_ci      i = nv30_codegen(chipset, type, tokens, &size, &code);
211bf215546Sopenharmony_ci   } else {
212bf215546Sopenharmony_ci      _debug_printf("chipset NV%02X not supported\n", chipset);
213bf215546Sopenharmony_ci      i = 1;
214bf215546Sopenharmony_ci   }
215bf215546Sopenharmony_ci   if (i)
216bf215546Sopenharmony_ci      return i;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   _debug_printf("program binary (%d bytes)\n", size);
219bf215546Sopenharmony_ci   for (i = 0; i < size; i += 4) {
220bf215546Sopenharmony_ci      printf("%08x ", code[i / 4]);
221bf215546Sopenharmony_ci      if (i % (8 * 4) == (7 * 4))
222bf215546Sopenharmony_ci         printf("\n");
223bf215546Sopenharmony_ci   }
224bf215546Sopenharmony_ci   if (i % (8 * 4) != 0)
225bf215546Sopenharmony_ci      printf("\n");
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   return 0;
228bf215546Sopenharmony_ci}
229