1/*
2Copyright 2020 Free Software Foundation, Inc.
3
4This file is part of the GNU MP Library test suite.
5
6The GNU MP Library test suite is free software; you can redistribute it
7and/or modify it under the terms of the GNU General Public License as
8published by the Free Software Foundation; either version 3 of the License,
9or (at your option) any later version.
10
11The GNU MP Library test suite is distributed in the hope that it will be
12useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
14Public License for more details.
15
16You should have received a copy of the GNU General Public License along with
17the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
18
19#include <stdlib.h>
20#include <string.h>
21#include <stdio.h>
22
23typedef unsigned long mp_limb_t; /* neat */
24
25void
26one (const char *op, size_t ind, mp_limb_t m0, mp_limb_t s0)
27{
28  printf ("static void f%zu(mp_limb_t*r1p,mp_limb_t*r0p){", ind);
29  printf ("mp_limb_t r1,r0;");
30  printf ("%s(r1,r0,0,%ld,0,%ld);", op, (long) m0, (long) s0);
31  printf ("*r1p=r1;*r0p=r0;");
32  printf ("}\n");
33}
34
35mp_limb_t ops[1000];
36
37enum what_t {ADD, SUB};
38
39int
40main (int argc, char **argv)
41{
42  size_t n_operands = 0;
43  size_t n_functions = 0;
44  const char *op;
45  enum what_t what;
46
47  if (argc == 2 && strcmp (argv[1], "add") == 0)
48    {
49      op = "add_ssaaaa";
50      what = ADD;
51    }
52  else if (argc == 2 && strcmp (argv[1], "sub") == 0)
53    {
54      op = "sub_ddmmss";
55      what = SUB;
56    }
57  else
58    {
59      fprintf (stderr, "what do yuo want me to do?\n");
60      exit (1);
61    }
62
63  for (int i = 0; i < 16; i++)
64    {
65      ops[n_operands++] = 1 << i;
66      ops[n_operands++] = -(1 << i);
67      ops[n_operands++] = (1 << i) - 1;
68      ops[n_operands++] = -(1 << i) - 1;
69    }
70
71  printf ("#include <stdlib.h>\n");
72  printf ("#include <stdio.h>\n");
73  printf ("#include \"gmp-impl.h\"\n");
74  printf ("#include \"longlong.h\"\n");
75
76  /* Print out ops[] definition.  */
77  printf ("static const int ops[%zu] = {\n", n_operands);
78  for (int i = 0; i < n_operands; i++)
79    {
80      printf ("%ld,", (long) ops[i]);
81      if ((i + 1) % 4 == 0)
82	puts ("");
83    }
84  printf ("};\n");
85
86  /* Generate functions and print them.  */
87  for (int i = 0; i < n_operands; i++)
88    {
89      for (int j = 0; j < n_operands; j++)
90	{
91	  one (op, n_functions++, ops[i], ops[j]);
92	}
93    }
94
95  /* Print out function pointer table.  */
96  printf ("typedef void (*func_t) (mp_limb_t*, mp_limb_t*);\n");
97  printf ("static const func_t funcs[%zu] = {\n", n_functions);
98  for (size_t i = 0; i < n_functions; i++)
99    {
100      printf ("f%zu,", i);
101      if ((i + 1) % 16 == 0)
102	puts ("");
103    }
104  printf ("};\n");
105
106  /* Print out table of reference results.  */
107  printf ("static const int ref[%zu][2] = {\n", n_functions);
108  for (int i = 0; i < n_operands; i++)
109    {
110      for (int j = 0; j < n_operands; j++)
111	{
112	  if (what == ADD)
113	    printf ("{%6ld,%2ld},", (long) ( ops[i] + ops[j]), (long) ((mp_limb_t) ((ops[i] + ops[j]) < ops[i])));
114	  else     /* SUB */
115	    printf ("{%6ld,%2ld},", (long) ( ops[i] - ops[j]), (long) (-(mp_limb_t) (ops[i] < ops[j])));
116	  if ((i * n_operands + j) % 8 == 0)
117	    puts ("");
118	}
119    }
120  printf ("};\n");
121
122  printf ("int main ()\n{\n");
123  printf ("  mp_limb_t r1, r0;\n");
124  printf ("  int err = 0;\n");
125  printf ("  size_t ind = 0;\n");
126  printf ("  for (size_t i = 0; i < %zu; i++)\n", n_functions);
127  printf ("    {\n");
128  printf ("      int ii = i / %zu, jj = i %% %zu;\n", n_operands, n_operands);
129  printf ("      funcs[i](&r1, &r0);\n");
130  printf ("      if (r0 != (mp_limb_signed_t) ref[ind][0] || r1 != (mp_limb_signed_t) ref[ind][1]) {\n");
131  printf ("         printf (\"error for f%%zu(%%d,%%d): want (%%d,%%d) got (%%d,%%d)\\n\", i, (int) ops[ii], (int) ops[jj], ref[ind][1], ref[ind][0], (int) r1, (int) r0);\n");
132  printf ("         err++;\n");
133  printf ("       }\n");
134  printf ("      ind++;\n");
135  printf ("    }\n");
136
137  printf ("  return err != 0;\n");
138  printf ("}\n");
139  return 0;
140}
141