1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <errno.h>
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <regex.h>
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h>
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h>
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <string.h>
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <sys/types.h>
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "../radeon_compiler_util.h"
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "../radeon_opcodes.h"
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "../radeon_program.h"
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "rc_test_helpers.h"
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* This file contains some helper functions for filling out the rc_instruction
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * data structures.  These functions take a string as input based on the format
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * output by rc_program_print().
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VERBOSE 0
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define DBG(...) do { if (VERBOSE) fprintf(stderr, __VA_ARGS__); } while(0)
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define REGEX_ERR_BUF_SIZE 50
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct match_info {
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * String;
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int Length;
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int match_length(regmatch_t * matches, int index)
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return matches[index].rm_eo - matches[index].rm_so;
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int regex_helper(
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * regex_str,
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * search_str,
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	regmatch_t * matches,
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int num_matches)
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char err_buf[REGEX_ERR_BUF_SIZE];
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	regex_t regex;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int err_code;
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int i;
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	err_code = regcomp(&regex, regex_str, REG_EXTENDED);
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (err_code) {
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		regerror(err_code, &regex, err_buf, REGEX_ERR_BUF_SIZE);
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Failed to compile regex: %s\n", err_buf);
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	err_code = regexec(&regex, search_str, num_matches, matches, 0);
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	DBG("Search string: '%s'\n", search_str);
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (i = 0; i < num_matches; i++) {
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		DBG("Match %u start = %d end = %d\n", i,
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					matches[i].rm_so, matches[i].rm_eo);
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (err_code) {
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		regerror(err_code, &regex, err_buf, REGEX_ERR_BUF_SIZE);
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Failed to match regex: %s\n", err_buf);
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 1;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define REGEX_SRC_MATCHES 6
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct src_tokens {
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Negate;
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Abs;
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info File;
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Index;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Swizzle;
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Initialize the source register at index src_index for the instruction based
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * on src_str.
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * NOTE: Warning in init_rc_normal_instruction() applies to this function as
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * well.
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param src_str A string that represents the source register.  The format for
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * this string is the same that is output by rc_program_print.
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @return 1 On success, 0 on failure
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint init_rc_normal_src(
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int src_index,
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * src_str)
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[([[:digit:]])\\](\\.*[[:lower:]-]*)";
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	regmatch_t matches[REGEX_SRC_MATCHES];
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct src_tokens tokens;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_src_register * src_reg = &inst->U.I.SrcReg[src_index];
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int i;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Execute the regex */
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!regex_helper(regex_str, src_str, matches, REGEX_SRC_MATCHES)) {
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Failed to execute regex for src register.\n");
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Create Tokens */
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Negate.String = src_str + matches[1].rm_so;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Negate.Length = match_length(matches, 1);
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Abs.String = src_str + matches[2].rm_so;
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Abs.Length = match_length(matches, 2);
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.File.String = src_str + matches[3].rm_so;
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.File.Length = match_length(matches, 3);
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Index.String = src_str + matches[4].rm_so;
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Index.Length = match_length(matches, 4);
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Swizzle.String = src_str + matches[5].rm_so;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Swizzle.Length = match_length(matches, 5);
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Negate */
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (tokens.Negate.Length  > 0) {
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->Negate = RC_MASK_XYZW;
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Abs */
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (tokens.Abs.Length > 0) {
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->Abs = 1;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* File */
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!strncmp(tokens.File.String, "temp", tokens.File.Length)) {
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->File = RC_FILE_TEMPORARY;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else if (!strncmp(tokens.File.String, "input", tokens.File.Length)) {
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->File = RC_FILE_INPUT;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else if (!strncmp(tokens.File.String, "const", tokens.File.Length)) {
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->File = RC_FILE_CONSTANT;
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else if (!strncmp(tokens.File.String, "none", tokens.File.Length)) {
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->File = RC_FILE_NONE;
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Index */
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	errno = 0;
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	src_reg->Index = strtol(tokens.Index.String, NULL, 10);
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (errno > 0) {
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Could not convert src register index.\n");
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Swizzle */
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (tokens.Swizzle.Length == 0) {
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->Swizzle = RC_SWIZZLE_XYZW;
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		int str_index = 1;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		src_reg->Swizzle = RC_MAKE_SWIZZLE_SMEAR(RC_SWIZZLE_UNUSED);
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (tokens.Swizzle.String[0] != '.') {
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			fprintf(stderr, "First char of swizzle is not valid.\n");
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return 0;
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (i = 0; i < 4; i++, str_index++) {
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tokens.Swizzle.String[str_index] == '-') {
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				src_reg->Negate |= (1 << i);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				str_index++;
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch(tokens.Swizzle.String[str_index]) {
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'x':
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_X);
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'y':
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_Y);
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'z':
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_Z);
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'w':
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_W);
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '1':
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_ONE);
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '0':
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_ZERO);
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'H':
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_HALF);
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '_':
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_UNUSED);
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			default:
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, "Unknown src register swizzle.\n");
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				return 0;
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	DBG("File=%u index=%u swizzle=%x negate=%u abs=%u\n",
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			src_reg->File, src_reg->Index, src_reg->Swizzle,
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			src_reg->Negate, src_reg->Abs);
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 1;
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define REGEX_DST_MATCHES 4
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct dst_tokens {
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info File;
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Index;
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info WriteMask;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Initialize the destination for the instruction based on dst_str.
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * NOTE: Warning in init_rc_normal_instruction() applies to this function as
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * well.
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param dst_str A string that represents the destination register.  The format
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * for this string is the same that is output by rc_program_print.
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @return 1 On success, 0 on failure
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint init_rc_normal_dst(
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * dst_str)
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * regex_str = "([[:lower:]]*)\\[([[:digit:]]*)\\](\\.*[[:lower:]]*)";
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	regmatch_t matches[REGEX_DST_MATCHES];
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct dst_tokens tokens;
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int i;
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Execute the regex */
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!regex_helper(regex_str, dst_str, matches, REGEX_DST_MATCHES)) {
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Failed to execute regex for dst register.\n");
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Create Tokens */
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.File.String = dst_str + matches[1].rm_so;
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.File.Length = match_length(matches, 1);
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Index.String = dst_str + matches[2].rm_so;
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Index.Length = match_length(matches, 2);
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.WriteMask.String = dst_str + matches[3].rm_so;
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.WriteMask.Length = match_length(matches, 3);
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* File Type */
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!strncmp(tokens.File.String, "temp", tokens.File.Length)) {
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else if (!strncmp(tokens.File.String, "output", tokens.File.Length)) {
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->U.I.DstReg.File = RC_FILE_OUTPUT;
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Unknown dst register file type.\n");
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* File Index */
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	errno = 0;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.DstReg.Index = strtol(tokens.Index.String, NULL, 10);
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (errno > 0) {
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "Could not convert dst register index\n");
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* WriteMask */
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (tokens.WriteMask.Length == 0) {
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* The first character should be '.' */
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (tokens.WriteMask.String[0] != '.') {
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			fprintf(stderr, "1st char of writemask is not valid.\n");
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return 0;
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (i = 1; i < tokens.WriteMask.Length; i++) {
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch(tokens.WriteMask.String[i]) {
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'x':
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.WriteMask |= RC_MASK_X;
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'y':
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.WriteMask |= RC_MASK_Y;
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'z':
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.WriteMask |= RC_MASK_Z;
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'w':
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.WriteMask |= RC_MASK_W;
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			default:
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, "Unknown swizzle in writemask.\n");
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				return 0;
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	DBG("Dst Reg File=%u Index=%d Writemask=%d\n",
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->U.I.DstReg.File,
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->U.I.DstReg.Index,
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->U.I.DstReg.WriteMask);
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 1;
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define REGEX_INST_MATCHES 7
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct inst_tokens {
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Opcode;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Sat;
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Dst;
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct match_info Srcs[3];
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Initialize a normal instruction based on inst_str.
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WARNING: This function might not be able to handle every kind of format that
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * rc_program_print() can output.  If you are having problems with a
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * particular string, you may need to add support for it to this functions.
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @param inst_str A string that represents the source register.  The format for
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * this string is the same that is output by rc_program_print.
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @return 1 On success, 0 on failure
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint init_rc_normal_instruction(
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst,
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * inst_str)
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char * regex_str = "([[:upper:]]+)(_SAT)* ([^,]*)[, ]*([^,]*)[, ]*([^,]*)[, ]*([^;]*)";
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int i;
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	regmatch_t matches[REGEX_INST_MATCHES];
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct inst_tokens tokens;
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Initialize inst */
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(inst, 0, sizeof(struct rc_instruction));
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->Type = RC_INSTRUCTION_NORMAL;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Execute the regex */
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!regex_helper(regex_str, inst_str, matches, REGEX_INST_MATCHES)) {
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return 0;
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(&tokens, 0, sizeof(tokens));
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Create Tokens */
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Opcode.String = inst_str + matches[1].rm_so;
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	tokens.Opcode.Length = match_length(matches, 1);
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (matches[2].rm_so > -1) {
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tokens.Sat.String = inst_str + matches[2].rm_so;
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tokens.Sat.Length = match_length(matches, 2);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Fill out the rest of the instruction. */
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (i = 0; i < MAX_RC_OPCODE; i++) {
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * info = rc_get_opcode_info(i);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int first_src = 3;
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int j;
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (strncmp(tokens.Opcode.String, info->Name, tokens.Opcode.Length)) {
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst->U.I.Opcode = info->Opcode;
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (info->HasDstReg) {
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			char * dst_str;
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			tokens.Dst.String = inst_str + matches[3].rm_so;
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			tokens.Dst.Length = match_length(matches, 3);
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			first_src++;
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			dst_str = malloc(sizeof(char) * (tokens.Dst.Length + 1));
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			strncpy(dst_str, tokens.Dst.String, tokens.Dst.Length);
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			dst_str[tokens.Dst.Length] = '\0';
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			init_rc_normal_dst(inst, dst_str);
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			free(dst_str);
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (j = 0; j < info->NumSrcRegs; j++) {
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			char * src_str;
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			tokens.Srcs[j].String =
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst_str + matches[first_src + j].rm_so;
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			tokens.Srcs[j].Length =
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				match_length(matches, first_src + j);
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			src_str = malloc(sizeof(char) *
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						(tokens.Srcs[j].Length + 1));
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			strncpy(src_str, tokens.Srcs[j].String,
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						tokens.Srcs[j].Length);
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			src_str[tokens.Srcs[j].Length] = '\0';
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			init_rc_normal_src(inst, j, src_str);
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		break;
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 1;
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
381