1 /*
2  * Test R5900-specific DIV1.
3  */
4 
5 #include <stdio.h>
6 #include <inttypes.h>
7 #include <assert.h>
8 
9 struct quotient_remainder { int32_t quotient, remainder; };
10 
11 static struct quotient_remainder div1(int32_t rs, int32_t rt)
12 {
13     int32_t lo, hi;
14 
15     __asm__ __volatile__ (
16             "    div1 $0, %2, %3\n"
17             "    mflo1 %0\n"
18             "    mfhi1 %1\n"
19             : "=r" (lo), "=r" (hi)
20             : "r" (rs), "r" (rt));
21 
22     assert(rs / rt == lo);
23     assert(rs % rt == hi);
24 
25     return (struct quotient_remainder) { .quotient = lo, .remainder = hi };
26 }
27 
28 static void verify_div1(int32_t rs, int32_t rt,
29                         int32_t expected_quotient,
30                         int32_t expected_remainder)
31 {
32     struct quotient_remainder qr = div1(rs, rt);
33 
34     assert(qr.quotient == expected_quotient);
35     assert(qr.remainder == expected_remainder);
36 }
37 
38 static void verify_div1_negations(int32_t rs, int32_t rt,
39                                   int32_t expected_quotient,
40                                   int32_t expected_remainder)
41 {
42     verify_div1(rs, rt, expected_quotient, expected_remainder);
43     verify_div1(rs, -rt, -expected_quotient, expected_remainder);
44     verify_div1(-rs, rt, -expected_quotient, -expected_remainder);
45     verify_div1(-rs, -rt, expected_quotient, -expected_remainder);
46 }
47 
48 int main()
49 {
50     verify_div1_negations(0, 1, 0, 0);
51     verify_div1_negations(1, 1, 1, 0);
52     verify_div1_negations(1, 2, 0, 1);
53     verify_div1_negations(17, 19, 0, 17);
54     verify_div1_negations(19, 17, 1, 2);
55     verify_div1_negations(77773, 101, 770, 3);
56 
57     verify_div1(-0x80000000,  1, -0x80000000, 0);
58 
59     /*
60      * Supplementary explanation from the Toshiba TX System RISC TX79 Core
61      * Architecture manual, A-38 and B-7, https://wiki.qemu.org/File:C790.pdf
62      *
63      * Normally, when 0x80000000 (-2147483648) the signed minimum value is
64      * divided by 0xFFFFFFFF (-1), the operation will result in an overflow.
65      * However, in this instruction an overflow exception doesn't occur and
66      * the result will be as follows:
67      *
68      * Quotient is 0x80000000 (-2147483648), and remainder is 0x00000000 (0).
69      */
70     verify_div1(-0x80000000, -1, -0x80000000, 0);
71 
72     return 0;
73 }
74