@@ -34,6 +34,8 @@ public override ushort And(ushort value1, ushort value2) {
3434 UpdateFlags ( res ) ;
3535 _state . CarryFlag = false ;
3636 _state . OverflowFlag = false ;
37+ // Undocumented: real CPUs clear AF for logical operations
38+ _state . AuxiliaryFlag = false ;
3739 return res ;
3840 }
3941
@@ -71,6 +73,8 @@ public override int Imul(short value1, short value2) {
7173 bool doesNotFitInWord = res != ( short ) res ;
7274 _state . OverflowFlag = doesNotFitInWord ;
7375 _state . CarryFlag = doesNotFitInWord ;
76+ UpdateFlags ( ( ushort ) res ) ;
77+ _state . AuxiliaryFlag = false ;
7478 return res ;
7579 }
7680
@@ -94,8 +98,14 @@ public override ushort Or(ushort value1, ushort value2) {
9498 }
9599
96100 public override ushort Rcl ( ushort value , byte count ) {
97- count = ( byte ) ( ( count & ShiftCountMask ) % 17 ) ;
101+ int maskedCount = count & ShiftCountMask ;
102+ if ( maskedCount == 0 ) {
103+ return value ;
104+ }
105+
106+ count = ( byte ) ( maskedCount % 17 ) ;
98107 if ( count == 0 ) {
108+ _state . OverflowFlag = _state . CarryFlag ^ ( ( value & MsbMask ) != 0 ) ;
99109 return value ;
100110 }
101111
@@ -115,8 +125,14 @@ public override ushort Rcl(ushort value, byte count) {
115125 }
116126
117127 public override ushort Rcr ( ushort value , int count ) {
118- count = ( count & ShiftCountMask ) % 17 ;
128+ int maskedCount = count & ShiftCountMask ;
129+ if ( maskedCount == 0 ) {
130+ return value ;
131+ }
132+
133+ count = maskedCount % 17 ;
119134 if ( count == 0 ) {
135+ SetOverflowForRigthRotate16 ( value ) ;
120136 return value ;
121137 }
122138
@@ -135,31 +151,30 @@ public override ushort Rcr(ushort value, int count) {
135151 }
136152
137153 public override ushort Rol ( ushort value , byte count ) {
138- count = ( byte ) ( ( count & ShiftCountMask ) % 16 ) ;
139- if ( count == 0 ) {
154+ int maskedCount = count & ShiftCountMask ;
155+ if ( maskedCount == 0 ) {
140156 return value ;
141157 }
142-
143- int carry = value >> 16 - count & 0x1 ;
144- ushort res = ( ushort ) ( value << count ) ;
145- res = ( ushort ) ( res | value >> 16 - count ) ;
146- _state . CarryFlag = carry != 0 ;
158+ int effective = maskedCount % 16 ;
159+ ushort res = effective == 0
160+ ? value
161+ : ( ushort ) ( ( value << effective ) | ( value >> 16 - effective ) ) ;
162+ _state . CarryFlag = ( res & 0x1 ) != 0 ;
147163 bool msb = ( res & MsbMask ) != 0 ;
148164 bool lsb = ( res & 0x01 ) != 0 ;
149165 _state . OverflowFlag = msb ^ lsb ;
150166 return res ;
151167 }
152168 public override ushort Ror ( ushort value , int count ) {
153- count = ( count & ShiftCountMask ) % 16 ;
154- if ( count == 0 ) {
169+ int maskedCount = count & ShiftCountMask ;
170+ if ( maskedCount == 0 ) {
155171 return value ;
156172 }
157-
158- int carry = value >> count - 1 & 0x1 ;
159- int mask = ( 1 << 16 - count ) - 1 ;
160- ushort res = ( ushort ) ( value >> count & mask ) ;
161- res = ( ushort ) ( res | value << 16 - count ) ;
162- _state . CarryFlag = carry != 0 ;
173+ int effective = maskedCount % 16 ;
174+ ushort res = effective == 0
175+ ? value
176+ : ( ushort ) ( ( value >> effective ) | ( value << 16 - effective ) ) ;
177+ _state . CarryFlag = ( res & MsbMask ) != 0 ;
163178 SetOverflowForRigthRotate16 ( res ) ;
164179 return res ;
165180 }
@@ -188,23 +203,28 @@ public override ushort Shl(ushort value, int count) {
188203 _state . CarryFlag = msbBefore != 0 ;
189204 ushort res = ( ushort ) ( value << count ) ;
190205 UpdateFlags ( res ) ;
191- _state . OverflowFlag = ( ( res ^ value ) & MsbMask ) != 0 ;
206+ // See Alu8.Shl for the OF derivation rationale.
207+ _state . OverflowFlag = ( ( res & MsbMask ) != 0 ) ^ _state . CarryFlag ;
192208 return res ;
193209 }
194210
195211 public override ushort Shld ( ushort destination , ushort source , byte count ) {
196212 count &= ShiftCountMask ;
197- switch ( count ) {
198- case 0 :
199- return destination ;
200- case > 16 :
201- // Undefined. We shift the source in again.
202- return ( ushort ) ( source << ( count - 16 ) ) ;
213+ if ( count == 0 ) {
214+ return destination ;
203215 }
204216
217+ // Real 386 behavior: for count <= 16 the documented SHLD formula applies;
218+ // for count > 16 (the 5-bit mask allows up to 31) the destination is fully
219+ // shifted out and the result equals ROL16(source, count - 16). Both branches
220+ // are expressed as a 32-bit ROL on a paired value, taking the upper 16 bits.
221+ uint combined = count > 16
222+ ? ( ( uint ) source << 16 ) | source
223+ : ( ( uint ) destination << 16 ) | source ;
224+ uint rotated = ( combined << count ) | ( combined >> ( 32 - count ) ) ;
205225 ushort msbBefore = ( ushort ) ( destination & MsbMask ) ;
206- _state . CarryFlag = ( destination >> ( 16 - count ) & 1 ) != 0 ;
207- ushort res = ( ushort ) ( ( destination << count ) | ( source >> ( 16 - count ) ) ) ;
226+ _state . CarryFlag = ( ( combined >> ( 32 - count ) ) & 1 ) != 0 ;
227+ ushort res = ( ushort ) ( rotated >> 16 ) ;
208228 UpdateFlags ( res ) ;
209229 ushort msb = ( ushort ) ( res & MsbMask ) ;
210230 _state . OverflowFlag = msb != msbBefore ;
@@ -217,22 +237,16 @@ public override ushort Shrd(ushort destination, ushort source, byte count) {
217237 return destination ;
218238 }
219239
240+ // Mirror of SHLD: for count > 16 the destination is fully shifted out and
241+ // the result equals ROR16(source, count - 16). Expressed as a 32-bit ROR
242+ // on a paired value, taking the lower 16 bits.
243+ uint combined = count > 16
244+ ? ( ( uint ) source << 16 ) | source
245+ : ( ( uint ) source << 16 ) | destination ;
246+ uint rotated = ( combined >> count ) | ( combined << ( 32 - count ) ) ;
220247 ushort msbBefore = ( ushort ) ( destination & MsbMask ) ;
221- ushort res ;
222-
223- if ( count > 16 ) {
224- // Undefined. We shift the source in again (opposite direction of SHLD).
225- int shiftFromSource = count - 16 ;
226- res = ( ushort ) ( source >> shiftFromSource ) ;
227-
228- // Carry flag is the last bit shifted out of the 32-bit concatenation.
229- // For count > 16, this is bit (count - 17) of the source.
230- _state . CarryFlag = ( ( source >> ( count - 17 ) ) & 1 ) != 0 ;
231- } else {
232- _state . CarryFlag = ( ( destination >> ( count - 1 ) ) & 1 ) != 0 ;
233- res = ( ushort ) ( ( destination >> count ) | ( source << ( 16 - count ) ) ) ;
234- }
235-
248+ _state . CarryFlag = ( ( combined >> ( count - 1 ) ) & 1 ) != 0 ;
249+ ushort res = ( ushort ) rotated ;
236250 UpdateFlags ( res ) ;
237251 ushort msb = ( ushort ) ( res & MsbMask ) ;
238252 _state . OverflowFlag = msb != msbBefore ;
@@ -270,6 +284,8 @@ public override ushort Xor(ushort value1, ushort value2) {
270284 UpdateFlags ( res ) ;
271285 _state . CarryFlag = false ;
272286 _state . OverflowFlag = false ;
287+ // Undocumented: real CPUs clear AF for logical operations
288+ _state . AuxiliaryFlag = false ;
273289 return res ;
274290 }
275291
0 commit comments