1#ifndef N
2#error "N must be #defined"
3#endif
4
5#include "symcat.h"
6
7/* NOTE: see end of file for #undef of these macros */
8#define unsignedN    XCONCAT3(uint,N,_t)
9#define MAX_INT      XCONCAT2(MAX_INT,N)
10#define MIN_INT      XCONCAT2(MIN_INT,N)
11#define alu_N_tests     XCONCAT3(alu_,N,_tests)
12#define do_alu_N_tests  XCONCAT3(do_alu_,N,_tests)
13#define OP_BEGIN     XCONCAT3(ALU,N,_BEGIN)
14#define OP_ADDC      XCONCAT3(ALU,N,_ADDC)
15#define OP_ADDC_C    XCONCAT3(ALU,N,_ADDC_C)
16#define OP_SUBC      XCONCAT3(ALU,N,_SUBC)
17#define OP_SUBB      XCONCAT3(ALU,N,_SUBB)
18#define OP_SUBB_B    XCONCAT3(ALU,N,_SUBB_B)
19#define OP_SUBC_X    XCONCAT3(ALU,N,_SUBC_X)
20#define OP_NEGC      XCONCAT3(ALU,N,_NEGC)
21#define OP_NEGB      XCONCAT3(ALU,N,_NEGB)
22#define HAD_CARRY_BORROW    (XCONCAT3(ALU,N,_HAD_CARRY_BORROW) != 0)
23#define HAD_OVERFLOW (XCONCAT3(ALU,N,_HAD_OVERFLOW) != 0)
24#define RESULT          XCONCAT3(ALU,N,_RESULT)
25#define CARRY_BORROW_RESULT    XCONCAT3(ALU,N,_CARRY_BORROW_RESULT)
26#define OVERFLOW_RESULT XCONCAT3(ALU,N,_OVERFLOW_RESULT)
27#define do_op_N      XCONCAT2(do_op_,N)
28
29
30void
31do_op_N (const alu_test *tst)
32{
33  const alu_op *op;
34  int borrow_p = 0;
35  OP_BEGIN (tst->begin);
36  print_hex (tst->begin, N);
37  for (op = tst->ops; op->op != NULL; op++)
38    {
39      printf (" %s ", op->op);
40      print_hex (op->arg, N);
41      if (strcmp (op->op, "ADDC") == 0)
42	OP_ADDC (op->arg);
43      else if (strcmp (op->op, "ADDC_C0") == 0)
44	OP_ADDC_C (op->arg, 0);
45      else if (strcmp (op->op, "ADDC_C1") == 0)
46	OP_ADDC_C (op->arg, 1);
47      else if (strcmp (op->op, "SUBC") == 0)
48	OP_SUBC (op->arg);
49      else if (strcmp (op->op, "SUBC_X0") == 0)
50	OP_SUBC_X (op->arg, 0);
51      else if (strcmp (op->op, "SUBC_X1") == 0)
52	OP_SUBC_X (op->arg, 1);
53      else if (strcmp (op->op, "SUBB") == 0)
54	{
55	  OP_SUBB (op->arg);
56	  borrow_p ++;
57	}
58      else if (strcmp (op->op, "SUBB_B0") == 0)
59	{
60	  OP_SUBB_B (op->arg, 0);
61	  borrow_p ++;
62	}
63      else if (strcmp (op->op, "SUBB_B1") == 0)
64	{
65	  OP_SUBB_B (op->arg, 1);
66	  borrow_p ++;
67	}
68      else if (strcmp (op->op, "NEGC") == 0)
69	OP_NEGC ();
70      else if (strcmp (op->op, "NEGB") == 0)
71	{
72	  OP_NEGB ();
73	  borrow_p ++;
74	}
75      else
76	{
77	  printf (" -- operator unknown\n");
78	  abort ();
79	}
80    }
81  printf (" = ");
82  print_hex (tst->result, N);
83  if (borrow_p)
84    printf (" B:%d", tst->carry_borrow);
85  else
86    printf (" C:%d", tst->carry_borrow);
87  printf (" V:%d", tst->overflow);
88  if (tst->carry_borrow != HAD_CARRY_BORROW)
89    {
90      if (borrow_p)
91	printf (" -- borrow (%d) wrong", HAD_CARRY_BORROW);
92      else
93	printf (" -- carry (%d) wrong", HAD_CARRY_BORROW);
94      errors ++;
95    }
96  if (tst->overflow != HAD_OVERFLOW)
97    {
98      printf (" -- overflow (%d) wrong", HAD_OVERFLOW);
99      errors ++;
100    }
101  if ((unsignedN) CARRY_BORROW_RESULT != (unsignedN) tst->result)
102    {
103      printf (" -- result for carry/borrow wrong ");
104      print_hex (CARRY_BORROW_RESULT, N);
105      errors ++;
106    }
107  if ((unsignedN) OVERFLOW_RESULT != (unsignedN) tst->result)
108    {
109      printf (" -- result for overflow wrong ");
110      print_hex (OVERFLOW_RESULT, N);
111      errors ++;
112    }
113  if ((unsignedN) RESULT != (unsignedN) tst->result)
114    {
115      printf (" -- result wrong ");
116      print_hex (RESULT, N);
117      errors ++;
118    }
119  printf ("\n");
120}
121
122
123const alu_test alu_N_tests[] = {
124
125  /* 0 + 0; 0 + 1; 1 + 0; 1 + 1 */
126  { 0, { { "ADDC", 0 }, }, 0, 0, 0, },
127  { 0, { { "ADDC", 1 }, }, 1, 0, 0, },
128  { 1, { { "ADDC", 0 }, }, 1, 0, 0, },
129  { 1, { { "ADDC", 1 }, }, 2, 0, 0, },
130
131  /* 0 + 0 + 0; 0 + 0 + 1; 0 + 1 + 0; 0 + 1 + 1 */
132  /* 1 + 0 + 0; 1 + 0 + 1; 1 + 1 + 0; 1 + 1 + 1 */
133  { 0, { { "ADDC_C0", 0 }, }, 0, 0, 0, },
134  { 0, { { "ADDC_C0", 1 }, }, 1, 0, 0, },
135  { 0, { { "ADDC_C1", 0 }, }, 1, 0, 0, },
136  { 0, { { "ADDC_C1", 1 }, }, 2, 0, 0, },
137  { 1, { { "ADDC_C0", 0 }, }, 1, 0, 0, },
138  { 1, { { "ADDC_C0", 1 }, }, 2, 0, 0, },
139  { 1, { { "ADDC_C1", 0 }, }, 2, 0, 0, },
140  { 1, { { "ADDC_C1", 1 }, }, 3, 0, 0, },
141
142  /* */
143  { MAX_INT, { { "ADDC", 1 }, }, MIN_INT, 0, 1, },
144  { MIN_INT, { { "ADDC", -1 }, }, MAX_INT, 1, 1, },
145  { MAX_INT, { { "ADDC", MIN_INT }, }, -1, 0, 0, },
146  { MIN_INT, { { "ADDC", MAX_INT }, }, -1, 0, 0, },
147  { MAX_INT, { { "ADDC", MAX_INT }, }, MAX_INT << 1, 0, 1, },
148  { MIN_INT, { { "ADDC", MIN_INT }, }, 0, 1, 1, },
149  /* */
150  { 0, { { "ADDC_C1", -1 }, }, 0, 1, 0, },
151  { 0, { { "ADDC_C1", -2 }, }, -1, 0, 0, },
152  { -1, { { "ADDC_C1", 0 }, }, 0, 1, 0, },
153  { 0, { { "ADDC_C0", 0 }, }, 0, 0, 0, },
154  { -1, { { "ADDC_C1", -1 }, }, -1, 1, 0, },
155  { -1, { { "ADDC_C1", 1 }, }, 1, 1, 0, },
156  { 0, { { "ADDC_C1", MAX_INT }, }, MIN_INT, 0, 1, },
157  { MAX_INT, { { "ADDC_C1", 1 }, }, MIN_INT + 1, 0, 1, },
158  { MAX_INT, { { "ADDC_C1", MIN_INT }, }, 0, 1, 0, },
159  { MAX_INT, { { "ADDC_C1", MAX_INT }, }, (MAX_INT << 1) + 1, 0, 1, },
160  { MAX_INT, { { "ADDC_C0", MAX_INT }, }, MAX_INT << 1, 0, 1, },
161
162  /* 0 - 0 */
163  { 0, { { "SUBC",    0 }, },  0, 1, 0, },
164  { 0, { { "SUBB",    0 }, },  0, 0, 0, },
165
166  /* 0 - 1 */
167  { 0, { { "SUBC",    1 }, }, -1, 0, 0, },
168  { 0, { { "SUBB",    1 }, }, -1, 1, 0, },
169
170  /* 1 - 0 */
171  { 1, { { "SUBC",    0 }, },  1, 1, 0, },
172  { 1, { { "SUBB",    0 }, },  1, 0, 0, },
173
174  /* 1 - 1 */
175  { 1, { { "SUBC",    1 }, },  0, 1, 0, },
176  { 1, { { "SUBB",    1 }, },  0, 0, 0, },
177
178  /* 0 - 0 - 0 */
179  { 0, { { "SUBC_X0", 0 }, }, -1, 0, 0, },
180  { 0, { { "SUBB_B0", 0 }, },  0, 0, 0, },
181
182  /* 0 - 0 - 1 */
183  { 0, { { "SUBC_X0", 1 }, }, -2, 0, 0, },
184  { 0, { { "SUBB_B0", 1 }, }, -1, 1, 0, },
185
186  /* 0 - 1 - 0 */
187  { 0, { { "SUBC_X1", 0 }, },  0, 1, 0, },
188  { 0, { { "SUBB_B1", 0 }, }, -1, 1, 0, },
189
190  /* 0 - 1 - 1 */
191  { 0, { { "SUBC_X1", 1 }, }, -1, 0, 0, },
192  { 0, { { "SUBB_B1", 1 }, }, -2, 1, 0, },
193
194  /* 1 - 0 - 0 */
195  { 1, { { "SUBC_X0", 0 }, },  0, 1, 0, },
196  { 1, { { "SUBB_B0", 0 }, },  1, 0, 0, },
197
198  /* 1 - 0 - 1 */
199  { 1, { { "SUBC_X0", 1 }, }, -1, 0, 0, },
200  { 1, { { "SUBB_B0", 1 }, },  0, 0, 0, },
201
202  /* 1 - 1 - 0 */
203  { 1, { { "SUBC_X1", 0 }, },  1, 1, 0, },
204  { 1, { { "SUBB_B1", 0 }, },  0, 0, 0, },
205
206  /* 1 - 1 - 1 */
207  { 1, { { "SUBC_X1", 1 }, },  0, 1, 0, },
208  { 1, { { "SUBB_B1", 1 }, }, -1, 1, 0, },
209
210  /* */
211  { 0,       { { "SUBC", MIN_INT }, }, MIN_INT, 0, 1, },
212  { MIN_INT, { { "SUBC", 1 }, }, MAX_INT, 1, 1, },
213  { MAX_INT, { { "SUBC", MAX_INT }, }, 0, 1, 0, },
214
215  /* */
216  { 0,       { { "SUBC_X0", MIN_INT }, }, MAX_INT, 0, 0, },
217  { MIN_INT, { { "SUBC_X1",       0 }, }, MIN_INT, 1, 0, },
218  { MAX_INT, { { "SUBC_X0", MAX_INT }, },      -1, 0, 0, },
219
220  /* */
221  { MAX_INT, { { "NEGC", 0 }, }, MIN_INT + 1, 0, 0, },
222  { MAX_INT, { { "NEGC", 0 }, }, MIN_INT + 1, 0, 0, },
223  { MIN_INT, { { "NEGC", 0 }, }, MIN_INT, 0, 1, },
224  { 0, { { "NEGC", 0 }, }, 0, 1, 0, },
225  { -1, { { "NEGC", 0 }, }, 1, 0, 0, },
226  { 1, { { "NEGC", 0 }, }, -1, 0, 0, },
227};
228
229
230static void
231do_alu_N_tests (void)
232{
233  int i;
234  for (i = 0; i < sizeof (alu_N_tests) / sizeof (*alu_N_tests); i++)
235    {
236      const alu_test *tst = &alu_N_tests[i];
237      do_op_N (tst);
238    }
239}
240
241
242#undef OP_BEGIN
243#undef OP_ADDC
244#undef OP_ADDC_C
245#undef OP_SUBB
246#undef OP_SUBC
247#undef OP_SUBC_X
248#undef OP_SUBB_B
249#undef HAD_OVERFLOW
250#undef HAD_CARRY_BORROW
251#undef OVERFLOW_RESULT
252#undef CARRY_BORROW_RESULT
253#undef RESULT
254#undef do_op_N
255#undef unsignedN
256#undef MAX_INT
257#undef MIN_INT
258#undef alu_N_tests
259#undef do_alu_N_tests
260
261