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