1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4
5 #include "Core/PowerPC/Interpreter/Interpreter.h"
6
7 #include "Common/BitUtils.h"
8 #include "Common/CommonTypes.h"
9 #include "Common/Logging/Log.h"
10 #include "Core/PowerPC/PowerPC.h"
11
Helper_UpdateCR0(u32 value)12 void Interpreter::Helper_UpdateCR0(u32 value)
13 {
14 s64 sign_extended = (s64)(s32)value;
15 u64 cr_val = (u64)sign_extended;
16 cr_val = (cr_val & ~(1ull << 61)) | ((u64)PowerPC::GetXER_SO() << 61);
17
18 PowerPC::ppcState.cr.fields[0] = cr_val;
19 }
20
Helper_Carry(u32 value1,u32 value2)21 u32 Interpreter::Helper_Carry(u32 value1, u32 value2)
22 {
23 return value2 > (~value1);
24 }
25
addi(UGeckoInstruction inst)26 void Interpreter::addi(UGeckoInstruction inst)
27 {
28 if (inst.RA)
29 rGPR[inst.RD] = rGPR[inst.RA] + inst.SIMM_16;
30 else
31 rGPR[inst.RD] = inst.SIMM_16;
32 }
33
addic(UGeckoInstruction inst)34 void Interpreter::addic(UGeckoInstruction inst)
35 {
36 u32 a = rGPR[inst.RA];
37 u32 imm = (u32)(s32)inst.SIMM_16;
38 // TODO(ector): verify this thing
39 rGPR[inst.RD] = a + imm;
40 PowerPC::SetCarry(Helper_Carry(a, imm));
41 }
42
addic_rc(UGeckoInstruction inst)43 void Interpreter::addic_rc(UGeckoInstruction inst)
44 {
45 addic(inst);
46 Helper_UpdateCR0(rGPR[inst.RD]);
47 }
48
addis(UGeckoInstruction inst)49 void Interpreter::addis(UGeckoInstruction inst)
50 {
51 if (inst.RA)
52 rGPR[inst.RD] = rGPR[inst.RA] + (inst.SIMM_16 << 16);
53 else
54 rGPR[inst.RD] = (inst.SIMM_16 << 16);
55 }
56
andi_rc(UGeckoInstruction inst)57 void Interpreter::andi_rc(UGeckoInstruction inst)
58 {
59 rGPR[inst.RA] = rGPR[inst.RS] & inst.UIMM;
60 Helper_UpdateCR0(rGPR[inst.RA]);
61 }
62
andis_rc(UGeckoInstruction inst)63 void Interpreter::andis_rc(UGeckoInstruction inst)
64 {
65 rGPR[inst.RA] = rGPR[inst.RS] & ((u32)inst.UIMM << 16);
66 Helper_UpdateCR0(rGPR[inst.RA]);
67 }
68
cmpi(UGeckoInstruction inst)69 void Interpreter::cmpi(UGeckoInstruction inst)
70 {
71 const s32 a = static_cast<s32>(rGPR[inst.RA]);
72 const s32 b = inst.SIMM_16;
73 u32 f;
74
75 if (a < b)
76 f = 0x8;
77 else if (a > b)
78 f = 0x4;
79 else
80 f = 0x2; // equals
81
82 if (PowerPC::GetXER_SO())
83 f |= 0x1;
84
85 PowerPC::ppcState.cr.SetField(inst.CRFD, f);
86 }
87
cmpli(UGeckoInstruction inst)88 void Interpreter::cmpli(UGeckoInstruction inst)
89 {
90 const u32 a = rGPR[inst.RA];
91 const u32 b = inst.UIMM;
92 u32 f;
93
94 if (a < b)
95 f = 0x8;
96 else if (a > b)
97 f = 0x4;
98 else
99 f = 0x2; // equals
100
101 if (PowerPC::GetXER_SO())
102 f |= 0x1;
103
104 PowerPC::ppcState.cr.SetField(inst.CRFD, f);
105 }
106
mulli(UGeckoInstruction inst)107 void Interpreter::mulli(UGeckoInstruction inst)
108 {
109 rGPR[inst.RD] = (s32)rGPR[inst.RA] * inst.SIMM_16;
110 }
111
ori(UGeckoInstruction inst)112 void Interpreter::ori(UGeckoInstruction inst)
113 {
114 rGPR[inst.RA] = rGPR[inst.RS] | inst.UIMM;
115 }
116
oris(UGeckoInstruction inst)117 void Interpreter::oris(UGeckoInstruction inst)
118 {
119 rGPR[inst.RA] = rGPR[inst.RS] | (inst.UIMM << 16);
120 }
121
subfic(UGeckoInstruction inst)122 void Interpreter::subfic(UGeckoInstruction inst)
123 {
124 s32 immediate = inst.SIMM_16;
125 rGPR[inst.RD] = immediate - (int)rGPR[inst.RA];
126 PowerPC::SetCarry((rGPR[inst.RA] == 0) || (Helper_Carry(0 - rGPR[inst.RA], immediate)));
127 }
128
twi(UGeckoInstruction inst)129 void Interpreter::twi(UGeckoInstruction inst)
130 {
131 s32 a = rGPR[inst.RA];
132 s32 b = inst.SIMM_16;
133 s32 TO = inst.TO;
134
135 DEBUG_LOG(POWERPC, "twi rA %x SIMM %x TO %0x", a, b, TO);
136
137 if (((a < b) && (TO & 0x10)) || ((a > b) && (TO & 0x08)) || ((a == b) && (TO & 0x04)) ||
138 (((u32)a < (u32)b) && (TO & 0x02)) || (((u32)a > (u32)b) && (TO & 0x01)))
139 {
140 PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
141 PowerPC::CheckExceptions();
142 m_end_block = true; // Dunno about this
143 }
144 }
145
xori(UGeckoInstruction inst)146 void Interpreter::xori(UGeckoInstruction inst)
147 {
148 rGPR[inst.RA] = rGPR[inst.RS] ^ inst.UIMM;
149 }
150
xoris(UGeckoInstruction inst)151 void Interpreter::xoris(UGeckoInstruction inst)
152 {
153 rGPR[inst.RA] = rGPR[inst.RS] ^ (inst.UIMM << 16);
154 }
155
rlwimix(UGeckoInstruction inst)156 void Interpreter::rlwimix(UGeckoInstruction inst)
157 {
158 const u32 mask = MakeRotationMask(inst.MB, inst.ME);
159 rGPR[inst.RA] = (rGPR[inst.RA] & ~mask) | (Common::RotateLeft(rGPR[inst.RS], inst.SH) & mask);
160
161 if (inst.Rc)
162 Helper_UpdateCR0(rGPR[inst.RA]);
163 }
164
rlwinmx(UGeckoInstruction inst)165 void Interpreter::rlwinmx(UGeckoInstruction inst)
166 {
167 const u32 mask = MakeRotationMask(inst.MB, inst.ME);
168 rGPR[inst.RA] = Common::RotateLeft(rGPR[inst.RS], inst.SH) & mask;
169
170 if (inst.Rc)
171 Helper_UpdateCR0(rGPR[inst.RA]);
172 }
173
rlwnmx(UGeckoInstruction inst)174 void Interpreter::rlwnmx(UGeckoInstruction inst)
175 {
176 const u32 mask = MakeRotationMask(inst.MB, inst.ME);
177 rGPR[inst.RA] = Common::RotateLeft(rGPR[inst.RS], rGPR[inst.RB] & 0x1F) & mask;
178
179 if (inst.Rc)
180 Helper_UpdateCR0(rGPR[inst.RA]);
181 }
182
andx(UGeckoInstruction inst)183 void Interpreter::andx(UGeckoInstruction inst)
184 {
185 rGPR[inst.RA] = rGPR[inst.RS] & rGPR[inst.RB];
186
187 if (inst.Rc)
188 Helper_UpdateCR0(rGPR[inst.RA]);
189 }
190
andcx(UGeckoInstruction inst)191 void Interpreter::andcx(UGeckoInstruction inst)
192 {
193 rGPR[inst.RA] = rGPR[inst.RS] & ~rGPR[inst.RB];
194
195 if (inst.Rc)
196 Helper_UpdateCR0(rGPR[inst.RA]);
197 }
198
cmp(UGeckoInstruction inst)199 void Interpreter::cmp(UGeckoInstruction inst)
200 {
201 const s32 a = static_cast<s32>(rGPR[inst.RA]);
202 const s32 b = static_cast<s32>(rGPR[inst.RB]);
203 u32 temp;
204
205 if (a < b)
206 temp = 0x8;
207 else if (a > b)
208 temp = 0x4;
209 else // Equals
210 temp = 0x2;
211
212 if (PowerPC::GetXER_SO())
213 temp |= 0x1;
214
215 PowerPC::ppcState.cr.SetField(inst.CRFD, temp);
216 }
217
cmpl(UGeckoInstruction inst)218 void Interpreter::cmpl(UGeckoInstruction inst)
219 {
220 const u32 a = rGPR[inst.RA];
221 const u32 b = rGPR[inst.RB];
222 u32 temp;
223
224 if (a < b)
225 temp = 0x8;
226 else if (a > b)
227 temp = 0x4;
228 else // Equals
229 temp = 0x2;
230
231 if (PowerPC::GetXER_SO())
232 temp |= 0x1;
233
234 PowerPC::ppcState.cr.SetField(inst.CRFD, temp);
235 }
236
cntlzwx(UGeckoInstruction inst)237 void Interpreter::cntlzwx(UGeckoInstruction inst)
238 {
239 u32 val = rGPR[inst.RS];
240 u32 mask = 0x80000000;
241
242 int i = 0;
243 for (; i < 32; i++, mask >>= 1)
244 {
245 if (val & mask)
246 break;
247 }
248
249 rGPR[inst.RA] = i;
250
251 if (inst.Rc)
252 Helper_UpdateCR0(rGPR[inst.RA]);
253 }
254
eqvx(UGeckoInstruction inst)255 void Interpreter::eqvx(UGeckoInstruction inst)
256 {
257 rGPR[inst.RA] = ~(rGPR[inst.RS] ^ rGPR[inst.RB]);
258
259 if (inst.Rc)
260 Helper_UpdateCR0(rGPR[inst.RA]);
261 }
262
extsbx(UGeckoInstruction inst)263 void Interpreter::extsbx(UGeckoInstruction inst)
264 {
265 rGPR[inst.RA] = (u32)(s32)(s8)rGPR[inst.RS];
266
267 if (inst.Rc)
268 Helper_UpdateCR0(rGPR[inst.RA]);
269 }
270
extshx(UGeckoInstruction inst)271 void Interpreter::extshx(UGeckoInstruction inst)
272 {
273 rGPR[inst.RA] = (u32)(s32)(s16)rGPR[inst.RS];
274
275 if (inst.Rc)
276 Helper_UpdateCR0(rGPR[inst.RA]);
277 }
278
nandx(UGeckoInstruction _inst)279 void Interpreter::nandx(UGeckoInstruction _inst)
280 {
281 rGPR[_inst.RA] = ~(rGPR[_inst.RS] & rGPR[_inst.RB]);
282
283 if (_inst.Rc)
284 Helper_UpdateCR0(rGPR[_inst.RA]);
285 }
286
norx(UGeckoInstruction inst)287 void Interpreter::norx(UGeckoInstruction inst)
288 {
289 rGPR[inst.RA] = ~(rGPR[inst.RS] | rGPR[inst.RB]);
290
291 if (inst.Rc)
292 Helper_UpdateCR0(rGPR[inst.RA]);
293 }
294
orx(UGeckoInstruction inst)295 void Interpreter::orx(UGeckoInstruction inst)
296 {
297 rGPR[inst.RA] = rGPR[inst.RS] | rGPR[inst.RB];
298
299 if (inst.Rc)
300 Helper_UpdateCR0(rGPR[inst.RA]);
301 }
302
orcx(UGeckoInstruction inst)303 void Interpreter::orcx(UGeckoInstruction inst)
304 {
305 rGPR[inst.RA] = rGPR[inst.RS] | (~rGPR[inst.RB]);
306
307 if (inst.Rc)
308 Helper_UpdateCR0(rGPR[inst.RA]);
309 }
310
slwx(UGeckoInstruction inst)311 void Interpreter::slwx(UGeckoInstruction inst)
312 {
313 u32 amount = rGPR[inst.RB];
314 rGPR[inst.RA] = (amount & 0x20) ? 0 : rGPR[inst.RS] << (amount & 0x1f);
315
316 if (inst.Rc)
317 Helper_UpdateCR0(rGPR[inst.RA]);
318 }
319
srawx(UGeckoInstruction inst)320 void Interpreter::srawx(UGeckoInstruction inst)
321 {
322 int rb = rGPR[inst.RB];
323
324 if (rb & 0x20)
325 {
326 if (rGPR[inst.RS] & 0x80000000)
327 {
328 rGPR[inst.RA] = 0xFFFFFFFF;
329 PowerPC::SetCarry(1);
330 }
331 else
332 {
333 rGPR[inst.RA] = 0x00000000;
334 PowerPC::SetCarry(0);
335 }
336 }
337 else
338 {
339 int amount = rb & 0x1f;
340 s32 rrs = rGPR[inst.RS];
341 rGPR[inst.RA] = rrs >> amount;
342
343 PowerPC::SetCarry(rrs < 0 && amount > 0 && (u32(rrs) << (32 - amount)) != 0);
344 }
345
346 if (inst.Rc)
347 Helper_UpdateCR0(rGPR[inst.RA]);
348 }
349
srawix(UGeckoInstruction inst)350 void Interpreter::srawix(UGeckoInstruction inst)
351 {
352 int amount = inst.SH;
353
354 s32 rrs = rGPR[inst.RS];
355 rGPR[inst.RA] = rrs >> amount;
356
357 PowerPC::SetCarry(rrs < 0 && amount > 0 && (u32(rrs) << (32 - amount)) != 0);
358
359 if (inst.Rc)
360 Helper_UpdateCR0(rGPR[inst.RA]);
361 }
362
srwx(UGeckoInstruction inst)363 void Interpreter::srwx(UGeckoInstruction inst)
364 {
365 u32 amount = rGPR[inst.RB];
366 rGPR[inst.RA] = (amount & 0x20) ? 0 : (rGPR[inst.RS] >> (amount & 0x1f));
367
368 if (inst.Rc)
369 Helper_UpdateCR0(rGPR[inst.RA]);
370 }
371
tw(UGeckoInstruction inst)372 void Interpreter::tw(UGeckoInstruction inst)
373 {
374 s32 a = rGPR[inst.RA];
375 s32 b = rGPR[inst.RB];
376 s32 TO = inst.TO;
377
378 DEBUG_LOG(POWERPC, "tw rA %0x rB %0x TO %0x", a, b, TO);
379
380 if (((a < b) && (TO & 0x10)) || ((a > b) && (TO & 0x08)) || ((a == b) && (TO & 0x04)) ||
381 (((u32)a < (u32)b) && (TO & 0x02)) || (((u32)a > (u32)b) && (TO & 0x01)))
382 {
383 PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
384 PowerPC::CheckExceptions();
385 m_end_block = true; // Dunno about this
386 }
387 }
388
xorx(UGeckoInstruction inst)389 void Interpreter::xorx(UGeckoInstruction inst)
390 {
391 rGPR[inst.RA] = rGPR[inst.RS] ^ rGPR[inst.RB];
392
393 if (inst.Rc)
394 Helper_UpdateCR0(rGPR[inst.RA]);
395 }
396
HasAddOverflowed(u32 x,u32 y,u32 result)397 static bool HasAddOverflowed(u32 x, u32 y, u32 result)
398 {
399 // If x and y have the same sign, but the result is different
400 // then an overflow has occurred.
401 return (((x ^ result) & (y ^ result)) >> 31) != 0;
402 }
403
addx(UGeckoInstruction inst)404 void Interpreter::addx(UGeckoInstruction inst)
405 {
406 const u32 a = rGPR[inst.RA];
407 const u32 b = rGPR[inst.RB];
408 const u32 result = a + b;
409
410 rGPR[inst.RD] = result;
411
412 if (inst.OE)
413 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
414
415 if (inst.Rc)
416 Helper_UpdateCR0(result);
417 }
418
addcx(UGeckoInstruction inst)419 void Interpreter::addcx(UGeckoInstruction inst)
420 {
421 const u32 a = rGPR[inst.RA];
422 const u32 b = rGPR[inst.RB];
423 const u32 result = a + b;
424
425 rGPR[inst.RD] = result;
426 PowerPC::SetCarry(Helper_Carry(a, b));
427
428 if (inst.OE)
429 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
430
431 if (inst.Rc)
432 Helper_UpdateCR0(result);
433 }
434
addex(UGeckoInstruction inst)435 void Interpreter::addex(UGeckoInstruction inst)
436 {
437 const u32 carry = PowerPC::GetCarry();
438 const u32 a = rGPR[inst.RA];
439 const u32 b = rGPR[inst.RB];
440 const u32 result = a + b + carry;
441
442 rGPR[inst.RD] = result;
443 PowerPC::SetCarry(Helper_Carry(a, b) || (carry != 0 && Helper_Carry(a + b, carry)));
444
445 if (inst.OE)
446 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
447
448 if (inst.Rc)
449 Helper_UpdateCR0(result);
450 }
451
addmex(UGeckoInstruction inst)452 void Interpreter::addmex(UGeckoInstruction inst)
453 {
454 const u32 carry = PowerPC::GetCarry();
455 const u32 a = rGPR[inst.RA];
456 const u32 b = 0xFFFFFFFF;
457 const u32 result = a + b + carry;
458
459 rGPR[inst.RD] = result;
460 PowerPC::SetCarry(Helper_Carry(a, carry - 1));
461
462 if (inst.OE)
463 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
464
465 if (inst.Rc)
466 Helper_UpdateCR0(result);
467 }
468
addzex(UGeckoInstruction inst)469 void Interpreter::addzex(UGeckoInstruction inst)
470 {
471 const u32 carry = PowerPC::GetCarry();
472 const u32 a = rGPR[inst.RA];
473 const u32 result = a + carry;
474
475 rGPR[inst.RD] = result;
476 PowerPC::SetCarry(Helper_Carry(a, carry));
477
478 if (inst.OE)
479 PowerPC::SetXER_OV(HasAddOverflowed(a, 0, result));
480
481 if (inst.Rc)
482 Helper_UpdateCR0(result);
483 }
484
divwx(UGeckoInstruction inst)485 void Interpreter::divwx(UGeckoInstruction inst)
486 {
487 const s32 a = rGPR[inst.RA];
488 const s32 b = rGPR[inst.RB];
489 const bool overflow = b == 0 || (static_cast<u32>(a) == 0x80000000 && b == -1);
490
491 if (overflow)
492 {
493 if (a < 0)
494 rGPR[inst.RD] = UINT32_MAX;
495 else
496 rGPR[inst.RD] = 0;
497 }
498 else
499 {
500 rGPR[inst.RD] = static_cast<u32>(a / b);
501 }
502
503 if (inst.OE)
504 PowerPC::SetXER_OV(overflow);
505
506 if (inst.Rc)
507 Helper_UpdateCR0(rGPR[inst.RD]);
508 }
509
divwux(UGeckoInstruction inst)510 void Interpreter::divwux(UGeckoInstruction inst)
511 {
512 const u32 a = rGPR[inst.RA];
513 const u32 b = rGPR[inst.RB];
514 const bool overflow = b == 0;
515
516 if (overflow)
517 {
518 rGPR[inst.RD] = 0;
519 }
520 else
521 {
522 rGPR[inst.RD] = a / b;
523 }
524
525 if (inst.OE)
526 PowerPC::SetXER_OV(overflow);
527
528 if (inst.Rc)
529 Helper_UpdateCR0(rGPR[inst.RD]);
530 }
531
mulhwx(UGeckoInstruction inst)532 void Interpreter::mulhwx(UGeckoInstruction inst)
533 {
534 const s64 a = static_cast<s32>(rGPR[inst.RA]);
535 const s64 b = static_cast<s32>(rGPR[inst.RB]);
536 const u32 d = static_cast<u32>((a * b) >> 32);
537
538 rGPR[inst.RD] = d;
539
540 if (inst.Rc)
541 Helper_UpdateCR0(d);
542 }
543
mulhwux(UGeckoInstruction inst)544 void Interpreter::mulhwux(UGeckoInstruction inst)
545 {
546 const u64 a = rGPR[inst.RA];
547 const u64 b = rGPR[inst.RB];
548 const u32 d = static_cast<u32>((a * b) >> 32);
549
550 rGPR[inst.RD] = d;
551
552 if (inst.Rc)
553 Helper_UpdateCR0(d);
554 }
555
mullwx(UGeckoInstruction inst)556 void Interpreter::mullwx(UGeckoInstruction inst)
557 {
558 const s64 a = static_cast<s32>(rGPR[inst.RA]);
559 const s64 b = static_cast<s32>(rGPR[inst.RB]);
560 const s64 result = a * b;
561
562 rGPR[inst.RD] = static_cast<u32>(result);
563
564 if (inst.OE)
565 PowerPC::SetXER_OV(result < -0x80000000LL || result > 0x7FFFFFFFLL);
566
567 if (inst.Rc)
568 Helper_UpdateCR0(rGPR[inst.RD]);
569 }
570
negx(UGeckoInstruction inst)571 void Interpreter::negx(UGeckoInstruction inst)
572 {
573 const u32 a = rGPR[inst.RA];
574
575 rGPR[inst.RD] = (~a) + 1;
576
577 if (inst.OE)
578 PowerPC::SetXER_OV(a == 0x80000000);
579
580 if (inst.Rc)
581 Helper_UpdateCR0(rGPR[inst.RD]);
582 }
583
subfx(UGeckoInstruction inst)584 void Interpreter::subfx(UGeckoInstruction inst)
585 {
586 const u32 a = ~rGPR[inst.RA];
587 const u32 b = rGPR[inst.RB];
588 const u32 result = a + b + 1;
589
590 rGPR[inst.RD] = result;
591
592 if (inst.OE)
593 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
594
595 if (inst.Rc)
596 Helper_UpdateCR0(result);
597 }
598
subfcx(UGeckoInstruction inst)599 void Interpreter::subfcx(UGeckoInstruction inst)
600 {
601 const u32 a = ~rGPR[inst.RA];
602 const u32 b = rGPR[inst.RB];
603 const u32 result = a + b + 1;
604
605 rGPR[inst.RD] = result;
606 PowerPC::SetCarry(a == 0xFFFFFFFF || Helper_Carry(b, a + 1));
607
608 if (inst.OE)
609 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
610
611 if (inst.Rc)
612 Helper_UpdateCR0(result);
613 }
614
subfex(UGeckoInstruction inst)615 void Interpreter::subfex(UGeckoInstruction inst)
616 {
617 const u32 a = ~rGPR[inst.RA];
618 const u32 b = rGPR[inst.RB];
619 const u32 carry = PowerPC::GetCarry();
620 const u32 result = a + b + carry;
621
622 rGPR[inst.RD] = result;
623 PowerPC::SetCarry(Helper_Carry(a, b) || Helper_Carry(a + b, carry));
624
625 if (inst.OE)
626 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
627
628 if (inst.Rc)
629 Helper_UpdateCR0(result);
630 }
631
632 // sub from minus one
subfmex(UGeckoInstruction inst)633 void Interpreter::subfmex(UGeckoInstruction inst)
634 {
635 const u32 a = ~rGPR[inst.RA];
636 const u32 b = 0xFFFFFFFF;
637 const u32 carry = PowerPC::GetCarry();
638 const u32 result = a + b + carry;
639
640 rGPR[inst.RD] = result;
641 PowerPC::SetCarry(Helper_Carry(a, carry - 1));
642
643 if (inst.OE)
644 PowerPC::SetXER_OV(HasAddOverflowed(a, b, result));
645
646 if (inst.Rc)
647 Helper_UpdateCR0(result);
648 }
649
650 // sub from zero
subfzex(UGeckoInstruction inst)651 void Interpreter::subfzex(UGeckoInstruction inst)
652 {
653 const u32 a = ~rGPR[inst.RA];
654 const u32 carry = PowerPC::GetCarry();
655 const u32 result = a + carry;
656
657 rGPR[inst.RD] = result;
658 PowerPC::SetCarry(Helper_Carry(a, carry));
659
660 if (inst.OE)
661 PowerPC::SetXER_OV(HasAddOverflowed(a, 0, result));
662
663 if (inst.Rc)
664 Helper_UpdateCR0(result);
665 }
666