8 #include "../radeon_compiler_util.h"
9 #include "../radeon_opcodes.h"
10 #include "../radeon_program.h"
12 #include "rc_test_helpers.h"
14 /* This file contains some helper functions for filling out the rc_instruction
15 * data structures. These functions take a string as input based on the format
16 * output by rc_program_print().
21 #define DBG(...) do { if (VERBOSE) fprintf(stderr, __VA_ARGS__); } while(0)
23 #define REGEX_ERR_BUF_SIZE 50
30 static int match_length(regmatch_t
* matches
, int index
)
32 return matches
[index
].rm_eo
- matches
[index
].rm_so
;
35 static int regex_helper(
36 const char * regex_str
,
37 const char * search_str
,
41 char err_buf
[REGEX_ERR_BUF_SIZE
];
46 err_code
= regcomp(®ex
, regex_str
, REG_EXTENDED
);
48 regerror(err_code
, ®ex
, err_buf
, REGEX_ERR_BUF_SIZE
);
49 fprintf(stderr
, "Failed to compile regex: %s\n", err_buf
);
53 err_code
= regexec(®ex
, search_str
, num_matches
, matches
, 0);
54 DBG("Search string: '%s'\n", search_str
);
55 for (i
= 0; i
< num_matches
; i
++) {
56 DBG("Match %u start = %d end = %d\n", i
,
57 matches
[i
].rm_so
, matches
[i
].rm_eo
);
60 regerror(err_code
, ®ex
, err_buf
, REGEX_ERR_BUF_SIZE
);
61 fprintf(stderr
, "Failed to match regex: %s\n", err_buf
);
67 #define REGEX_SRC_MATCHES 6
70 struct match_info Negate
;
71 struct match_info Abs
;
72 struct match_info File
;
73 struct match_info Index
;
74 struct match_info Swizzle
;
78 * Initialize the source register at index src_index for the instruction based
81 * NOTE: Warning in init_rc_normal_instruction() applies to this function as
84 * @param src_str A string that represents the source register. The format for
85 * this string is the same that is output by rc_program_print.
86 * @return 1 On success, 0 on failure
88 int init_rc_normal_src(
89 struct rc_instruction
* inst
,
90 unsigned int src_index
,
93 const char * regex_str
= "(-*)(\\|*)([[:lower:]]*)\\[([[:digit:]])\\](\\.*[[:lower:]-]*)";
94 regmatch_t matches
[REGEX_SRC_MATCHES
];
95 struct src_tokens tokens
;
96 struct rc_src_register
* src_reg
= &inst
->U
.I
.SrcReg
[src_index
];
99 /* Execute the regex */
100 if (!regex_helper(regex_str
, src_str
, matches
, REGEX_SRC_MATCHES
)) {
101 fprintf(stderr
, "Failed to execute regex for src register.\n");
106 tokens
.Negate
.String
= src_str
+ matches
[1].rm_so
;
107 tokens
.Negate
.Length
= match_length(matches
, 1);
108 tokens
.Abs
.String
= src_str
+ matches
[2].rm_so
;
109 tokens
.Abs
.Length
= match_length(matches
, 2);
110 tokens
.File
.String
= src_str
+ matches
[3].rm_so
;
111 tokens
.File
.Length
= match_length(matches
, 3);
112 tokens
.Index
.String
= src_str
+ matches
[4].rm_so
;
113 tokens
.Index
.Length
= match_length(matches
, 4);
114 tokens
.Swizzle
.String
= src_str
+ matches
[5].rm_so
;
115 tokens
.Swizzle
.Length
= match_length(matches
, 5);
118 if (tokens
.Negate
.Length
> 0) {
119 src_reg
->Negate
= RC_MASK_XYZW
;
123 if (tokens
.Abs
.Length
> 0) {
128 if (!strncmp(tokens
.File
.String
, "temp", tokens
.File
.Length
)) {
129 src_reg
->File
= RC_FILE_TEMPORARY
;
130 } else if (!strncmp(tokens
.File
.String
, "input", tokens
.File
.Length
)) {
131 src_reg
->File
= RC_FILE_INPUT
;
132 } else if (!strncmp(tokens
.File
.String
, "const", tokens
.File
.Length
)) {
133 src_reg
->File
= RC_FILE_CONSTANT
;
134 } else if (!strncmp(tokens
.File
.String
, "none", tokens
.File
.Length
)) {
135 src_reg
->File
= RC_FILE_NONE
;
140 src_reg
->Index
= strtol(tokens
.Index
.String
, NULL
, 10);
142 fprintf(stderr
, "Could not convert src register index.\n");
147 if (tokens
.Swizzle
.Length
== 0) {
148 src_reg
->Swizzle
= RC_SWIZZLE_XYZW
;
151 src_reg
->Swizzle
= RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_UNUSED
);
152 if (tokens
.Swizzle
.String
[0] != '.') {
153 fprintf(stderr
, "First char of swizzle is not valid.\n");
156 for (i
= 0; i
< 4; i
++, str_index
++) {
157 if (tokens
.Swizzle
.String
[str_index
] == '-') {
158 src_reg
->Negate
|= (1 << i
);
161 switch(tokens
.Swizzle
.String
[str_index
]) {
163 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_X
);
166 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_Y
);
169 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_Z
);
172 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_W
);
175 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_ONE
);
178 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_ZERO
);
181 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_HALF
);
184 SET_SWZ(src_reg
->Swizzle
, i
, RC_SWIZZLE_UNUSED
);
187 fprintf(stderr
, "Unknown src register swizzle.\n");
192 DBG("File=%u index=%u swizzle=%x negate=%u abs=%u\n",
193 src_reg
->File
, src_reg
->Index
, src_reg
->Swizzle
,
194 src_reg
->Negate
, src_reg
->Abs
);
198 #define REGEX_DST_MATCHES 4
201 struct match_info File
;
202 struct match_info Index
;
203 struct match_info WriteMask
;
207 * Initialize the destination for the instruction based on dst_str.
209 * NOTE: Warning in init_rc_normal_instruction() applies to this function as
212 * @param dst_str A string that represents the destination register. The format
213 * for this string is the same that is output by rc_program_print.
214 * @return 1 On success, 0 on failure
216 int init_rc_normal_dst(
217 struct rc_instruction
* inst
,
218 const char * dst_str
)
220 const char * regex_str
= "([[:lower:]]*)\\[([[:digit:]]*)\\](\\.*[[:lower:]]*)";
221 regmatch_t matches
[REGEX_DST_MATCHES
];
222 struct dst_tokens tokens
;
225 /* Execute the regex */
226 if (!regex_helper(regex_str
, dst_str
, matches
, REGEX_DST_MATCHES
)) {
227 fprintf(stderr
, "Failed to execute regex for dst register.\n");
232 tokens
.File
.String
= dst_str
+ matches
[1].rm_so
;
233 tokens
.File
.Length
= match_length(matches
, 1);
234 tokens
.Index
.String
= dst_str
+ matches
[2].rm_so
;
235 tokens
.Index
.Length
= match_length(matches
, 2);
236 tokens
.WriteMask
.String
= dst_str
+ matches
[3].rm_so
;
237 tokens
.WriteMask
.Length
= match_length(matches
, 3);
240 if (!strncmp(tokens
.File
.String
, "temp", tokens
.File
.Length
)) {
241 inst
->U
.I
.DstReg
.File
= RC_FILE_TEMPORARY
;
242 } else if (!strncmp(tokens
.File
.String
, "output", tokens
.File
.Length
)) {
243 inst
->U
.I
.DstReg
.File
= RC_FILE_OUTPUT
;
245 fprintf(stderr
, "Unknown dst register file type.\n");
251 inst
->U
.I
.DstReg
.Index
= strtol(tokens
.Index
.String
, NULL
, 10);
254 fprintf(stderr
, "Could not convert dst register index\n");
259 if (tokens
.WriteMask
.Length
== 0) {
260 inst
->U
.I
.DstReg
.WriteMask
= RC_MASK_XYZW
;
262 /* The first character should be '.' */
263 if (tokens
.WriteMask
.String
[0] != '.') {
264 fprintf(stderr
, "1st char of writemask is not valid.\n");
267 for (i
= 1; i
< tokens
.WriteMask
.Length
; i
++) {
268 switch(tokens
.WriteMask
.String
[i
]) {
270 inst
->U
.I
.DstReg
.WriteMask
|= RC_MASK_X
;
273 inst
->U
.I
.DstReg
.WriteMask
|= RC_MASK_Y
;
276 inst
->U
.I
.DstReg
.WriteMask
|= RC_MASK_Z
;
279 inst
->U
.I
.DstReg
.WriteMask
|= RC_MASK_W
;
282 fprintf(stderr
, "Unknown swizzle in writemask.\n");
287 DBG("Dst Reg File=%u Index=%d Writemask=%d\n",
288 inst
->U
.I
.DstReg
.File
,
289 inst
->U
.I
.DstReg
.Index
,
290 inst
->U
.I
.DstReg
.WriteMask
);
294 #define REGEX_INST_MATCHES 7
297 struct match_info Opcode
;
298 struct match_info Sat
;
299 struct match_info Dst
;
300 struct match_info Srcs
[3];
304 * Initialize a normal instruction based on inst_str.
306 * WARNING: This function might not be able to handle every kind of format that
307 * rc_program_print() can output. If you are having problems with a
308 * particular string, you may need to add support for it to this functions.
310 * @param inst_str A string that represents the source register. The format for
311 * this string is the same that is output by rc_program_print.
312 * @return 1 On success, 0 on failure
314 int init_rc_normal_instruction(
315 struct rc_instruction
* inst
,
316 const char * inst_str
)
318 const char * regex_str
= "([[:upper:]]+)(_SAT)* ([^,]*)[, ]*([^,]*)[, ]*([^,]*)[, ]*([^;]*)";
320 regmatch_t matches
[REGEX_INST_MATCHES
];
321 struct inst_tokens tokens
;
323 /* Initialize inst */
324 memset(inst
, 0, sizeof(struct rc_instruction
));
325 inst
->Type
= RC_INSTRUCTION_NORMAL
;
327 /* Execute the regex */
328 if (!regex_helper(regex_str
, inst_str
, matches
, REGEX_INST_MATCHES
)) {
331 memset(&tokens
, 0, sizeof(tokens
));
334 tokens
.Opcode
.String
= inst_str
+ matches
[1].rm_so
;
335 tokens
.Opcode
.Length
= match_length(matches
, 1);
336 if (matches
[2].rm_so
> -1) {
337 tokens
.Sat
.String
= inst_str
+ matches
[2].rm_so
;
338 tokens
.Sat
.Length
= match_length(matches
, 2);
342 /* Fill out the rest of the instruction. */
343 for (i
= 0; i
< MAX_RC_OPCODE
; i
++) {
344 const struct rc_opcode_info
* info
= rc_get_opcode_info(i
);
345 unsigned int first_src
= 3;
347 if (strncmp(tokens
.Opcode
.String
, info
->Name
, tokens
.Opcode
.Length
)) {
350 inst
->U
.I
.Opcode
= info
->Opcode
;
351 if (info
->HasDstReg
) {
353 tokens
.Dst
.String
= inst_str
+ matches
[3].rm_so
;
354 tokens
.Dst
.Length
= match_length(matches
, 3);
357 dst_str
= malloc(sizeof(char) * (tokens
.Dst
.Length
+ 1));
358 strncpy(dst_str
, tokens
.Dst
.String
, tokens
.Dst
.Length
);
359 dst_str
[tokens
.Dst
.Length
] = '\0';
360 init_rc_normal_dst(inst
, dst_str
);
363 for (j
= 0; j
< info
->NumSrcRegs
; j
++) {
365 tokens
.Srcs
[j
].String
=
366 inst_str
+ matches
[first_src
+ j
].rm_so
;
367 tokens
.Srcs
[j
].Length
=
368 match_length(matches
, first_src
+ j
);
370 src_str
= malloc(sizeof(char) *
371 (tokens
.Srcs
[j
].Length
+ 1));
372 strncpy(src_str
, tokens
.Srcs
[j
].String
,
373 tokens
.Srcs
[j
].Length
);
374 src_str
[tokens
.Srcs
[j
].Length
] = '\0';
375 init_rc_normal_src(inst
, j
, src_str
);