451ab91e |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - interpreter_special.def * |
3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
4 | * Copyright (C) 2002 Hacktarux * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | DECLARE_INSTRUCTION(NOP) |
23 | { |
24 | ADD_TO_PC(1); |
25 | } |
26 | |
27 | DECLARE_INSTRUCTION(SLL) |
28 | { |
29 | rrd32 = (unsigned int)(rrt32) << rsa; |
30 | sign_extended(rrd); |
31 | ADD_TO_PC(1); |
32 | } |
33 | |
34 | DECLARE_INSTRUCTION(SRL) |
35 | { |
36 | rrd32 = (unsigned int)rrt32 >> rsa; |
37 | sign_extended(rrd); |
38 | ADD_TO_PC(1); |
39 | } |
40 | |
41 | DECLARE_INSTRUCTION(SRA) |
42 | { |
43 | rrd32 = (signed int)rrt32 >> rsa; |
44 | sign_extended(rrd); |
45 | ADD_TO_PC(1); |
46 | } |
47 | |
48 | DECLARE_INSTRUCTION(SLLV) |
49 | { |
50 | rrd32 = (unsigned int)(rrt32) << (rrs32&0x1F); |
51 | sign_extended(rrd); |
52 | ADD_TO_PC(1); |
53 | } |
54 | |
55 | DECLARE_INSTRUCTION(SRLV) |
56 | { |
57 | rrd32 = (unsigned int)rrt32 >> (rrs32 & 0x1F); |
58 | sign_extended(rrd); |
59 | ADD_TO_PC(1); |
60 | } |
61 | |
62 | DECLARE_INSTRUCTION(SRAV) |
63 | { |
64 | rrd32 = (signed int)rrt32 >> (rrs32 & 0x1F); |
65 | sign_extended(rrd); |
66 | ADD_TO_PC(1); |
67 | } |
68 | |
69 | DECLARE_JUMP(JR, irs32, 1, ®[0], 0, 0) |
70 | DECLARE_JUMP(JALR, irs32, 1, PC->f.r.rd, 0, 0) |
71 | |
72 | DECLARE_INSTRUCTION(SYSCALL) |
73 | { |
74 | Cause = 8 << 2; |
75 | exception_general(); |
76 | } |
77 | |
78 | DECLARE_INSTRUCTION(SYNC) |
79 | { |
80 | ADD_TO_PC(1); |
81 | } |
82 | |
83 | DECLARE_INSTRUCTION(MFHI) |
84 | { |
85 | rrd = hi; |
86 | ADD_TO_PC(1); |
87 | } |
88 | |
89 | DECLARE_INSTRUCTION(MTHI) |
90 | { |
91 | hi = rrs; |
92 | ADD_TO_PC(1); |
93 | } |
94 | |
95 | DECLARE_INSTRUCTION(MFLO) |
96 | { |
97 | rrd = lo; |
98 | ADD_TO_PC(1); |
99 | } |
100 | |
101 | DECLARE_INSTRUCTION(MTLO) |
102 | { |
103 | lo = rrs; |
104 | ADD_TO_PC(1); |
105 | } |
106 | |
107 | DECLARE_INSTRUCTION(DSLLV) |
108 | { |
109 | rrd = rrt << (rrs32&0x3F); |
110 | ADD_TO_PC(1); |
111 | } |
112 | |
113 | DECLARE_INSTRUCTION(DSRLV) |
114 | { |
115 | rrd = (unsigned long long)rrt >> (rrs32 & 0x3F); |
116 | ADD_TO_PC(1); |
117 | } |
118 | |
119 | DECLARE_INSTRUCTION(DSRAV) |
120 | { |
121 | rrd = (long long)rrt >> (rrs32 & 0x3F); |
122 | ADD_TO_PC(1); |
123 | } |
124 | |
125 | DECLARE_INSTRUCTION(MULT) |
126 | { |
127 | long long int temp; |
128 | temp = rrs * rrt; |
129 | hi = temp >> 32; |
130 | lo = temp; |
131 | sign_extended(lo); |
132 | ADD_TO_PC(1); |
133 | } |
134 | |
135 | DECLARE_INSTRUCTION(MULTU) |
136 | { |
137 | unsigned long long int temp; |
138 | temp = (unsigned int)rrs * (unsigned long long)((unsigned int)rrt); |
139 | hi = (long long)temp >> 32; |
140 | lo = temp; |
141 | sign_extended(lo); |
142 | ADD_TO_PC(1); |
143 | } |
144 | |
145 | DECLARE_INSTRUCTION(DIV) |
146 | { |
147 | if (rrt32) |
148 | { |
149 | lo = rrs32 / rrt32; |
150 | hi = rrs32 % rrt32; |
151 | sign_extended(lo); |
152 | sign_extended(hi); |
153 | } |
154 | else DebugMessage(M64MSG_ERROR, "DIV: divide by 0"); |
155 | ADD_TO_PC(1); |
156 | } |
157 | |
158 | DECLARE_INSTRUCTION(DIVU) |
159 | { |
160 | if (rrt32) |
161 | { |
162 | lo = (unsigned int)rrs32 / (unsigned int)rrt32; |
163 | hi = (unsigned int)rrs32 % (unsigned int)rrt32; |
164 | sign_extended(lo); |
165 | sign_extended(hi); |
166 | } |
167 | else DebugMessage(M64MSG_ERROR, "DIVU: divide by 0"); |
168 | ADD_TO_PC(1); |
169 | } |
170 | |
171 | DECLARE_INSTRUCTION(DMULT) |
172 | { |
173 | unsigned long long int op1, op2, op3, op4; |
174 | unsigned long long int result1, result2, result3, result4; |
175 | unsigned long long int temp1, temp2, temp3, temp4; |
176 | int sign = 0; |
177 | |
178 | if (rrs < 0) |
179 | { |
180 | op2 = -rrs; |
181 | sign = 1 - sign; |
182 | } |
183 | else op2 = rrs; |
184 | if (rrt < 0) |
185 | { |
186 | op4 = -rrt; |
187 | sign = 1 - sign; |
188 | } |
189 | else op4 = rrt; |
190 | |
191 | op1 = op2 & 0xFFFFFFFF; |
192 | op2 = (op2 >> 32) & 0xFFFFFFFF; |
193 | op3 = op4 & 0xFFFFFFFF; |
194 | op4 = (op4 >> 32) & 0xFFFFFFFF; |
195 | |
196 | temp1 = op1 * op3; |
197 | temp2 = (temp1 >> 32) + op1 * op4; |
198 | temp3 = op2 * op3; |
199 | temp4 = (temp3 >> 32) + op2 * op4; |
200 | |
201 | result1 = temp1 & 0xFFFFFFFF; |
202 | result2 = temp2 + (temp3 & 0xFFFFFFFF); |
203 | result3 = (result2 >> 32) + temp4; |
204 | result4 = (result3 >> 32); |
205 | |
206 | lo = result1 | (result2 << 32); |
207 | hi = (result3 & 0xFFFFFFFF) | (result4 << 32); |
208 | if (sign) |
209 | { |
210 | hi = ~hi; |
211 | if (!lo) hi++; |
212 | else lo = ~lo + 1; |
213 | } |
214 | ADD_TO_PC(1); |
215 | } |
216 | |
217 | DECLARE_INSTRUCTION(DMULTU) |
218 | { |
219 | unsigned long long int op1, op2, op3, op4; |
220 | unsigned long long int result1, result2, result3, result4; |
221 | unsigned long long int temp1, temp2, temp3, temp4; |
222 | |
223 | op1 = rrs & 0xFFFFFFFF; |
224 | op2 = (rrs >> 32) & 0xFFFFFFFF; |
225 | op3 = rrt & 0xFFFFFFFF; |
226 | op4 = (rrt >> 32) & 0xFFFFFFFF; |
227 | |
228 | temp1 = op1 * op3; |
229 | temp2 = (temp1 >> 32) + op1 * op4; |
230 | temp3 = op2 * op3; |
231 | temp4 = (temp3 >> 32) + op2 * op4; |
232 | |
233 | result1 = temp1 & 0xFFFFFFFF; |
234 | result2 = temp2 + (temp3 & 0xFFFFFFFF); |
235 | result3 = (result2 >> 32) + temp4; |
236 | result4 = (result3 >> 32); |
237 | |
238 | lo = result1 | (result2 << 32); |
239 | hi = (result3 & 0xFFFFFFFF) | (result4 << 32); |
240 | |
241 | ADD_TO_PC(1); |
242 | } |
243 | |
244 | DECLARE_INSTRUCTION(DDIV) |
245 | { |
246 | if (rrt) |
247 | { |
248 | lo = (long long int)rrs / (long long int)rrt; |
249 | hi = (long long int)rrs % (long long int)rrt; |
250 | } |
251 | else DebugMessage(M64MSG_ERROR, "DDIV: divide by 0"); |
252 | ADD_TO_PC(1); |
253 | } |
254 | |
255 | DECLARE_INSTRUCTION(DDIVU) |
256 | { |
257 | if (rrt) |
258 | { |
259 | lo = (unsigned long long int)rrs / (unsigned long long int)rrt; |
260 | hi = (unsigned long long int)rrs % (unsigned long long int)rrt; |
261 | } |
262 | else DebugMessage(M64MSG_ERROR, "DDIVU: divide by 0"); |
263 | ADD_TO_PC(1); |
264 | } |
265 | |
266 | DECLARE_INSTRUCTION(ADD) |
267 | { |
268 | rrd32 = rrs32 + rrt32; |
269 | sign_extended(rrd); |
270 | ADD_TO_PC(1); |
271 | } |
272 | |
273 | DECLARE_INSTRUCTION(ADDU) |
274 | { |
275 | rrd32 = rrs32 + rrt32; |
276 | sign_extended(rrd); |
277 | ADD_TO_PC(1); |
278 | } |
279 | |
280 | DECLARE_INSTRUCTION(SUB) |
281 | { |
282 | rrd32 = rrs32 - rrt32; |
283 | sign_extended(rrd); |
284 | ADD_TO_PC(1); |
285 | } |
286 | |
287 | DECLARE_INSTRUCTION(SUBU) |
288 | { |
289 | rrd32 = rrs32 - rrt32; |
290 | sign_extended(rrd); |
291 | ADD_TO_PC(1); |
292 | } |
293 | |
294 | DECLARE_INSTRUCTION(AND) |
295 | { |
296 | rrd = rrs & rrt; |
297 | ADD_TO_PC(1); |
298 | } |
299 | |
300 | DECLARE_INSTRUCTION(OR) |
301 | { |
302 | rrd = rrs | rrt; |
303 | ADD_TO_PC(1); |
304 | } |
305 | |
306 | DECLARE_INSTRUCTION(XOR) |
307 | { |
308 | rrd = rrs ^ rrt; |
309 | ADD_TO_PC(1); |
310 | } |
311 | |
312 | DECLARE_INSTRUCTION(NOR) |
313 | { |
314 | rrd = ~(rrs | rrt); |
315 | ADD_TO_PC(1); |
316 | } |
317 | |
318 | DECLARE_INSTRUCTION(SLT) |
319 | { |
320 | if (rrs < rrt) rrd = 1; |
321 | else rrd = 0; |
322 | ADD_TO_PC(1); |
323 | } |
324 | |
325 | DECLARE_INSTRUCTION(SLTU) |
326 | { |
327 | if ((unsigned long long)rrs < (unsigned long long)rrt) |
328 | rrd = 1; |
329 | else rrd = 0; |
330 | ADD_TO_PC(1); |
331 | } |
332 | |
333 | DECLARE_INSTRUCTION(DADD) |
334 | { |
335 | rrd = rrs + rrt; |
336 | ADD_TO_PC(1); |
337 | } |
338 | |
339 | DECLARE_INSTRUCTION(DADDU) |
340 | { |
341 | rrd = rrs + rrt; |
342 | ADD_TO_PC(1); |
343 | } |
344 | |
345 | DECLARE_INSTRUCTION(DSUB) |
346 | { |
347 | rrd = rrs - rrt; |
348 | ADD_TO_PC(1); |
349 | } |
350 | |
351 | DECLARE_INSTRUCTION(DSUBU) |
352 | { |
353 | rrd = rrs - rrt; |
354 | ADD_TO_PC(1); |
355 | } |
356 | |
357 | DECLARE_INSTRUCTION(TEQ) |
358 | { |
359 | if (rrs == rrt) |
360 | { |
361 | DebugMessage(M64MSG_ERROR, "trap exception in TEQ"); |
362 | stop=1; |
363 | } |
364 | ADD_TO_PC(1); |
365 | } |
366 | |
367 | DECLARE_INSTRUCTION(DSLL) |
368 | { |
369 | rrd = rrt << rsa; |
370 | ADD_TO_PC(1); |
371 | } |
372 | |
373 | DECLARE_INSTRUCTION(DSRL) |
374 | { |
375 | rrd = (unsigned long long)rrt >> rsa; |
376 | ADD_TO_PC(1); |
377 | } |
378 | |
379 | DECLARE_INSTRUCTION(DSRA) |
380 | { |
381 | rrd = rrt >> rsa; |
382 | ADD_TO_PC(1); |
383 | } |
384 | |
385 | DECLARE_INSTRUCTION(DSLL32) |
386 | { |
387 | rrd = rrt << (32+rsa); |
388 | ADD_TO_PC(1); |
389 | } |
390 | |
391 | DECLARE_INSTRUCTION(DSRL32) |
392 | { |
393 | rrd = (unsigned long long int)rrt >> (32+rsa); |
394 | ADD_TO_PC(1); |
395 | } |
396 | |
397 | DECLARE_INSTRUCTION(DSRA32) |
398 | { |
399 | rrd = (signed long long int)rrt >> (32+rsa); |
400 | ADD_TO_PC(1); |
401 | } |