• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2 
3 /*
4  * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Authors:
26  *    Rob Clark <robclark@freedesktop.org>
27  */
28 
29 #define LUA_COMPAT_APIINTCASTS
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <lua.h>
35 #include <lauxlib.h>
36 #include <lualib.h>
37 #include <assert.h>
38 
39 #include "script.h"
40 #include "cffdec.h"
41 #include "rnnutil.h"
42 
43 static lua_State *L;
44 
45 #if 0
46 #define DBG(fmt, ...) \
47 		do { printf(" ** %s:%d ** "fmt "\n", \
48 				__FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0)
49 #else
50 #define DBG(fmt, ...) do {} while (0)
51 #endif
52 
53 /* An rnn based decoder, which can either be decoding current register
54  * values, or domain based decoding of a pm4 packet.
55  *
56  */
57 struct rnndec {
58 	struct rnn base;
59 
60 	/* for pm4 packet decoding: */
61 	uint32_t sizedwords;
62 	uint32_t *dwords;
63 };
64 
to_rnndec(struct rnn * rnn)65 static inline struct rnndec *to_rnndec(struct rnn *rnn)
66 {
67 	return (struct rnndec *)rnn;
68 }
69 
rnn_val(struct rnn * rnn,uint32_t regbase)70 static uint32_t rnn_val(struct rnn *rnn, uint32_t regbase)
71 {
72 	struct rnndec *rnndec = to_rnndec(rnn);
73 
74 	if (!rnndec->sizedwords) {
75 		return reg_val(regbase);
76 	} else if (regbase < rnndec->sizedwords) {
77 		return rnndec->dwords[regbase];
78 	} else {
79 		// XXX throw an error
80 		return -1;
81 	}
82 }
83 
84 /* does not return */
error(const char * fmt)85 static void error(const char *fmt)
86 {
87 	fprintf(stderr, fmt, lua_tostring(L, -1));
88 	exit(1);
89 }
90 
91 /*
92  * An enum type that can be used as string or number:
93  */
94 
95 struct rnndenum {
96 	const char *str;
97 	int val;
98 };
99 
l_meta_rnn_enum_tostring(lua_State * L)100 static int l_meta_rnn_enum_tostring(lua_State *L)
101 {
102 	struct rnndenum *e = lua_touserdata(L, 1);
103 	if (e->str) {
104 		lua_pushstring(L, e->str);
105 	} else {
106 		char buf[32];
107 		sprintf(buf, "%u", e->val);
108 		lua_pushstring(L, buf);
109 	}
110 	return 1;
111 }
112 
113 /* so, this doesn't actually seem to be implemented yet, but hopefully
114  * some day lua comes to it's senses
115  */
l_meta_rnn_enum_tonumber(lua_State * L)116 static int l_meta_rnn_enum_tonumber(lua_State *L)
117 {
118 	struct rnndenum *e = lua_touserdata(L, 1);
119 	lua_pushinteger(L, e->val);
120 	return 1;
121 }
122 
123 static const struct luaL_Reg l_meta_rnn_enum[] = {
124 	{"__tostring", l_meta_rnn_enum_tostring},
125 	{"__tonumber", l_meta_rnn_enum_tonumber},
126 	{NULL, NULL}  /* sentinel */
127 };
128 
pushenum(struct lua_State * L,int val,struct rnnenum * info)129 static void pushenum(struct lua_State *L, int val, struct rnnenum *info)
130 {
131 	struct rnndenum *e = lua_newuserdata(L, sizeof(*e));
132 
133 	e->val = val;
134 	e->str = NULL;
135 
136 	for (int i = 0; i < info->valsnum; i++) {
137 		if (info->vals[i]->valvalid && (info->vals[i]->value == val)) {
138 			e->str = info->vals[i]->name;
139 			break;
140 		}
141 	}
142 
143 	luaL_newmetatable(L, "rnnmetaenum");
144 	luaL_setfuncs(L, l_meta_rnn_enum, 0);
145 	lua_pop(L, 1);
146 
147 	luaL_setmetatable(L, "rnnmetaenum");
148 }
149 
150 /* Expose rnn decode to script environment as "rnn" library:
151  */
152 
153 struct rnndoff {
154 	struct rnn *rnn;
155 	struct rnndelem *elem;
156 	uint64_t offset;
157 };
158 
push_rnndoff(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)159 static void push_rnndoff(lua_State *L, struct rnn *rnn,
160 		struct rnndelem *elem, uint64_t offset)
161 {
162 	struct rnndoff *rnndoff = lua_newuserdata(L, sizeof(*rnndoff));
163 	rnndoff->rnn = rnn;
164 	rnndoff->elem = elem;
165 	rnndoff->offset = offset;
166 }
167 
168 static int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
169 		struct rnndelem *elem, uint64_t offset);
170 static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn,
171 		struct rnndelem *elem, uint64_t offset);
172 
pushdecval(struct lua_State * L,struct rnn * rnn,uint32_t regval,struct rnntypeinfo * info)173 static int pushdecval(struct lua_State *L, struct rnn *rnn,
174 		uint32_t regval, struct rnntypeinfo *info)
175 {
176 	union rnndecval val;
177 	switch (rnn_decodelem(rnn, info, regval, &val)) {
178 	case RNN_TTYPE_ENUM:
179 	case RNN_TTYPE_INLINE_ENUM:
180 		pushenum(L, val.i, info->eenum);
181 		return 1;
182 	case RNN_TTYPE_INT:
183 		lua_pushinteger(L, val.i);
184 		return 1;
185 	case RNN_TTYPE_UINT:
186 	case RNN_TTYPE_HEX:
187 		lua_pushunsigned(L, val.u);
188 		return 1;
189 	case RNN_TTYPE_FLOAT:
190 		lua_pushnumber(L, val.f);
191 		return 1;
192 	case RNN_TTYPE_BOOLEAN:
193 		lua_pushboolean(L, val.u);
194 		return 1;
195 	case RNN_TTYPE_INVALID:
196 	default:
197 		return 0;
198 	}
199 
200 }
201 
l_rnn_etype(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)202 static int l_rnn_etype(lua_State *L, struct rnn *rnn,
203 		struct rnndelem *elem, uint64_t offset)
204 {
205 	int ret;
206 	uint32_t regval;
207 	DBG("elem=%p (%d), offset=%lu", elem, elem->type, offset);
208 	switch (elem->type) {
209 	case RNN_ETYPE_REG:
210 		/* if a register has no bitfields, just return
211 		 * the raw value:
212 		 */
213 		regval = rnn_val(rnn, offset);
214 		regval <<= elem->typeinfo.shr;
215 		ret = pushdecval(L, rnn, regval, &elem->typeinfo);
216 		if (ret)
217 			return ret;
218 		return l_rnn_etype_reg(L, rnn, elem, offset);
219 	case RNN_ETYPE_ARRAY:
220 		return l_rnn_etype_array(L, rnn, elem, offset);
221 	default:
222 		/* hmm.. */
223 		printf("unhandled type: %d\n", elem->type);
224 		return 0;
225 	}
226 }
227 
228 /*
229  * Struct Object:
230  * To implement stuff like 'RB_MRT[n].CONTROL' we need a struct-object
231  * to represent the current array index (ie. 'RB_MRT[n]')
232  */
233 
l_rnn_struct_meta_index(lua_State * L)234 static int l_rnn_struct_meta_index(lua_State *L)
235 {
236 	struct rnndoff *rnndoff = lua_touserdata(L, 1);
237 	const char *name = lua_tostring(L, 2);
238 	struct rnndelem *elem = rnndoff->elem;
239 	int i;
240 
241 	for (i = 0; i < elem->subelemsnum; i++) {
242 		struct rnndelem *subelem = elem->subelems[i];
243 		if (!strcmp(name, subelem->name)) {
244 			return l_rnn_etype(L, rnndoff->rnn, subelem,
245 					rnndoff->offset + subelem->offset);
246 		}
247 	}
248 
249 	return 0;
250 }
251 
252 static const struct luaL_Reg l_meta_rnn_struct[] = {
253 	{"__index", l_rnn_struct_meta_index},
254 	{NULL, NULL}  /* sentinel */
255 };
256 
l_rnn_etype_struct(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)257 static int l_rnn_etype_struct(lua_State *L, struct rnn *rnn,
258 		struct rnndelem *elem, uint64_t offset)
259 {
260 	push_rnndoff(L, rnn, elem, offset);
261 
262 	luaL_newmetatable(L, "rnnmetastruct");
263 	luaL_setfuncs(L, l_meta_rnn_struct, 0);
264 	lua_pop(L, 1);
265 
266 	luaL_setmetatable(L, "rnnmetastruct");
267 
268 	return 1;
269 }
270 
271 /*
272  * Array Object:
273  */
274 
l_rnn_array_meta_index(lua_State * L)275 static int l_rnn_array_meta_index(lua_State *L)
276 {
277 	struct rnndoff *rnndoff = lua_touserdata(L, 1);
278 	int idx = lua_tointeger(L, 2);
279 	struct rnndelem *elem = rnndoff->elem;
280 	uint64_t offset = rnndoff->offset + (elem->stride * idx);
281 
282 	DBG("rnndoff=%p, idx=%d, numsubelems=%d",
283 			rnndoff, idx, rnndoff->elem->subelemsnum);
284 
285 	/* if just a single sub-element, it is directly a register,
286 	 * otherwise we need to accumulate the array index while
287 	 * we wait for the register name within the array..
288 	 */
289 	if (elem->subelemsnum == 1) {
290 		return l_rnn_etype(L, rnndoff->rnn, elem->subelems[0], offset);
291 	} else {
292 		return l_rnn_etype_struct(L, rnndoff->rnn, elem, offset);
293 	}
294 
295 	return 0;
296 }
297 
298 static const struct luaL_Reg l_meta_rnn_array[] = {
299 	{"__index", l_rnn_array_meta_index},
300 	{NULL, NULL}  /* sentinel */
301 };
302 
l_rnn_etype_array(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)303 static int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
304 		struct rnndelem *elem, uint64_t offset)
305 {
306 	push_rnndoff(L, rnn, elem, offset);
307 
308 	luaL_newmetatable(L, "rnnmetaarray");
309 	luaL_setfuncs(L, l_meta_rnn_array, 0);
310 	lua_pop(L, 1);
311 
312 	luaL_setmetatable(L, "rnnmetaarray");
313 
314 	return 1;
315 }
316 
317 /*
318  * Register element:
319  */
320 
l_rnn_reg_meta_index(lua_State * L)321 static int l_rnn_reg_meta_index(lua_State *L)
322 {
323 	struct rnndoff *rnndoff = lua_touserdata(L, 1);
324 	const char *name = lua_tostring(L, 2);
325 	struct rnndelem *elem = rnndoff->elem;
326 	struct rnntypeinfo *info = &elem->typeinfo;
327 	struct rnnbitfield **bitfields;
328 	int bitfieldsnum;
329 	int i;
330 
331 	switch (info->type) {
332 	case RNN_TTYPE_BITSET:
333 		bitfields = info->ebitset->bitfields;
334 		bitfieldsnum = info->ebitset->bitfieldsnum;
335 		break;
336 	case RNN_TTYPE_INLINE_BITSET:
337 		bitfields = info->bitfields;
338 		bitfieldsnum = info->bitfieldsnum;
339 		break;
340 	default:
341 		printf("invalid register type: %d\n", info->type);
342 		return 0;
343 	}
344 
345 	for (i = 0; i < bitfieldsnum; i++) {
346 		struct rnnbitfield *bf = bitfields[i];
347 		if (!strcmp(name, bf->name)) {
348 			uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
349 
350 			regval &= typeinfo_mask(&bf->typeinfo);
351 			regval >>= bf->typeinfo.low;
352 			regval <<= bf->typeinfo.shr;
353 
354 			DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x",
355 					name, info, rnndoff->elem->subelemsnum,
356 					bf->typeinfo.type, regval);
357 
358 			return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo);
359 		}
360 	}
361 
362 	printf("invalid member: %s\n", name);
363 	return 0;
364 }
365 
l_rnn_reg_meta_tostring(lua_State * L)366 static int l_rnn_reg_meta_tostring(lua_State *L)
367 {
368 	struct rnndoff *rnndoff = lua_touserdata(L, 1);
369 	uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
370 	struct rnndecaddrinfo *info = rnn_reginfo(rnndoff->rnn, rnndoff->offset);
371 	char *decoded;
372 	if (info && info->typeinfo) {
373 		decoded = rnndec_decodeval(rnndoff->rnn->vc,
374 				info->typeinfo, regval);
375 	} else {
376 		asprintf(&decoded, "%08x", regval);
377 	}
378 	lua_pushstring(L, decoded);
379 	free(decoded);
380 	if (info) {
381 		free(info->name);
382 		free(info);
383 	}
384 	return 1;
385 }
386 
l_rnn_reg_meta_tonumber(lua_State * L)387 static int l_rnn_reg_meta_tonumber(lua_State *L)
388 {
389 	struct rnndoff *rnndoff = lua_touserdata(L, 1);
390 	uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
391 
392 	regval <<= rnndoff->elem->typeinfo.shr;
393 
394 	lua_pushnumber(L, regval);
395 	return 1;
396 }
397 
398 static const struct luaL_Reg l_meta_rnn_reg[] = {
399 	{"__index", l_rnn_reg_meta_index},
400 	{"__tostring", l_rnn_reg_meta_tostring},
401 	{"__tonumber", l_rnn_reg_meta_tonumber},
402 	{NULL, NULL}  /* sentinel */
403 };
404 
l_rnn_etype_reg(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)405 static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn,
406 		struct rnndelem *elem, uint64_t offset)
407 {
408 	push_rnndoff(L, rnn, elem, offset);
409 
410 	luaL_newmetatable(L, "rnnmetareg");
411 	luaL_setfuncs(L, l_meta_rnn_reg, 0);
412 	lua_pop(L, 1);
413 
414 	luaL_setmetatable(L, "rnnmetareg");
415 
416 	return 1;
417 }
418 
419 /*
420  *
421  */
422 
l_rnn_meta_index(lua_State * L)423 static int l_rnn_meta_index(lua_State *L)
424 {
425 	struct rnn *rnn = lua_touserdata(L, 1);
426 	const char *name = lua_tostring(L, 2);
427 	struct rnndelem *elem;
428 
429 	elem = rnn_regelem(rnn, name);
430 	if (!elem)
431 		return 0;
432 
433 	return l_rnn_etype(L, rnn, elem, elem->offset);
434 }
435 
l_rnn_meta_gc(lua_State * L)436 static int l_rnn_meta_gc(lua_State *L)
437 {
438 	// TODO
439 	//struct rnn *rnn = lua_touserdata(L, 1);
440 	//rnn_deinit(rnn);
441 	return 0;
442 }
443 
444 static const struct luaL_Reg l_meta_rnn[] = {
445 	{"__index", l_rnn_meta_index},
446 	{"__gc", l_rnn_meta_gc},
447 	{NULL, NULL}  /* sentinel */
448 };
449 
l_rnn_init(lua_State * L)450 static int l_rnn_init(lua_State *L)
451 {
452 	const char *gpuname = lua_tostring(L, 1);
453 	struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
454 	_rnn_init(&rnndec->base, 0);
455 	rnn_load(&rnndec->base, gpuname);
456 	rnndec->sizedwords = 0;
457 
458 	luaL_newmetatable(L, "rnnmeta");
459 	luaL_setfuncs(L, l_meta_rnn, 0);
460 	lua_pop(L, 1);
461 
462 	luaL_setmetatable(L, "rnnmeta");
463 
464 	return 1;
465 }
466 
l_rnn_enumname(lua_State * L)467 static int l_rnn_enumname(lua_State *L)
468 {
469 	struct rnn *rnn = lua_touserdata(L, 1);
470 	const char *name = lua_tostring(L, 2);
471 	uint32_t val = (uint32_t)lua_tonumber(L, 3);
472 	lua_pushstring(L, rnn_enumname(rnn, name, val));
473 	return 1;
474 }
475 
l_rnn_regname(lua_State * L)476 static int l_rnn_regname(lua_State *L)
477 {
478 	struct rnn *rnn = lua_touserdata(L, 1);
479 	uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
480 	lua_pushstring(L, rnn_regname(rnn, regbase, 1));
481 	return 1;
482 }
483 
l_rnn_regval(lua_State * L)484 static int l_rnn_regval(lua_State *L)
485 {
486 	struct rnn *rnn = lua_touserdata(L, 1);
487 	uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
488 	uint32_t regval = (uint32_t)lua_tonumber(L, 3);
489 	struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
490 	char *decoded;
491 	if (info && info->typeinfo) {
492 		decoded = rnndec_decodeval(rnn->vc, info->typeinfo, regval);
493 	} else {
494 		asprintf(&decoded, "%08x", regval);
495 	}
496 	lua_pushstring(L, decoded);
497 	free(decoded);
498 	if (info) {
499 		free(info->name);
500 		free(info);
501 	}
502 	return 1;
503 }
504 
505 static const struct luaL_Reg l_rnn[] = {
506 	{"init", l_rnn_init},
507 	{"enumname", l_rnn_enumname},
508 	{"regname", l_rnn_regname},
509 	{"regval", l_rnn_regval},
510 	{NULL, NULL}  /* sentinel */
511 };
512 
513 
514 
515 /* Expose the register state to script enviroment as a "regs" library:
516  */
517 
l_reg_written(lua_State * L)518 static int l_reg_written(lua_State *L)
519 {
520 	uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
521 	lua_pushnumber(L, reg_written(regbase));
522 	return 1;
523 }
524 
l_reg_lastval(lua_State * L)525 static int l_reg_lastval(lua_State *L)
526 {
527 	uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
528 	lua_pushnumber(L, reg_lastval(regbase));
529 	return 1;
530 }
531 
l_reg_val(lua_State * L)532 static int l_reg_val(lua_State *L)
533 {
534 	uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
535 	lua_pushnumber(L, reg_val(regbase));
536 	return 1;
537 }
538 
539 static const struct luaL_Reg l_regs[] = {
540 	{"written", l_reg_written},
541 	{"lastval", l_reg_lastval},
542 	{"val",     l_reg_val},
543 	{NULL, NULL}  /* sentinel */
544 };
545 
546 /* Expose API to lookup snapshot buffers:
547  */
548 
549 uint64_t gpubaseaddr(uint64_t gpuaddr);
550 unsigned hostlen(uint64_t gpuaddr);
551 
552 /* given address, return base-address of buffer: */
l_bo_base(lua_State * L)553 static int l_bo_base(lua_State *L)
554 {
555 	uint64_t addr = (uint64_t)lua_tonumber(L, 1);
556 	lua_pushnumber(L, gpubaseaddr(addr));
557 	return 1;
558 }
559 
560 /* given address, return the remaining size of the buffer: */
l_bo_size(lua_State * L)561 static int l_bo_size(lua_State *L)
562 {
563 	uint64_t addr = (uint64_t)lua_tonumber(L, 1);
564 	lua_pushnumber(L, hostlen(addr));
565 	return 1;
566 }
567 
568 static const struct luaL_Reg l_bos[] = {
569 	{"base", l_bo_base},
570 	{"size", l_bo_size},
571 	{NULL, NULL}  /* sentinel */
572 };
573 
openlib(const char * lib,const luaL_Reg * reg)574 static void openlib(const char *lib, const luaL_Reg *reg)
575 {
576   lua_newtable(L);
577   luaL_setfuncs(L, reg, 0);
578   lua_setglobal(L, lib);
579 }
580 
581 /* called at start to load the script: */
script_load(const char * file)582 int script_load(const char *file)
583 {
584 	int ret;
585 
586 	assert(!L);
587 
588 	L = luaL_newstate();
589 	luaL_openlibs(L);
590 	openlib("bos", l_bos);
591 	openlib("regs", l_regs);
592 	openlib("rnn", l_rnn);
593 
594 	ret = luaL_loadfile(L, file);
595 	if (ret)
596 		error("%s\n");
597 
598 	ret = lua_pcall(L, 0, LUA_MULTRET, 0);
599 	if (ret)
600 		error("%s\n");
601 
602 	return 0;
603 }
604 
605 
606 /* called at start of each cmdstream file: */
script_start_cmdstream(const char * name)607 void script_start_cmdstream(const char *name)
608 {
609 	if (!L)
610 		return;
611 
612 	lua_getglobal(L, "start_cmdstream");
613 
614 	/* if no handler just ignore it: */
615 	if (!lua_isfunction(L, -1)) {
616 		lua_pop(L, 1);
617 		return;
618 	}
619 
620 	lua_pushstring(L, name);
621 
622 	/* do the call (1 arguments, 0 result) */
623 	if (lua_pcall(L, 1, 0, 0) != 0)
624 		error("error running function `f': %s\n");
625 }
626 
627 /* called at each DRAW_INDX, calls script drawidx fxn to process
628  * the current state
629  */
script_draw(const char * primtype,uint32_t nindx)630 void script_draw(const char *primtype, uint32_t nindx)
631 {
632 	if (!L)
633 		return;
634 
635 	lua_getglobal(L, "draw");
636 
637 	/* if no handler just ignore it: */
638 	if (!lua_isfunction(L, -1)) {
639 		lua_pop(L, 1);
640 		return;
641 	}
642 
643 	lua_pushstring(L, primtype);
644 	lua_pushnumber(L, nindx);
645 
646 	/* do the call (2 arguments, 0 result) */
647 	if (lua_pcall(L, 2, 0, 0) != 0)
648 		error("error running function `f': %s\n");
649 }
650 
651 
l_rnn_meta_dom_index(lua_State * L)652 static int l_rnn_meta_dom_index(lua_State *L)
653 {
654 	struct rnn *rnn = lua_touserdata(L, 1);
655 	uint32_t offset = (uint32_t)lua_tonumber(L, 2);
656 	struct rnndelem *elem;
657 
658 	/* TODO might be nicer if the arg isn't a number, to search the domain
659 	 * for matching bitfields.. so that the script could do something like
660 	 * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
661 	 * offset of the dword containing the bitfield..
662 	 */
663 
664 	elem = rnn_regoff(rnn, offset);
665 	if (!elem)
666 		return 0;
667 
668 	return l_rnn_etype(L, rnn, elem, elem->offset);
669 }
670 
671 /*
672  * A wrapper object for rnndomain based decoding of an array of dwords
673  * (ie. for pm4 packet decoding).  Mostly re-uses the register-value
674  * decoding for the individual dwords and bitfields.
675  */
676 
l_rnn_meta_dom_gc(lua_State * L)677 static int l_rnn_meta_dom_gc(lua_State *L)
678 {
679 	// TODO
680 	//struct rnn *rnn = lua_touserdata(L, 1);
681 	//rnn_deinit(rnn);
682 	return 0;
683 }
684 
685 static const struct luaL_Reg l_meta_rnn_dom[] = {
686 	{"__index", l_rnn_meta_dom_index},
687 	{"__gc", l_rnn_meta_dom_gc},
688 	{NULL, NULL}  /* sentinel */
689 };
690 
691 /* called to general pm4 packet decoding, such as texture/sampler state
692  */
script_packet(uint32_t * dwords,uint32_t sizedwords,struct rnn * rnn,struct rnndomain * dom)693 void script_packet(uint32_t *dwords, uint32_t sizedwords,
694 		struct rnn *rnn, struct rnndomain *dom)
695 {
696 	if (!L)
697 		return;
698 
699 	lua_getglobal(L, dom->name);
700 
701 	/* if no handler for the packet, just ignore it: */
702 	if (!lua_isfunction(L, -1)) {
703 		lua_pop(L, 1);
704 		return;
705 	}
706 
707 	struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
708 
709 	rnndec->base = *rnn;
710 	rnndec->base.dom[0] = dom;
711 	rnndec->base.dom[1] = NULL;
712 	rnndec->dwords = dwords;
713 	rnndec->sizedwords = sizedwords;
714 
715 	luaL_newmetatable(L, "rnnmetadom");
716 	luaL_setfuncs(L, l_meta_rnn_dom, 0);
717 	lua_pop(L, 1);
718 
719 	luaL_setmetatable(L, "rnnmetadom");
720 
721 	lua_pushnumber(L, sizedwords);
722 
723 	if (lua_pcall(L, 2, 0, 0) != 0)
724 		error("error running function `f': %s\n");
725 }
726 
727 /* helper to call fxn that takes and returns void: */
simple_call(const char * name)728 static void simple_call(const char *name)
729 {
730 	if (!L)
731 		return;
732 
733 	lua_getglobal(L, name);
734 
735 	/* if no handler just ignore it: */
736 	if (!lua_isfunction(L, -1)) {
737 		lua_pop(L, 1);
738 		return;
739 	}
740 
741 	/* do the call (0 arguments, 0 result) */
742 	if (lua_pcall(L, 0, 0, 0) != 0)
743 		error("error running function `f': %s\n");
744 }
745 
746 /* called at end of each cmdstream file: */
script_end_cmdstream(void)747 void script_end_cmdstream(void)
748 {
749 	simple_call("end_cmdstream");
750 }
751 
752 /* called at start of submit/issueibcmds: */
script_start_submit(void)753 void script_start_submit(void)
754 {
755 	simple_call("start_submit");
756 }
757 
758 /* called at end of submit/issueibcmds: */
script_end_submit(void)759 void script_end_submit(void)
760 {
761 	simple_call("end_submit");
762 }
763 
764 /* called after last cmdstream file: */
script_finish(void)765 void script_finish(void)
766 {
767 	if (!L)
768 		return;
769 
770 	simple_call("finish");
771 
772 	lua_close(L);
773 	L = NULL;
774 }
775