From 6b7808e412ca9db41ac194a0a0e35d515cb1d38a Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 24 Dec 2014 07:56:57 -0500
Subject: [PATCH] armemu: Fix GE/Q flag setting semantics

---
 src/core/arm/interpreter/armemu.cpp | 118 +++++++++++++---------------
 1 file changed, 56 insertions(+), 62 deletions(-)

diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index b2f671f94..c4c09d1fb 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -5863,22 +5863,21 @@ L_stm_s_takeabort:
                 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
 
                 if (lo_result >= 0) {
-                    state->Cpsr |= (1 << 16);
-                    state->Cpsr |= (1 << 17);
+                    state->GEFlag |= (1 << 16);
+                    state->GEFlag |= (1 << 17);
                 } else {
-                    state->Cpsr &= ~(1 << 16);
-                    state->Cpsr &= ~(1 << 17);
+                    state->GEFlag &= ~(1 << 16);
+                    state->GEFlag &= ~(1 << 17);
                 }
 
                 if (hi_result >= 0) {
-                    state->Cpsr |= (1 << 18);
-                    state->Cpsr |= (1 << 19);
+                    state->GEFlag |= (1 << 18);
+                    state->GEFlag |= (1 << 19);
                 } else {
-                    state->Cpsr &= ~(1 << 18);
-                    state->Cpsr &= ~(1 << 19);
+                    state->GEFlag &= ~(1 << 18);
+                    state->GEFlag &= ~(1 << 19);
                 }
 
-                ARMul_CPSRAltered(state);
                 return 1;
             }
             // SADD8/SSUB8
@@ -5903,24 +5902,24 @@ L_stm_s_takeabort:
                     hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF));
 
                     if (lo_val1 & 0x80)
-                        state->Cpsr |= (1 << 16);
+                        state->GEFlag |= (1 << 16);
                     else
-                        state->Cpsr &= ~(1 << 16);
+                        state->GEFlag &= ~(1 << 16);
 
                     if (lo_val2 & 0x80)
-                        state->Cpsr |= (1 << 17);
+                        state->GEFlag |= (1 << 17);
                     else
-                        state->Cpsr &= ~(1 << 17);
+                        state->GEFlag &= ~(1 << 17);
 
                     if (hi_val1 & 0x80)
-                        state->Cpsr |= (1 << 18);
+                        state->GEFlag |= (1 << 18);
                     else
-                        state->Cpsr &= ~(1 << 18);
+                        state->GEFlag &= ~(1 << 18);
 
                     if (hi_val2 & 0x80)
-                        state->Cpsr |= (1 << 19);
+                        state->GEFlag |= (1 << 19);
                     else
-                        state->Cpsr &= ~(1 << 19);
+                        state->GEFlag &= ~(1 << 19);
                 }
                 // SSUB8
                 else {
@@ -5930,27 +5929,26 @@ L_stm_s_takeabort:
                     hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
 
                     if (!(lo_val1 & 0x80))
-                        state->Cpsr |= (1 << 16);
+                        state->GEFlag |= (1 << 16);
                     else
-                        state->Cpsr &= ~(1 << 16);
+                        state->GEFlag &= ~(1 << 16);
 
                     if (!(lo_val2 & 0x80))
-                        state->Cpsr |= (1 << 17);
+                        state->GEFlag |= (1 << 17);
                     else
-                        state->Cpsr &= ~(1 << 17);
+                        state->GEFlag &= ~(1 << 17);
 
                     if (!(hi_val1 & 0x80))
-                        state->Cpsr |= (1 << 18);
+                        state->GEFlag |= (1 << 18);
                     else
-                        state->Cpsr &= ~(1 << 18);
+                        state->GEFlag &= ~(1 << 18);
 
                     if (!(hi_val2 & 0x80))
-                        state->Cpsr |= (1 << 19);
+                        state->GEFlag |= (1 << 19);
                     else
-                        state->Cpsr &= ~(1 << 19);
+                        state->GEFlag &= ~(1 << 19);
                 }
 
-                ARMul_CPSRAltered(state);
                 state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24);
                 return 1;
             }
@@ -6029,31 +6027,30 @@ L_stm_s_takeabort:
                     h2 = ((u16)(from >> 16) - (u16)(to >> 16));
 
                     if (!(h1 & 0xffff0000))
-                        state->Cpsr |= (3 << 16);
+                        state->GEFlag |= (3 << 16);
                     else
-                        state->Cpsr &= ~(3 << 16);
+                        state->GEFlag &= ~(3 << 16);
 
                     if (!(h2 & 0xffff0000))
-                        state->Cpsr |= (3 << 18);
+                        state->GEFlag |= (3 << 18);
                     else
