| #ifndef N |
| #error "N must be #defined" |
| #endif |
| |
| #include "symcat.h" |
| |
| /* NOTE: see end of file for #undef of these macros */ |
| #define unsignedN XCONCAT3(uint,N,_t) |
| #define MAX_INT XCONCAT2(MAX_INT,N) |
| #define MIN_INT XCONCAT2(MIN_INT,N) |
| #define alu_N_tests XCONCAT3(alu_,N,_tests) |
| #define do_alu_N_tests XCONCAT3(do_alu_,N,_tests) |
| #define OP_BEGIN XCONCAT3(ALU,N,_BEGIN) |
| #define OP_ADDC XCONCAT3(ALU,N,_ADDC) |
| #define OP_ADDC_C XCONCAT3(ALU,N,_ADDC_C) |
| #define OP_SUBC XCONCAT3(ALU,N,_SUBC) |
| #define OP_SUBB XCONCAT3(ALU,N,_SUBB) |
| #define OP_SUBB_B XCONCAT3(ALU,N,_SUBB_B) |
| #define OP_SUBC_X XCONCAT3(ALU,N,_SUBC_X) |
| #define OP_NEGC XCONCAT3(ALU,N,_NEGC) |
| #define OP_NEGB XCONCAT3(ALU,N,_NEGB) |
| #define HAD_CARRY_BORROW (XCONCAT3(ALU,N,_HAD_CARRY_BORROW) != 0) |
| #define HAD_OVERFLOW (XCONCAT3(ALU,N,_HAD_OVERFLOW) != 0) |
| #define RESULT XCONCAT3(ALU,N,_RESULT) |
| #define CARRY_BORROW_RESULT XCONCAT3(ALU,N,_CARRY_BORROW_RESULT) |
| #define OVERFLOW_RESULT XCONCAT3(ALU,N,_OVERFLOW_RESULT) |
| #define do_op_N XCONCAT2(do_op_,N) |
| |
| |
| static void |
| do_op_N (const alu_test *tst) |
| { |
| const alu_op *op; |
| int borrow_p = 0; |
| OP_BEGIN (tst->begin); |
| print_hex (tst->begin, N); |
| for (op = tst->ops; op->op != NULL; op++) |
| { |
| printf (" %s ", op->op); |
| print_hex (op->arg, N); |
| if (strcmp (op->op, "ADDC") == 0) |
| OP_ADDC (op->arg); |
| else if (strcmp (op->op, "ADDC_C0") == 0) |
| OP_ADDC_C (op->arg, 0); |
| else if (strcmp (op->op, "ADDC_C1") == 0) |
| OP_ADDC_C (op->arg, 1); |
| else if (strcmp (op->op, "SUBC") == 0) |
| OP_SUBC (op->arg); |
| else if (strcmp (op->op, "SUBC_X0") == 0) |
| OP_SUBC_X (op->arg, 0); |
| else if (strcmp (op->op, "SUBC_X1") == 0) |
| OP_SUBC_X (op->arg, 1); |
| else if (strcmp (op->op, "SUBB") == 0) |
| { |
| OP_SUBB (op->arg); |
| borrow_p ++; |
| } |
| else if (strcmp (op->op, "SUBB_B0") == 0) |
| { |
| OP_SUBB_B (op->arg, 0); |
| borrow_p ++; |
| } |
| else if (strcmp (op->op, "SUBB_B1") == 0) |
| { |
| OP_SUBB_B (op->arg, 1); |
| borrow_p ++; |
| } |
| else if (strcmp (op->op, "NEGC") == 0) |
| OP_NEGC (); |
| else if (strcmp (op->op, "NEGB") == 0) |
| { |
| OP_NEGB (); |
| borrow_p ++; |
| } |
| else |
| { |
| printf (" -- operator unknown\n"); |
| abort (); |
| } |
| } |
| printf (" = "); |
| print_hex (tst->result, N); |
| if (borrow_p) |
| printf (" B:%d", tst->carry_borrow); |
| else |
| printf (" C:%d", tst->carry_borrow); |
| printf (" V:%d", tst->overflow); |
| if (tst->carry_borrow != HAD_CARRY_BORROW) |
| { |
| if (borrow_p) |
| printf (" -- borrow (%d) wrong", HAD_CARRY_BORROW); |
| else |
| printf (" -- carry (%d) wrong", HAD_CARRY_BORROW); |
| errors ++; |
| } |
| if (tst->overflow != HAD_OVERFLOW) |
| { |
| printf (" -- overflow (%d) wrong", HAD_OVERFLOW); |
| errors ++; |
| } |
| if ((unsignedN) CARRY_BORROW_RESULT != (unsignedN) tst->result) |
| { |
| printf (" -- result for carry/borrow wrong "); |
| print_hex (CARRY_BORROW_RESULT, N); |
| errors ++; |
| } |
| if ((unsignedN) OVERFLOW_RESULT != (unsignedN) tst->result) |
| { |
| printf (" -- result for overflow wrong "); |
| print_hex (OVERFLOW_RESULT, N); |
| errors ++; |
| } |
| if ((unsignedN) RESULT != (unsignedN) tst->result) |
| { |
| printf (" -- result wrong "); |
| print_hex (RESULT, N); |
| errors ++; |
| } |
| printf ("\n"); |
| } |
| |
| |
| static const alu_test alu_N_tests[] = { |
| |
| /* 0 + 0; 0 + 1; 1 + 0; 1 + 1 */ |
| { 0, { { "ADDC", 0 }, }, 0, 0, 0, }, |
| { 0, { { "ADDC", 1 }, }, 1, 0, 0, }, |
| { 1, { { "ADDC", 0 }, }, 1, 0, 0, }, |
| { 1, { { "ADDC", 1 }, }, 2, 0, 0, }, |
| |
| /* 0 + 0 + 0; 0 + 0 + 1; 0 + 1 + 0; 0 + 1 + 1 */ |
| /* 1 + 0 + 0; 1 + 0 + 1; 1 + 1 + 0; 1 + 1 + 1 */ |
| { 0, { { "ADDC_C0", 0 }, }, 0, 0, 0, }, |
| { 0, { { "ADDC_C0", 1 }, }, 1, 0, 0, }, |
| { 0, { { "ADDC_C1", 0 }, }, 1, 0, 0, }, |
| { 0, { { "ADDC_C1", 1 }, }, 2, 0, 0, }, |
| { 1, { { "ADDC_C0", 0 }, }, 1, 0, 0, }, |
| { 1, { { "ADDC_C0", 1 }, }, 2, 0, 0, }, |
| { 1, { { "ADDC_C1", 0 }, }, 2, 0, 0, }, |
| { 1, { { "ADDC_C1", 1 }, }, 3, 0, 0, }, |
| |
| /* */ |
| { MAX_INT, { { "ADDC", 1 }, }, MIN_INT, 0, 1, }, |
| { MIN_INT, { { "ADDC", -1 }, }, MAX_INT, 1, 1, }, |
| { MAX_INT, { { "ADDC", MIN_INT }, }, -1, 0, 0, }, |
| { MIN_INT, { { "ADDC", MAX_INT }, }, -1, 0, 0, }, |
| { MAX_INT, { { "ADDC", MAX_INT }, }, MAX_INT << 1, 0, 1, }, |
| { MIN_INT, { { "ADDC", MIN_INT }, }, 0, 1, 1, }, |
| /* */ |
| { 0, { { "ADDC_C1", -1 }, }, 0, 1, 0, }, |
| { 0, { { "ADDC_C1", -2 }, }, -1, 0, 0, }, |
| { -1, { { "ADDC_C1", 0 }, }, 0, 1, 0, }, |
| { 0, { { "ADDC_C0", 0 }, }, 0, 0, 0, }, |
| { -1, { { "ADDC_C1", -1 }, }, -1, 1, 0, }, |
| { -1, { { "ADDC_C1", 1 }, }, 1, 1, 0, }, |
| { 0, { { "ADDC_C1", MAX_INT }, }, MIN_INT, 0, 1, }, |
| { MAX_INT, { { "ADDC_C1", 1 }, }, MIN_INT + 1, 0, 1, }, |
| { MAX_INT, { { "ADDC_C1", MIN_INT }, }, 0, 1, 0, }, |
| { MAX_INT, { { "ADDC_C1", MAX_INT }, }, (MAX_INT << 1) + 1, 0, 1, }, |
| { MAX_INT, { { "ADDC_C0", MAX_INT }, }, MAX_INT << 1, 0, 1, }, |
| |
| /* 0 - 0 */ |
| { 0, { { "SUBC", 0 }, }, 0, 1, 0, }, |
| { 0, { { "SUBB", 0 }, }, 0, 0, 0, }, |
| |
| /* 0 - 1 */ |
| { 0, { { "SUBC", 1 }, }, -1, 0, 0, }, |
| { 0, { { "SUBB", 1 }, }, -1, 1, 0, }, |
| |
| /* 1 - 0 */ |
| { 1, { { "SUBC", 0 }, }, 1, 1, 0, }, |
| { 1, { { "SUBB", 0 }, }, 1, 0, 0, }, |
| |
| /* 1 - 1 */ |
| { 1, { { "SUBC", 1 }, }, 0, 1, 0, }, |
| { 1, { { "SUBB", 1 }, }, 0, 0, 0, }, |
| |
| /* 0 - 0 - 0 */ |
| { 0, { { "SUBC_X0", 0 }, }, -1, 0, 0, }, |
| { 0, { { "SUBB_B0", 0 }, }, 0, 0, 0, }, |
| |
| /* 0 - 0 - 1 */ |
| { 0, { { "SUBC_X0", 1 }, }, -2, 0, 0, }, |
| { 0, { { "SUBB_B0", 1 }, }, -1, 1, 0, }, |
| |
| /* 0 - 1 - 0 */ |
| { 0, { { "SUBC_X1", 0 }, }, 0, 1, 0, }, |
| { 0, { { "SUBB_B1", 0 }, }, -1, 1, 0, }, |
| |
| /* 0 - 1 - 1 */ |
| { 0, { { "SUBC_X1", 1 }, }, -1, 0, 0, }, |
| { 0, { { "SUBB_B1", 1 }, }, -2, 1, 0, }, |
| |
| /* 1 - 0 - 0 */ |
| { 1, { { "SUBC_X0", 0 }, }, 0, 1, 0, }, |
| { 1, { { "SUBB_B0", 0 }, }, 1, 0, 0, }, |
| |
| /* 1 - 0 - 1 */ |
| { 1, { { "SUBC_X0", 1 }, }, -1, 0, 0, }, |
| { 1, { { "SUBB_B0", 1 }, }, 0, 0, 0, }, |
| |
| /* 1 - 1 - 0 */ |
| { 1, { { "SUBC_X1", 0 }, }, 1, 1, 0, }, |
| { 1, { { "SUBB_B1", 0 }, }, 0, 0, 0, }, |
| |
| /* 1 - 1 - 1 */ |
| { 1, { { "SUBC_X1", 1 }, }, 0, 1, 0, }, |
| { 1, { { "SUBB_B1", 1 }, }, -1, 1, 0, }, |
| |
| /* */ |
| { 0, { { "SUBC", MIN_INT }, }, MIN_INT, 0, 1, }, |
| { MIN_INT, { { "SUBC", 1 }, }, MAX_INT, 1, 1, }, |
| { MAX_INT, { { "SUBC", MAX_INT }, }, 0, 1, 0, }, |
| |
| /* */ |
| { 0, { { "SUBC_X0", MIN_INT }, }, MAX_INT, 0, 0, }, |
| { MIN_INT, { { "SUBC_X1", 0 }, }, MIN_INT, 1, 0, }, |
| { MAX_INT, { { "SUBC_X0", MAX_INT }, }, -1, 0, 0, }, |
| |
| /* */ |
| { MAX_INT, { { "NEGC", 0 }, }, MIN_INT + 1, 0, 0, }, |
| { MAX_INT, { { "NEGC", 0 }, }, MIN_INT + 1, 0, 0, }, |
| { MIN_INT, { { "NEGC", 0 }, }, MIN_INT, 0, 1, }, |
| { 0, { { "NEGC", 0 }, }, 0, 1, 0, }, |
| { -1, { { "NEGC", 0 }, }, 1, 0, 0, }, |
| { 1, { { "NEGC", 0 }, }, -1, 0, 0, }, |
| }; |
| |
| |
| static void |
| do_alu_N_tests (void) |
| { |
| int i; |
| for (i = 0; i < sizeof (alu_N_tests) / sizeof (*alu_N_tests); i++) |
| { |
| const alu_test *tst = &alu_N_tests[i]; |
| do_op_N (tst); |
| } |
| } |
| |
| |
| #undef OP_BEGIN |
| #undef OP_ADDC |
| #undef OP_ADDC_C |
| #undef OP_SUBB |
| #undef OP_SUBC |
| #undef OP_SUBC_X |
| #undef OP_SUBB_B |
| #undef HAD_OVERFLOW |
| #undef HAD_CARRY_BORROW |
| #undef OVERFLOW_RESULT |
| #undef CARRY_BORROW_RESULT |
| #undef RESULT |
| #undef do_op_N |
| #undef unsignedN |
| #undef MAX_INT |
| #undef MIN_INT |
| #undef alu_N_tests |
| #undef do_alu_N_tests |
| |