aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/tests/testalu.cpp
blob: a701b647e0ba562eec324f98348c413fbc57d205 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include "tst_machine.h"
#include "alu.h"
#include "qtmipsexception.h"

using namespace machine;

void MachineTests::alu_data() {
    QTest::addColumn<AluOp>("op");
    QTest::addColumn<std::uint32_t>("s");
    QTest::addColumn<std::uint32_t>("t");
    QTest::addColumn<std::uint8_t>("sa");
    QTest::addColumn<Registers>("regs_init");
    QTest::addColumn<Registers>("regs_res");
    QTest::addColumn<std::uint32_t>("res");

    QTest::newRow("SLL") << ALU_OP_SLL \
                         << (std::uint32_t)0 \
                         << (std::uint32_t)0x80000001 \
                         << (std::uint8_t)3 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0x8;
    QTest::newRow("SRL") << ALU_OP_SRL \
                         << (std::uint32_t)0 \
                         << (std::uint32_t)0x80000008 \
                         << (std::uint8_t)3 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0x10000001;
    QTest::newRow("SRA") << ALU_OP_SRA \
                         << (std::uint32_t)0 \
                         << (std::uint32_t)0x80000008 \
                         << (std::uint8_t)3 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0xF0000001;
    QTest::newRow("SLLV") << ALU_OP_SLLV \
                         << (std::uint32_t)3 \
                         << (std::uint32_t)0x80000001 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0x8;
    QTest::newRow("SRLV") << ALU_OP_SRLV \
                         << (std::uint32_t)3 \
                         << (std::uint32_t)0x80000008 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0x10000001;
    QTest::newRow("SRAV") << ALU_OP_SRAV \
                         << (std::uint32_t)3 \
                         << (std::uint32_t)0x80000008 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0xF0000001;
    // JR and JALR should have no effect and we test that in core (it really doesn't make sense to test it here)
    QTest::newRow("MOVZ") << ALU_OP_MOVZ \
                         << (std::uint32_t)22 \
                         << (std::uint32_t)0 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)22;
    QTest::newRow("MOVN") << ALU_OP_MOVN \
                         << (std::uint32_t)22 \
                         << (std::uint32_t)1 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)22;
    {
    Registers init;
    init.write_hi_lo(true, 42);
    init.write_hi_lo(false, 24);
    Registers res(init);
    QTest::newRow("MFHI") << ALU_OP_MFHI \
                         << (std::uint32_t)0 \
                         << (std::uint32_t)0 \
                         << (std::uint8_t)0 \
                         << init \
                         << res \
                         << (std::uint32_t)42;
    QTest::newRow("MFLO") << ALU_OP_MFLO \
                         << (std::uint32_t)0 \
                         << (std::uint32_t)0 \
                         << (std::uint8_t)0 \
                         << init \
                         << res \
                         << (std::uint32_t)24;
    res.write_hi_lo(true, 43);
    QTest::newRow("MTHI") << ALU_OP_MTHI \
                         << (std::uint32_t)43 \
                         << (std::uint32_t)0 \
                         << (std::uint8_t)0 \
                         << init \
                         << res \
                         << (std::uint32_t)0;
    res.write_hi_lo(true, 42);
    res.write_hi_lo(false, 23);
    QTest::newRow("MTLO") << ALU_OP_MTLO \
                         << (std::uint32_t)23 \
                         << (std::uint32_t)0 \
                         << (std::uint8_t)0 \
                         << init \
                         << res \
                         << (std::uint32_t)0;
    }
    QTest::newRow("ADD") << ALU_OP_ADD \
                         << (std::uint32_t)24 \
                         << (std::uint32_t)66 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)90;
    QTest::newRow("ADDU") << ALU_OP_ADDU \
                         << (std::uint32_t)24 \
                         << (std::uint32_t)66 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)90;
    QTest::newRow("SUB") << ALU_OP_SUB \
                         << (std::uint32_t)66 \
                         << (std::uint32_t)24 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)42;
    QTest::newRow("SUBU") << ALU_OP_SUBU \
                         << (std::uint32_t)24 \
                         << (std::uint32_t)66 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)-42;
    QTest::newRow("AND") << ALU_OP_AND \
                         << (std::uint32_t)0xA81 \
                         << (std::uint32_t)0x603 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0x201;
    QTest::newRow("OR") << ALU_OP_OR \
                         << (std::uint32_t)0xA81 \
                         << (std::uint32_t)0x603 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0xE83;
    QTest::newRow("XOR") << ALU_OP_XOR \
                         << (std::uint32_t)0xA81 \
                         << (std::uint32_t)0x603 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0xC82;
    QTest::newRow("NOR") << ALU_OP_NOR \
                         << (std::uint32_t)0xA81 \
                         << (std::uint32_t)0x603 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)0xFFFFF17C;
    QTest::newRow("SLT") << ALU_OP_SLT \
                         << (std::uint32_t)-31 \
                         << (std::uint32_t)24 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)1;
    QTest::newRow("SLTU") << ALU_OP_SLTU \
                         << (std::uint32_t)24 \
                         << (std::uint32_t)32 \
                         << (std::uint8_t)0 \
                         << Registers() \
                         << Registers() \
                         << (std::uint32_t)1;
}

void MachineTests::alu() {
    QFETCH(AluOp, op);
    QFETCH(std::uint32_t, s);
    QFETCH(std::uint32_t, t);
    QFETCH(std::uint8_t, sa);
    QFETCH(Registers, regs_init);
    QFETCH(Registers, regs_res);
    QFETCH(std::uint32_t, res);

    QCOMPARE(alu_operate(op, s , t, sa, &regs_init), res);
    QCOMPARE(regs_res, regs_init);
}

void MachineTests::alu_except_data() {
    QTest::addColumn<std::uint8_t>("op");
    QTest::addColumn<std::uint32_t>("s");
    QTest::addColumn<std::uint32_t>("t");
    // Note no sa as shift unstruction has no exceptions

    QTest::newRow("ADD") << (std::uint8_t)ALU_OP_ADD \
                         << (std::uint32_t)0x8fffffff \
                         << (std::uint32_t)0x90000000;
    QTest::newRow("SUB") << (std::uint8_t)ALU_OP_SUB \
                         << (std::uint32_t)3 \
                         << (std::uint32_t)4;
    // Just test that we can throw unsupported ALU operation
    QTest::newRow("?") << (std::uint8_t)ALU_OP_LAST \
                         << (std::uint32_t)0 \
                         << (std::uint32_t)0;
}

void MachineTests::alu_except() {
    QFETCH(std::uint8_t, op);
    QFETCH(std::uint32_t, s);
    QFETCH(std::uint32_t, t);
    Registers regs;

    // Only runtime exception is expected as any other exception is a bug
    QVERIFY_EXCEPTION_THROWN(alu_operate((enum AluOp)op, s , t, 0, &regs), QtMipsExceptionRuntime);
}