summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2010-07-21 17:08:30 -0400
committerJerome Glisse <jglisse@redhat.com>2010-07-21 17:08:30 -0400
commit85b17273a0be1c27c83166cd14b12db2d114c31d (patch)
treee8db54cd329a548e2adbb48ac9c17bf03ff94931
parentac123b7ed1f7331e76f9a152aa564428fc20ea4a (diff)
radeondb: add define generation to rdb tools
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
-rw-r--r--tools/rdb.c155
1 files changed, 154 insertions, 1 deletions
diff --git a/tools/rdb.c b/tools/rdb.c
index 37bb45f..1206797 100644
--- a/tools/rdb.c
+++ b/tools/rdb.c
@@ -29,8 +29,151 @@
#include <errno.h>
#include <getopt.h>
#include <jansson.h>
+#include <regex.h>
#include "rdb_json.h"
+struct read {
+ struct rdb_json *rdb;
+ regex_t name;
+};
+
+void regex_get(int n, regmatch_t *match, const char *line, char *out)
+{
+ if (match[n].rm_so == -1) {
+ out[0] = 0;
+ return;
+ }
+ for (int i = 0; i < (match[n].rm_eo - match[n].rm_so); i++) {
+ out[i] = line[match[n].rm_so + i];
+ out[i+1] = 0;
+ }
+}
+
+static void space_align(unsigned n, unsigned lenght)
+{
+ unsigned i;
+
+ if (lenght > n) {
+ n = 1;
+ } else {
+ n = n - lenght;
+ }
+ for (i = 0; i < n; i++)
+ printf(" ");
+}
+
+static void define_print_reg(json_t *reg, unsigned offset)
+{
+ json_t *tmp, *fields, *field;
+ unsigned i, bf, bl, bits, j;
+
+ tmp = json_object_get(reg, "name");
+ printf("#define R_%06X_%s", offset, json_string_value(tmp));
+ space_align(54, strlen(json_string_value(tmp)) + 18);
+ printf("0x%08X\n", offset);
+ fields = json_object_get(reg, "field");
+ for (i = 0; i < json_array_size(fields); i++) {
+ field = json_array_get(fields, i);
+ tmp = json_object_get(field, "bf");
+ bf = json_integer_value(tmp);
+ tmp = json_object_get(field, "bl");
+ bl = json_integer_value(tmp);
+ for (j = 0, bits = 0; j < (bl - bf + 1); j++) {
+ bits |= 1 << j;
+ }
+ tmp = json_object_get(field, "name");
+ printf("#define S_%06X_%s(x)", offset, json_string_value(tmp));
+ space_align(56, strlen(json_string_value(tmp)) + 23);
+ printf("(((x) & 0x%X) << %d)\n", bits, bf);
+ printf("#define G_%06X_%s(x)", offset, json_string_value(tmp));
+ space_align(56, strlen(json_string_value(tmp)) + 23);
+ printf("(((x) >> %d) & 0x%X)\n", bf, bits);
+ printf("#define C_%06X_%s(x)", offset, json_string_value(tmp));
+ space_align(56, strlen(json_string_value(tmp)) + 23);
+ printf("0x%08X\n", 0xFFFFFFFF & ~(bits << bf));
+ }
+}
+
+static int process_line(void *user_data, const char *line)
+{
+ struct read *hr = (struct read *)user_data;
+ json_t *block, *reg, *tmp;
+ regmatch_t match[3];
+ char name[128];
+ int r, i;
+ void *iter;
+
+ r = regexec(&hr->name, line, 2, match, 0);
+ switch (r) {
+ case REG_NOMATCH:
+ break;
+ case 0:
+ regex_get(1, match, line, name);
+ for (i = 0; i < json_array_size(hr->rdb->block); i++) {
+ block = json_array_get(hr->rdb->block, i);
+ iter = json_object_iter(block);
+ while (iter) {
+ unsigned offset;
+ reg = json_object_iter_value(iter);
+ if (json_is_object(reg)) {
+ offset = strtoul(json_object_iter_key(iter), NULL, 16);
+ tmp = json_object_get(reg, "name");
+ if (!strcmp(json_string_value(tmp), name)) {
+ define_print_reg(reg, offset);
+ }
+ }
+ iter = json_object_iter_next(block, iter);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "Error matching regular expression %d\n", r);
+ return r;
+ }
+ return 0;
+}
+
+typedef int (*process_line_t)(void *user_data, const char *line);
+static int read_file(const char *filename, void *user_data, process_line_t pline)
+{
+ FILE *file;
+ size_t end;
+ char line[512];
+ int r;
+
+ file = fopen(filename, "r");
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open: %s\n", filename);
+ return 0;
+ }
+ fseek(file, 0, SEEK_END);
+ end = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ while (ftell(file) != end) {
+ if (fgets(line, 512, file) == NULL)
+ return -1;
+ if (strlen(line)) {
+ r = pline(user_data, line);
+ if (r)
+ return r;
+ }
+ }
+ fclose(file);
+ return 0;
+}
+
+static int list_read(const char *filename, struct rdb_json *rdb)
+{
+ struct read hr;
+
+ hr.rdb = rdb;
+ if (regcomp(&hr.name, "^([_A-Z0-9]*)", REG_EXTENDED)) {
+ fprintf(stderr, "Failed to compile regular expression\n");
+ return -1;
+ }
+ return read_file(filename, &hr, &process_line);
+}
+
void usage(void)
{
printf("usage: rdb [arguments] [file ..]\n\n");
@@ -63,9 +206,11 @@ static unsigned blockflag(struct rdb_json *rdb, json_t *reg)
struct param {
int list;
int header;
+ int define;
char *file;
char *list_str;
char *header_name;
+ char *define_name;
};
int main(int argc, char *argv[])
@@ -74,6 +219,7 @@ int main(int argc, char *argv[])
{"json", required_argument, 0, 'j'},
{"list", required_argument, 0, 'l'},
{"header", required_argument, 0, 'h'},
+ {"define", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
struct param param;
@@ -86,7 +232,7 @@ int main(int argc, char *argv[])
memset(&param, 0, sizeof(struct param));
while (1) {
- c = getopt_long(argc, argv, "l:j:h:", options, &option_id);
+ c = getopt_long(argc, argv, "l:j:h:d:", options, &option_id);
if (c == -1)
break;
switch (c) {
@@ -101,6 +247,10 @@ int main(int argc, char *argv[])
param.header = 1;
param.header_name = strdup(optarg);
break;
+ case 'd':
+ param.define = 1;
+ param.define_name = strdup(optarg);
+ break;
case '?':
/* getopt_long already printed an error message. */
break;
@@ -133,6 +283,9 @@ int main(int argc, char *argv[])
}
return 0;
}
+ if (param.define) {
+ list_read(param.define_name, rdb);
+ }
if (param.header_name) {
printf("/* this file is autogenerated don't edit */\n");
printf("#include \"radeon_reg.h\"\n\n");