All of lore.kernel.org
 help / color / mirror / Atom feed
From: "J. Mayer" <l_indien@magic.fr>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [ADD] PPC processor emulation
Date: 18 Nov 2003 08:48:55 +0100	[thread overview]
Message-ID: <1069141734.14646.2222.camel@rapid> (raw)
In-Reply-To: <1069140512.14646.2174.camel@rapid>

gen_multi.c.diff

New utility to generate repetitive micro-ops

diff -urNbB -x CVS qemu-current/gen_multi.c qemu/gen_multi.c
--- qemu-current/gen_multi.c	Thu Jan  1 01:00:00 1970
+++ qemu/gen_multi.c	Sun Aug 17 13:36:23 2003
@@ -0,0 +1,519 @@
+/*
+ * Minimalist preprocessor.
+ * Recognized token:
+ * $DEF regname number
+ * $OP name rega0 rega1 regb0
+ * ...
+ * $ENDOP
+ *
+ * example:
+ * $DEF gpr 32
+ * $DEF T   3
+ * $OP load_gpr gpr0 T0
+ * {
+ *     ....
+ * }
+ * $ENDOP
+ * $OP add T0 T1
+ * {
+ *     ....
+ * }
+ * $ENDOP
+ * $OP op3 T0 T1 T2
+ * {
+ *     ....
+ * }
+ * $ENDOP
+ *
+ * The '$' MUST be at start of the line.
+ *
+ * The preprocessor will generate:
+ * - n micro-routines
+ * - 1 routine to select the right micro helper at run-time.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+const unsigned char *prologue_str =
+"/* This file has been auto-generated - PLEASE DON'T EDIT BY HAND */\n\n";
+
+typedef struct reg_t {
+    char *name;
+    int nr;
+} reg_t;
+
+static int regtypes_nr;
+static reg_t regtypes[16], *host_reg; /* Should be sufficient... */
+static FILE *fuops = NULL, *fc = NULL;
+static int verbose, limit, host_max;
+
+static int outbuf (FILE *file,
+                   const unsigned char *start,
+                   const unsigned char *end)
+{
+    int out;
+
+    for (out = 0; out == 0;) {
+        out = fwrite(start, end - start, 1, file);
+        if (out == 0) {
+            if (errno != EINTR && errno != ERESTART) {
+                fprintf(stderr, "Unable to copy function out\n");
+                return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int recurs_out_uop (const unsigned char *name,
+                           const unsigned char *start,
+                           const unsigned char *end,
+                           int nr, int *regnums, const int *regmax,
+                           unsigned char *const *regs)
+{
+    int hostregs[16] = { 0, };
+    int i, j, tmphost = 0, tmpemu = 0, tmpparm = 0;
+    
+    /* Generate function prototype */
+    if (fuops != NULL) {
+        /* Define registers */
+        for (i = 0; i < nr; i++) {
+            if (strcmp(regs[i], host_reg->name) == 0) {
+                fprintf(fuops, "#define %s%c %s%d\n",
+                        regs[i], 'a' + tmphost, regs[i], regnums[i]);
+                hostregs[regnums[i]] = 1;
+                tmphost++;
+            } else if (strcmp(regs[i], "PARAM") == 0) {
+                tmpparm++;
+            } else {
+                fprintf(fuops, "#define %s%c %s[%d]\n",
+                        regs[i], 'a' + tmpemu, regs[i], regnums[i]);
+                tmpemu++;
+            }
+        }
+        j = 0;
+        fprintf(fuops, "volatile void op_%s", name);
+    }
+    if (fc != NULL && nr > tmpparm)
+        fprintf(fc, "    &gen_op_%s", name);
+    for (i = 0; i < nr; i++) {
+        if (strcmp(regs[i], "PARAM") == 0)
+            continue;
+        if (fuops != NULL)
+            fprintf(fuops, "_%s%d", regs[i], regnums[i]);
+        if (fc != NULL)
+            fprintf(fc, "_%s%d", regs[i], regnums[i]);
+    }
+    if (fuops != NULL)
+        fprintf(fuops, " (void)\n");
+    if (fc != NULL && nr > tmpparm)
+        fprintf(fc, ",\n");
+    if (fuops != NULL) {
+        /* Copy function core */
+        if (outbuf(fuops, start, end) < 0)
+            return -1;
+        /* Undef registers */
+        tmphost = tmpemu = 0;
+        for (i = 0; i < nr; i++) {
+            if (strcmp(regs[i], host_reg->name) == 0) {
+                fprintf(fuops, "#undef %s%c\n", regs[i], 'a' + tmphost++);
+            } else if (strcmp(regs[i], "PARAM") == 0) {
+                continue;
+            } else {
+                fprintf(fuops, "#undef %s%c\n", regs[i], 'a' + tmpemu++);
+            }
+        }
+        /* Separate functions */
+        fprintf(fuops, "\n");
+    }
+
+    return 0;
+}
+
+static int _recurs_out_uop (const unsigned char *name,
+                            const unsigned char *start,
+                            const unsigned char *end,
+                            int nr, int *regnums, const int *regmax,
+                            unsigned char *const *regs, int level)
+{
+    int i;
+
+    if (level >= 0) {
+        if (strcmp(regs[level], "PARAM") == 0) {
+            if (_recurs_out_uop(name, start, end, nr, regnums, regmax,
+                                regs, level - 1) < 0)
+                return -1;
+        } else if (strcmp(regs[level], host_reg->name) == 0) {
+            for (i = 0; i < regmax[level]; i++) {
+                regnums[level] = i;
+                if (_recurs_out_uop(name, start, end, nr, regnums, regmax,
+                                    regs, level - 1) < 0)
+                    return -1;
+            }
+#if 0
+            for (; i < regmax[level]; i++) {
+                if (fc != NULL && nr > 0)
+                    fprintf(fc, "    NULL,\n");
+            }
+#endif
+        } else {
+            for (i = 0; i < regmax[level]; i++) {
+                regnums[level] = i;
+                if (_recurs_out_uop(name, start, end, nr, regnums, regmax,
+                                    regs, level - 1) < 0)
+                    return -1;
+            }
+        }
+    } else {
+        if (recurs_out_uop(name, start, end, nr,
+                           regnums, regmax, regs) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+static void usage (const unsigned char *progname,
+                   const unsigned char *message)
+{
+    fprintf(stderr, "Usage: %s -o uops_file -s -h h_file in_file\n",
+            progname);
+    fprintf(stderr, "Generate C-code...\n");
+    fprintf(stderr, "\tuops_file: C-code: micro-operations routines\n");
+    fprintf(stderr, "\th_file   : C-code; run-time selector for uops\n");
+    if (message != NULL)
+        fprintf(stderr, message);
+}
+
+int main (int argc, char **argv)
+{
+    unsigned char *function, *regs[32];
+    int regnums[16], regmax[16];
+    struct stat st;
+    const unsigned char *message;
+    unsigned char *map, *start, *end;
+    unsigned char *name_start, *name_end, *tmp_end;
+    int fd_in = -1;
+    int nr_regs, nr_tmp;
+    int tmp, mul;
+    int i, j;
+    int c;
+
+    while ((c = getopt(argc, argv, "o:s:lvh?")) != -1) {
+        switch (c) {
+        case 'o':
+            if (fuops != NULL) {
+                message = "Can output only one uops file at once\n";
+                goto out_error;
+            }
+            fuops = fopen(argv[optind - 1], "w");
+            if (fuops == NULL) {
+                message = "Can't open fuops file\n";
+                goto out_error;
+            }
+            break;
+        case 's':
+            if (fc != NULL) {
+                message = "Can output only one C file at once\n";
+                goto out_error;
+            }
+            fc = fopen(argv[optind - 1], "w");
+            if (fc == NULL) {
+                message = "Can't open C file\n";
+                goto out_error;
+            }
+            break;
+        case 'v':
+            verbose++;
+            break;
+        case 'l':
+            limit++;
+            break;
+        case 'h':
+        case '?':
+            usage(argv[0], NULL);
+            exit(0);
+            break;
+        default:
+            message = "Unknown option\n";
+            goto out_error;
+        }
+    }
+    if (fuops == NULL && fc == NULL) {
+        message = "Must have at least one output file\n";
+        goto out_error;
+    }
+    if (optind != (argc - 1)) {
+        message = "Bad number of arguments\n";
+        goto out_error;
+    }
+    fd_in = open(argv[optind], O_RDONLY);
+    if (fd_in < 0) {
+        message = "Error oppening in file\n";
+        goto out_error;
+    }
+    if (fstat(fd_in, &st) < 0) {
+        message = "Error getting in file infos\n";
+        goto out_error;
+    }
+    map = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+               fd_in, 0);
+    if (map == NULL) {
+        message = "Can't map in_file\n";
+        goto out_error;
+    }
+
+    /* Get variables definitions */
+    end = map;
+    for (regtypes_nr = 0; regtypes_nr < 16;) {
+        start = strstr(end, "$DEF");
+        if (start == NULL)
+            break;
+        if (start == map || *(start - 1) == '\n') {
+            end = strchr(start, '\n');
+            if (end == NULL)
+                end = start + st.st_size;
+            start += 4;
+            if (*start == 'H') {
+                if (host_reg != NULL) {
+                    message = "host regs cannot be defined more than once";
+                    goto out_error;
+                }
+                host_reg = &regtypes[regtypes_nr];
+                start++;
+            }
+            if (!isspace(*start++)) {
+                message = "invalid $DEF token\n";
+                goto out_error;
+            }
+            for (name_start = start; isspace(*name_start); name_start++)
+                continue;
+            if (name_start == end) {
+                message = "no $DEF name\n";
+                goto out_error;
+            }
+            for (name_end = name_start;
+                 !isspace(*name_end) && name_end < end; name_end++)
+                continue;
+            tmp = strtol(name_end + 1, NULL, 0);
+            if (tmp == 0) {
+                message = "invalid number of registers\n";
+                goto out_error;
+            }
+            regtypes[regtypes_nr].nr = tmp;
+            tmp = name_end - name_start;
+            regtypes[regtypes_nr].name = malloc(tmp + 1);
+            if (regtypes[regtypes_nr].name == NULL) {
+                message = "memory error\n";
+                goto out_error;
+            }
+            memcpy(regtypes[regtypes_nr].name, name_start, tmp);
+            regtypes[regtypes_nr].name[tmp] = '\0';
+            if (verbose > 0) {
+                printf("Registered %d vars of type: %s\n",
+                       regtypes[regtypes_nr].nr, regtypes[regtypes_nr].name);
+            }
+            regtypes_nr++;
+        } else {
+            end = start + 4;
+        }
+    }
+
+    if (host_reg == NULL) {
+        message = "No host registers defined !\n";
+        goto out_error;
+    }
+
+    tmp = strlen(prologue_str);
+    if (fuops != NULL) {
+        fwrite(prologue_str, tmp, 1, fuops);
+    }
+
+    if (fc != NULL)
+        fwrite(prologue_str, tmp, 1, fc);
+    /* Proceed micro-operations */
+    while (1) {
+        host_max = 0;
+        start = strstr(end, "$OP");
+        if (start == NULL)
+            break;
+        if (outbuf(fuops, end, start) < 0)
+            return -1;
+        if (start == map || *(start - 1) == '\n') {
+            tmp_end = strchr(start, '\n');
+            if (tmp_end == NULL)
+                tmp_end = start + st.st_size;
+            start += 3;
+            if (!isspace(*start++)) {
+                message = "invalid $OP token\n";
+                goto out_error;
+            }
+            for (name_start = start; isspace(*name_start); name_start++)
+                continue;
+            if (name_start == tmp_end) {
+                message = "no $OP name\n";
+                goto out_error;
+            }
+            for (name_end = name_start;
+                 !isspace(*name_end) && name_end < tmp_end; name_end++)
+                continue;
+            tmp = name_end - name_start;
+            function = malloc(tmp + 1);
+            if (function == NULL) {
+                message = "memory error\n";
+                goto out_error;
+            }
+            memcpy(function, name_start, tmp);
+            function[tmp] = '\0';
+            for (nr_regs = 0;
+                 name_end != tmp_end && nr_regs < 32;) {
+                for (name_start = name_end + 1;
+                     isspace(*name_start); name_start++)
+                    continue;
+                if (name_start == tmp_end)
+                    break;
+                for (name_end = name_start;
+                     !isspace(*name_end) && name_end < tmp_end; name_end++)
+                    continue;
+                tmp = name_end - name_start;
+                regs[nr_regs] = malloc(tmp + 1);
+                if (regs[nr_regs] == NULL) {
+                    message = "memory error\n";
+                    goto out_error;
+                }
+                memcpy(regs[nr_regs], name_start, tmp);
+                (regs[nr_regs++])[tmp] = '\0';
+            }
+            end = strstr(tmp_end, "$ENDOP");
+            if (end == NULL) {
+                message = "operation with no end\n";
+                goto out_error;
+            }
+            if (verbose > 0)
+                printf("Generate function: %s\n", function);
+
+            nr_tmp = 0;
+            for (i = 0; i < nr_regs; i++) {
+                for (j = 0; j < regtypes_nr; j++) {
+                    if (strcmp(regs[i], regtypes[j].name) == 0) {
+                        if (verbose > 0) {
+                            printf("\tregister of type: %s (%s - %d)\n",
+                                   regs[i], regtypes[j].name, regtypes[j].nr);
+                        }
+                        regmax[i] = regtypes[j].nr;
+                        goto got_it;
+                    }
+                    if (strcmp(regs[i], "PARAM") == 0) {
+                        nr_tmp++;
+                        goto got_it;
+                    }
+                }
+                printf("register %s not found\n", regs[i]);
+                message = "register not found\n";
+                goto out_error;
+            got_it:
+                continue;
+            }
+            
+            if (nr_regs > nr_tmp) {
+                if (fc != NULL)
+                    fprintf(fc, "static void *table_%s[] = {\n", function);
+                memset(regnums, 0, sizeof(regnums));
+            }
+            if (_recurs_out_uop(function, tmp_end + 1, end, nr_regs,
+                                regnums, regmax, regs, nr_regs - 1) < 0) {
+                message = "code generation error\n";
+                goto out_error;
+            }
+            if (nr_regs > nr_tmp) {
+                if (fc != NULL) {
+                    fprintf(fc, "};\n\n");
+                    fprintf(fc, "static inline void gen_op_%s (", function);
+                }
+            }
+            if (nr_regs == nr_tmp)
+                goto do_free;
+
+            if (fc != NULL) {
+                int tmp = 0;
+                for (i = 0; i < nr_tmp; i++) {
+                    if (i > 0)
+                        fprintf(fc, ", ");
+                    fprintf(fc, "unsigned long parm%d", i);
+                }
+                for (i = 0; i < nr_regs; i++) {
+                    if (strcmp(regs[i], "PARAM") == 0)
+                        continue;
+                    if (tmp++ > 0 || nr_tmp > 0)
+                        fprintf(fc, ", ");
+                    if (fc != NULL)
+                        fprintf(fc, "int regn%d", i);
+                }
+                fprintf(fc, ")\n");
+                fprintf(fc, "{\n");
+                fprintf(fc, "    void (*gen_op)(");
+                for (i = 0; i < nr_tmp; i++) {
+                    if (i > 0)
+                        fprintf(fc, ", ");
+                    fprintf(fc, "unsigned long p%d", i);
+                }
+                fprintf(fc, ");\n\n");
+                fprintf(fc, "    gen_op = table_%s[", function);
+                fprintf(fc, "regn0");
+                mul = 1;
+                for (i = 1; i < nr_regs; i++) {
+                    if (strcmp(regs[i], "PARAM") == 0)
+                        continue;
+                    mul *= regmax[i - 1];
+                    fprintf(fc, " + (regn%d * %d)", i, mul);
+                }
+                fprintf(fc, "];\n");
+                fprintf(fc, "    (*gen_op)(");
+                for (i = 0; i < nr_tmp; i++) {
+                    if (i > 0)
+                        fprintf(fc, ", ");
+                    fprintf(fc, "parm%d", i);
+                }
+                fprintf(fc, ");\n");
+                fprintf(fc, "}\n\n");
+            }
+        do_free:
+            free(function);
+            for (; nr_regs > 0; nr_regs--)
+                free(regs[nr_regs - 1]);
+            end = strchr(end, '\n');
+            if (end == NULL)
+                break;
+        } else {
+            end = start + 3;
+        }
+    }
+
+    if (fuops != NULL)
+        fclose(fuops);
+    if (fc != NULL)
+        fclose(fc);
+    close(fd_in);
+
+    exit(0);
+
+out_error:
+    if (fuops != NULL)
+        fclose(fuops);
+    if (fc != NULL)
+        fclose(fc);
+    if (fd_in >= 0)
+        close(fd_in);
+    usage(argv[0], message);
+
+    exit(1);
+}

  parent reply	other threads:[~2003-11-18  8:46 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-11-17  9:51 [Qemu-devel] new knoppix SegFault Jens Arm
2003-11-18  7:15 ` [Qemu-devel] [PATCH] Fixes for qemu J. Mayer
2003-11-18  7:30   ` J. Mayer
2003-11-18  7:31   ` Chad Page
2003-11-18  7:32   ` J. Mayer
2003-11-18  7:33   ` J. Mayer
2003-11-18  7:34   ` J. Mayer
2003-11-18  8:24   ` J. Mayer
2003-11-18  7:22 ` [Qemu-devel] [ADD] floppy disk emulation J. Mayer
2003-11-18  7:37   ` J. Mayer
2003-11-18  7:38   ` J. Mayer
2003-11-18  7:39   ` J. Mayer
2003-11-18  7:39   ` J. Mayer
2003-11-18  8:24   ` J. Mayer
2003-11-18  7:28 ` [Qemu-devel] [ADD] PPC processor emulation J. Mayer
2003-11-18  7:43   ` J. Mayer
2003-11-18  7:43   ` J. Mayer
2003-11-18  7:44   ` J. Mayer
2003-11-18  7:45   ` J. Mayer
2003-11-18  7:45   ` J. Mayer
2003-11-18  7:46   ` J. Mayer
2003-11-18  7:46   ` J. Mayer
2003-11-18  7:48   ` J. Mayer
2003-11-18  7:48   ` J. Mayer [this message]
2003-11-18  7:49   ` J. Mayer
2003-11-18  7:50   ` J. Mayer
2003-11-18  7:50   ` J. Mayer
2003-11-18  7:51   ` J. Mayer
2003-11-18  7:53   ` J. Mayer
2003-11-18  7:54   ` J. Mayer
2003-11-18  7:55   ` J. Mayer
2003-11-18  7:56   ` J. Mayer
2003-11-18  7:56   ` J. Mayer
2003-11-18  7:57   ` J. Mayer
2003-11-18  7:58   ` J. Mayer
2003-11-18  7:59   ` J. Mayer
2003-11-18  7:59   ` J. Mayer
2003-11-18  8:00   ` J. Mayer
2003-11-18  8:02   ` [Qemu-devel] [ADD] tests for PPC target J. Mayer
2003-11-18  8:06     ` J. Mayer
2003-11-18  8:08     ` J. Mayer
2003-11-18  8:08     ` J. Mayer
2003-11-18  8:09     ` J. Mayer
2003-11-18  8:10     ` J. Mayer
2003-11-18  8:25     ` J. Mayer
2003-11-18  8:24   ` [Qemu-devel] [ADD] PPC processor emulation J. Mayer
2003-11-18  9:37   ` Gwenole Beauchesne
2003-11-18 10:37     ` J. Mayer
2003-11-18 11:39       ` Raymond W. Lucke IV
2003-11-18 12:13         ` J. Mayer
2003-11-18 20:24           ` Raymond W. Lucke IV
2003-11-18 20:44             ` Jocelyn Mayer
2003-11-18 21:48               ` Chad Page
2003-11-18 22:50                 ` J. Mayer
2003-11-19  1:11                   ` Benjamin Herrenschmidt
2003-11-19 15:35                     ` Jocelyn Mayer
2003-11-18 12:24       ` Gwenole Beauchesne
2003-11-18 12:57         ` Johan Rydberg
2003-11-18 14:52           ` Gwenole Beauchesne
2003-11-18 14:59         ` Jocelyn Mayer
2003-11-18  7:29 ` [Qemu-devel] [PATCH] Term prompt for qemu J. Mayer
2003-11-18  8:11   ` J. Mayer
2003-11-18  8:11   ` J. Mayer
2003-11-18  8:13   ` J. Mayer
2003-11-18  8:25   ` J. Mayer
  -- strict thread matches above, loose matches on Subject: below --
2003-11-18 22:28 [Qemu-devel] [ADD] PPC processor emulation J. Mayer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1069141734.14646.2222.camel@rapid \
    --to=l_indien@magic.fr \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.