mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:22:46 +00:00 
			
		
		
		
	UserspaceEmulator: Fix buggy IDIV instructions
These were not doing mashing together the signed double-size results correctly and lost bits in the signed/unsigned casting process.
This commit is contained in:
		
							parent
							
								
									9e6d002660
								
							
						
					
					
						commit
						e4b068aec5
					
				
					 1 changed files with 24 additions and 7 deletions
				
			
		|  | @ -1257,18 +1257,35 @@ void SoftCPU::ESCAPE(const X86::Instruction&) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SoftCPU::HLT(const X86::Instruction&) { TODO(); } | void SoftCPU::HLT(const X86::Instruction&) { TODO(); } | ||||||
| void SoftCPU::IDIV_RM16(const X86::Instruction&) { TODO(); } |  | ||||||
| 
 | 
 | ||||||
| void SoftCPU::IDIV_RM32(const X86::Instruction& insn) | void SoftCPU::IDIV_RM16(const X86::Instruction& insn) | ||||||
| { | { | ||||||
|     auto divisor = insn.modrm().read32(*this, insn); |     auto divisor = (i16)insn.modrm().read16(*this, insn); | ||||||
|     if (divisor == 0) { |     if (divisor == 0) { | ||||||
|         warn() << "Divide by zero"; |         warn() << "Divide by zero"; | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
|     i64 dividend = ((i64)edx() << 32) | eax(); |     i32 dividend = (i32)(((u32)dx() << 16) | (u32)ax()); | ||||||
|     auto result = dividend / divisor; |     i32 result = dividend / divisor; | ||||||
|     if (result > NumericLimits<i32>::max()) { |     if (result > NumericLimits<i16>::max() || result < NumericLimits<i16>::min()) { | ||||||
|  |         warn() << "Divide overflow"; | ||||||
|  |         TODO(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     set_ax(result); | ||||||
|  |     set_dx(dividend % divisor); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SoftCPU::IDIV_RM32(const X86::Instruction& insn) | ||||||
|  | { | ||||||
|  |     auto divisor = (i32)insn.modrm().read32(*this, insn); | ||||||
|  |     if (divisor == 0) { | ||||||
|  |         warn() << "Divide by zero"; | ||||||
|  |         TODO(); | ||||||
|  |     } | ||||||
|  |     i64 dividend = (i64)(((u64)edx() << 32) | (u64)eax()); | ||||||
|  |     i64 result = dividend / divisor; | ||||||
|  |     if (result > NumericLimits<i32>::max() || result < NumericLimits<i32>::min()) { | ||||||
|         warn() << "Divide overflow"; |         warn() << "Divide overflow"; | ||||||
|         TODO(); |         TODO(); | ||||||
|     } |     } | ||||||
|  | @ -1279,7 +1296,7 @@ void SoftCPU::IDIV_RM32(const X86::Instruction& insn) | ||||||
| 
 | 
 | ||||||
| void SoftCPU::IDIV_RM8(const X86::Instruction& insn) | void SoftCPU::IDIV_RM8(const X86::Instruction& insn) | ||||||
| { | { | ||||||
|     auto divisor = (i16)insn.modrm().read8(*this, insn); |     auto divisor = (i8)insn.modrm().read8(*this, insn); | ||||||
|     if (divisor == 0) { |     if (divisor == 0) { | ||||||
|         warn() << "Divide by zero"; |         warn() << "Divide by zero"; | ||||||
|         TODO(); |         TODO(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling