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