vladstamate wrote:it already showed issues, so I am fixing stuff now.
F000:00000457 B0 01 movb al,01
F000:00000459 BA 84 00 movw dx,0084
F000:0000045C EE out dx,al
F000:0000045D 66 B8 01 00 00 80 movd eax,80000001
F000:00000463 66 F7 E8 imuld eax
F000:00000466 66 B8 11 22 33 44 movd eax,44332211
F000:0000046C 66 89 C3 movd ebx,eax
F000:0000046F 66 B9 55 66 77 88 movd ecx,88776655
F000:00000475 66 F7 E1 muld ecx
00:01:34:77.07472: Interrupt 00=0000:00000000@F000:0478(F7); ERRORCODE: -1
F000:00000478 66 F7 F1 divd ecx
0000:00000000 00 00 addb [ds:bx+si],al
extern byte tmps,tmpp; //Sign/parity backup!
extern byte CPU_databussize; //Current data bus size!
extern byte tempAL;
uint_32 tempEAX;
uint_64 tempEDXEAX;
OPTINLINE void op_div32(uint_64 valdiv, uint_32 divisor) {
//word v1, v2;
if ((!divisor) && (CPU[activeCPU].internalinstructionstep==0)) //First step?
{
//Timings always!
++CPU[activeCPU].internalinstructionstep; //Next step after we're done!
CPU[activeCPU].cycles_OP += 1; //Take 1 cycle only!
CPU[activeCPU].executed = 0; //Not executed yet!
return;
}
uint_32 quotient, remainder; //Result and modulo!
byte error, applycycles; //Error/apply cycles!
CPU80386_internal_DIV(valdiv,divisor,"ient,&remainder,&error,32,2,6,&applycycles); //Execute the unsigned division! 8-bits result and modulo!
if (error==0) //No error?
{
REG_EAX = quotient; //Quotient!
REG_EDX = remainder; //Remainder!
}
else //Error?
{
CPU_exDIV0(); //Exception!
return; //Exception executed!
}
if (applycycles) /* No 80286+ cycles instead? */
{
if (MODRM_EA(params)) //Memory?
{
CPU[activeCPU].cycles_OP += 6 - EU_CYCLES_SUBSTRACT_ACCESSREAD; //Mem max!
}
}
}
//Universal DIV instruction for x86 DIV instructions!
/*
Parameters:
val: The value to divide
divisor: The value to divide by
quotient: Quotient result container
remainder: Remainder result container
error: 1 on error(DIV0), 0 when valid.
resultbits: The amount of bits the result contains(16 or 8 on 8086) of quotient and remainder.
SHLcycle: The amount of cycles for each SHL.
ADDSUBcycle: The amount of cycles for ADD&SUB instruction to execute.
*/
void CPU80386_internal_DIV(uint_64 val, uint_32 divisor, uint_32 *quotient, uint_32 *remainder, byte *error, byte resultbits, byte SHLcycle, byte ADDSUBcycle, byte *applycycles)
{
uint_64 temp, temp2, currentquotient; //Remaining value and current divisor!
byte shift; //The shift to apply! No match on 0 shift is done!
temp = val; //Load the value to divide!
*applycycles = 1; //Default: apply the cycles normally!
if (divisor==0) //Not able to divide?
{
*quotient = 0;
*remainder = temp; //Unable to comply!
*error = 1; //Divide by 0 error!
return; //Abort: division by 0!
}
if (CPU_apply286cycles()) /* No 80286+ cycles instead? */
{
SHLcycle = ADDSUBcycle = 0; //Don't apply the cycle counts for this instruction!
*applycycles = 0; //Don't apply the cycles anymore!
}
temp = val; //Load the remainder to use!
*quotient = 0; //Default: we have nothing after division!
nextstep:
//First step: calculate shift so that (divisor<<shift)<=remainder and ((divisor<<(shift+1))>remainder)
temp2 = divisor; //Load the default divisor for x1!
if (temp2>temp) //Not enough to divide? We're done!
{
goto gotresult; //We've gotten a result!
}
currentquotient = 1; //We're starting with x1 factor!
for (shift=0;shift<(resultbits+1);++shift) //Check for the biggest factor to apply(we're going from bit 0 to maxbit)!
{
if ((temp2<=temp) && ((temp2<<1)>temp)) //Found our value to divide?
{
CPU[activeCPU].cycles_OP += SHLcycle; //We're taking 1 more SHL cycle for this!
break; //We've found our shift!
}
temp2 <<= 1; //Shift to the next position!
currentquotient <<= 1; //Shift to the next result!
CPU[activeCPU].cycles_OP += SHLcycle; //We're taking 1 SHL cycle for this! Assuming parallel shifting!
}
if (shift==(resultbits+1)) //We've overflown? We're too large to divide!
{
*error = 1; //Raise divide by 0 error due to overflow!
return; //Abort!
}
//Second step: substract divisor<<n from remainder and increase result with 1<<n.
temp -= temp2; //Substract divisor<<n from remainder!
*quotient += currentquotient; //Increase result(divided value) with the found power of 2 (1<<n).
CPU[activeCPU].cycles_OP += ADDSUBcycle; //We're taking 1 substract and 1 addition cycle for this(ADD/SUB register take 3 cycles)!
goto nextstep; //Start the next step!
//Finished when remainder<divisor or remainder==0.
gotresult: //We've gotten a result!
if (temp>((1<<resultbits)-1)) //Modulo overflow?
{
*error = 1; //Raise divide by 0 error due to overflow!
return; //Abort!
}
if (*quotient>((1<<resultbits)-1)) //Quotient overflow?
{
*error = 1; //Raise divide by 0 error due to overflow!
return; //Abort!
}
*remainder = temp; //Give the modulo! The result is already calculated!
*error = 0; //We're having a valid result!
}
superfury wrote:Edit: It also doesn't seem the POST macro is being assembled, it resolves to no code being inserted? The conditional jump tests start immediately after CLI, the code "POST 0" isn't being assembled at all?
63 ;
64 ; We set our exception handlers at fixed addresses to simplify interrupt gate descriptor initialization.
65 ;
66 OFF_INTDEFAULT equ OFF_ERROR
67 OFF_INTDIVERR equ OFF_INTDEFAULT+0x200
68 OFF_INTPAGEFAULT equ OFF_INTDIVERR+0x200
69 OFF_INTBOUND equ OFF_INTPAGEFAULT+0x200
70
71 ;
72 ; Output a byte to the POST port, destroys al and dx
73 ;
74 %macro POST 1
75 mov al, 0x%1
76 mov dx, POST_PORT
77 out dx, al
78 %endmacro
79
80
81 header:
82 00000000 746573743338362E61- db COPYRIGHT
82 00000009 736D20284329203230-
82 00000012 31322D32303135204A-
82 0000001B 65666620506172736F-
82 00000024 6E732C202843292032-
82 0000002D 303137204D6172636F-
82 00000036 20426F72746F6C696E-
82 0000003F 202020202020
83
84 cpuTest:
85 00000045 FA cli
86
87
88 ; ==============================================================================
89 ; Real mode tests
90 ; ==============================================================================
91
92 ;
93 ; Conditional jumps
94 ;
95 %include "tests/jcc_m.asm"
1 <1> ;
2 <1> ; Tests conditional relative jumps.
3 <1> ; Uses: AX, ECX, Flags
4 <1> ;
5 <1> ; Opcodes tested, with positive and negative offsets:
6 <1> ;
7 <1> ; rel8 rel16/32 mnemonic condition
8 <1> ; 70 0F80 JO OF=1
9 <1> ; 71 0F81 JNO OF=0
10 <1> ; 72 0F82 JC CF=1
11 <1> ; 73 0F83 JNC CF=0
12 <1> ; 74 0F84 JZ ZF=1
13 <1> ; 75 0F85 JNZ ZF=0
14 <1> ; 76 0F86 JBE CF=1 || ZF=1
15 <1> ; 77 0F87 JA CF=0 && ZF=0
16 <1> ; 78 0F88 JS SF=1
17 <1> ; 79 0F89 JNS SF=0
18 <1> ; 7A 0F8A JP PF=1
19 <1> ; 7B 0F8B JNP PF=0
20 <1> ; 7C 0F8C JL SF!=OF
21 <1> ; 7D 0F8D JNL SF=OF
22 <1> ; 7E 0F8E JLE ZF=1 || SF!=OF
23 <1> ; 7F 0F8F JNLE ZF=0 && SF=OF
24 <1> ; E3 JCXZ CX=0
25 <1> ; E3 JECXZ ECX=0
26 <1> ;
27 <1> %macro testJcc 1
28 <1> mov ah, PS_CF
29 <1> sahf ; don't use the stack (pushf/popf)
30 <1> jnc %%err1 ; 73 / 0F83 JNC CF=0
31 <1> jc %%jcok ; 72 / 0F82 JC CF=1
32 <1> hlt
33 <1> %%jz:
34 <1> mov ah, PS_ZF
35 <1> sahf
36 <1> jnz %%err1 ; 75 / 0F85 JNZ ZF=0
37 <1> jz %%jzok ; 74 / 0F84 JZ ZF=1
38 <1> hlt
39 <1> %%jp:
40 <1> mov ah, PS_PF
41 <1> sahf
42 <1> jnp %%err1 ; 7B / 0F8B JNP PF=0
43 <1> jp %%jpok ; 7A / 0F8A JP PF=1
44 <1> hlt
45 <1> %%js:
46 <1> mov ah, PS_SF
47 <1> sahf
48 <1> jns %%err1 ; 79 / 0F89 JNS SF=0
49 <1> js %%jsok ; 78 / 0F88 JS SF=1
50 <1> hlt
51 <1> %%jna:
52 <1> mov ah, PS_ZF|PS_CF
53 <1> sahf
54 <1> ja %%err1 ; 77 / 0F87 JA CF=0 && ZF=0
55 <1> jna %%jnaok ; 76 / 0F86 JBE CF=1 || ZF=1
56 <1> %%next1:
57 <1> jmp %%jnc
58 <1>
59 <1> %if %1==16
60 <1> times 128 hlt
61 <1> %endif
62 <1>
63 <1> %%err1:
64 <1> hlt
65 <1>
66 <1> ; test negative offsets
67 <1> %%jcok: jc %%jz
68 <1> %%jzok: jz %%jp
69 <1> %%jpok: jp %%js
70 <1> %%jsok: js %%jna
71 <1> %%jnaok: jna %%next1
72 <1>
testLEA32 [eax * 2], 0x00000002
testLEA32 [ebx * 4], 0x00000008
0010:00000F96 50 pushd eax
0010:00000F97 8D 04 00 lead eax,[ds:eax+eax*1]
0010:00000F9A 83 F8 02 cmpd eax,0002
0010:00000F9D 0F 85 5D B0 00 00 jne 0000c000
0010:00000FA3 58 popd eax
0010:00000FA4 50 pushd eax
0010:00000FA5 8D 04 9D lead eax,[ds:00000000+ebx*4]
0010:00000FA8 00 00 addb [ds:eax],al
0010:00000FAA 00 00 addb [ds:eax],al
0010:00000FAC 83 F8 08 cmpd eax,0008
0010:00000FAF 0F 85 4B B0 00 00 jne 0000c000
0010:00000FB5 58 popd eax
0010:00000FB6 50 pushd eax
0010:00000FB7 8D 04 CD lead eax,[ds:00000000+ecx*8]
0010:00000FBA 00 00 addb [ds:eax],al
0010:00000FBC 00 00 addb [ds:eax],al
0010:00000FBE 83 F8 20 cmpd eax,0020
0010:00000FC1 0F 85 39 B0 00 00 jne 0000c000
0010:00000FC7 58 popd eax
0010:00000FC8 50 pushd eax
0010:00000FC9 8D 44 00 40 lead eax,[ds:40+eax+eax*1]
0010:00000FCD 83 F8 42 cmpd eax,0042
0010:00000FD0 0F 85 2A B0 00 00 jne 0000c000
0010:00000FD6 58 popd eax
0010:00000FD7 50 pushd eax
0010:00000FD8 8D 04 9D lead eax,[ds:00000000+ebx*4]
0010:00000FDB 40 incd eax
0010:00000FDC 00 00 addb [ds:eax],al
00:10:11:29.04144: #GP fault(00000018)!
0010:00000FDE 00 83 F8 48 0F 85 addb [ds:ebx+850f48f8],al
0010:0000C000 FA cli
0010:0000C001 F4 hlt
0010:0000C002 F4 <hlt>
peterferrie wrote:This tester needs some of the corner cases. I shall make a PR for them.
peterferrie wrote:This tester needs some of the corner cases. I shall make a PR for them.
Users browsing this forum: No registered users and 4 guests