-                        state->Cpsr &= ~(3 << 18);
+                        state->GEFlag &= ~(3 << 18);
                 }
                 else { // UADD16
                     h1 = ((u16)from + (u16)to);
                     h2 = ((u16)(from >> 16) + (u16)(to >> 16));
 
                     if (h1 & 0xffff0000)
-                        state->Cpsr |= (3 << 16);
+                        state->GEFlag |= (3 << 16);
                     else
-                        state->Cpsr &= ~(3 << 16);
+                        state->GEFlag &= ~(3 << 16);
 
                     if (h2 & 0xffff0000)
-                        state->Cpsr |= (3 << 18);
+                        state->GEFlag |= (3 << 18);
                     else
-                        state->Cpsr &= ~(3 << 18);
+                        state->GEFlag &= ~(3 << 18);
                 }
 
-                ARMul_CPSRAltered(state);
                 state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16));
                 return 1;
             }
@@ -6068,24 +6065,24 @@ L_stm_s_takeabort:
                         b4 = ((u8)(from >> 24) - (u8)(to >> 24));
 
                         if (!(b1 & 0xffffff00))
-                            state->Cpsr |= (1 << 16);
+                            state->GEFlag |= (1 << 16);
                         else
-                            state->Cpsr &= ~(1 << 16);
+                            state->GEFlag &= ~(1 << 16);
 
                         if (!(b2 & 0xffffff00))
-                            state->Cpsr |= (1 << 17);
+                            state->GEFlag |= (1 << 17);
                         else
-                            state->Cpsr &= ~(1 << 17);
+                            state->GEFlag &= ~(1 << 17);
 
                         if (!(b3 & 0xffffff00))
-                            state->Cpsr |= (1 << 18);
+                            state->GEFlag |= (1 << 18);
                         else
-                            state->Cpsr &= ~(1 << 18);
+                            state->GEFlag &= ~(1 << 18);
 
                         if (!(b4 & 0xffffff00))
-                            state->Cpsr |= (1 << 19);
+                            state->GEFlag |= (1 << 19);
                         else
-                            state->Cpsr &= ~(1 << 19);
+                            state->GEFlag &= ~(1 << 19);
                     }
                     else { // UADD8
                         b1 = ((u8)from + (u8)to);
@@ -6094,27 +6091,26 @@ L_stm_s_takeabort:
                         b4 = ((u8)(from >> 24) + (u8)(to >> 24));
 
                         if (b1 & 0xffffff00)
-                            state->Cpsr |= (1 << 16);
+                            state->GEFlag |= (1 << 16);
                         else
-                            state->Cpsr &= ~(1 << 16);
+                            state->GEFlag &= ~(1 << 16);
 
                         if (b2 & 0xffffff00)
-                            state->Cpsr |= (1 << 17);
+                            state->GEFlag |= (1 << 17);
                         else
-                            state->Cpsr &= ~(1 << 17);
+                            state->GEFlag &= ~(1 << 17);
 
                         if (b3 & 0xffffff00)
-                            state->Cpsr |= (1 << 18);
+                            state->GEFlag |= (1 << 18);
                         else
-                            state->Cpsr &= ~(1 << 18);
+                            state->GEFlag &= ~(1 << 18);
 
                         if (b4 & 0xffffff00)
-                            state->Cpsr |= (1 << 19);
+                            state->GEFlag |= (1 << 19);
                         else
-                            state->Cpsr &= ~(1 << 19);
+                            state->GEFlag &= ~(1 << 19);
                     }
 
-                    ARMul_CPSRAltered(state);
                     state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24);
                     return 1;
                 }
@@ -6211,21 +6207,20 @@ L_stm_s_takeabort:
 
 					if (rn_lo > max) {
 						rn_lo = max;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					} else if (rn_lo < min) {
 						rn_lo = min;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					}
 
 					if (rn_hi > max) {
 						rn_hi = max;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					} else if (rn_hi < min) {
 						rn_hi = min;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					}
 
-					ARMul_CPSRAltered(state);
 					state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
 					return 1;
 				}
@@ -6359,21 +6354,20 @@ L_stm_s_takeabort:
 					
 					if (max < rn_lo) {
 						rn_lo = max;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					} else if (rn_lo < 0) {
 						rn_lo = 0;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					}
 
 					if (max < rn_hi) {
 						rn_hi = max;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					} else if (rn_hi < 0) {
 						rn_hi = 0;
-						state->Cpsr |= (1 << 27);
+						SETQ;
 					}
 
-					ARMul_CPSRAltered(state);
 					state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);
 					return 1;
 				}