diff mbox

Re: sparc32 FPU SP Invalid CEXC Test

Message ID j2wf43fc5581004151048h67d81fe8r6aa486fa7da083dd@mail.gmail.com
State New
Headers show

Commit Message

Blue Swirl April 15, 2010, 5:48 p.m. UTC
On 4/15/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>
> > One of LX's tests crashes pretty hard, causing qemu abort.
>  > I've tried to look how does the execution flow works with -d in_asm.
>  > Does the address in the log show the guest's PC register?
>
>
> It's probably sort of a "timing" issue.
>
>  Can we check exceptions not just on jumps, but also on floating poit
>  operations which may cause a trap?
>  These traps are supposed to be syncronous.

Yes, the bug is that PC and NPC are not saved before executing FPU
instructions. Please try this patch.

Comments

Artyom Tarasenko April 15, 2010, 8:53 p.m. UTC | #1
2010/4/15 Blue Swirl <blauwirbel@gmail.com>:
> On 4/15/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
>> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>>
>> > One of LX's tests crashes pretty hard, causing qemu abort.
>>  > I've tried to look how does the execution flow works with -d in_asm.
>>  > Does the address in the log show the guest's PC register?
>>
>>
>> It's probably sort of a "timing" issue.
>>
>>  Can we check exceptions not just on jumps, but also on floating poit
>>  operations which may cause a trap?
>>  These traps are supposed to be syncronous.
>
> Yes, the bug is that PC and NPC are not saved before executing FPU
> instructions. Please try this patch.

The patch gets it a couple of tests further:

FPU SP Invalid CEXC Test
FPU SP Overflow CEXC Test
FPU SP Divide-by-0 CEXC Test
FPU SP Inexact CEXC Test
FPU SP Trap Priority >  Test Unassigned mem write access of 4 bytes to
000000008421f000 from 700030f8

FPU SP Trap Priority <  Test
     ERROR : Unexpected Synchronous Trap Taken, Trap Type = 00000008,
PSR = 414010c4, PC = 70003190, TBR = 00000080
     STATUS : Entering scope loop .... Press <A> key to Abort!qemu:
fatal: Trap 0x03 while interrupts disabled, Error state
pc: 0000217c  npc: 00003170
General Registers:
%g0-7: 00000000 00003170 00000055 00000001 00000002 00000000 00000000 00000000

Current Register Window:
%o0-7: 00000000 00000999 00000000 00000000 00000000 00000000 0001fba0 7000971c
%l0-7: 0002fff8 00000000 00000000 00000000 00000000 ffffffff 00000000 00000000
%i0-7: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Floating Point Registers:
%f00: 000000002.890625 000000025.000000 000000000.000000 000000000.000000
%f04: 000000002.890625 000000000.000000 000000002.890625 000000000.000000
%f08: 000000003.390625 000000000.000000 000000002.250000 000000000.000000
%f12: 000000002.890625 000000000.000000 000000002.312500 000000000.000000
%f16: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
%f20: 000000002.718750 000000000.000000 000000002.562500 000000000.000000
%f24: 000000002.890625 000000000.000000 000000002.968750 000000000.000000
%f28: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
psr: 41000000 (icc: ---- SPE: ---) wim: 00000002
fsr: 0f884002 y: 00000000
Aborted


The code:

   0x70003174:  sethi  %hi(0x41c80000), %l3
   0x70003178:  add  %l4, 2, %l5
   0x7000317c:  st  %l3, [ %l4 ]
   0x70003180:  ld  [ %l4 ], %f1
   0x70003184:  clr  [ %l4 ]
   0x70003188:  ld  [ %l4 ], %f2
   0x7000318c:  mov  7, %g5
   0x70003190:  fdivs  %f1, %f2, %f3
   0x70003194:  st  %f3, [ %l5 ]
   0x70003198:  nop

Is it a test for MMU trap inside of  fpu trap?
qemu.log:

0x70003190:  fdivs  %f1, %f2, %f3
--------------
IN:
0x00000080:  sethi  %hi(0x1c00), %l4
0x00000084:  or  %l4, 0x324, %l4        ! 0x1f24
0x00000088:  jmp  %l4
0x0000008c:  rd  %psr, %l0
--------------
IN:
0x00001f24:  rd  %tbr, %l3
0x00001f28:  srl  %l3, 4, %l3
0x00001f2c:  and  %l3, 0xff, %l3
0x00001f30:  cmp  %l3, %g5
0x00001f34:  bne,a   0x2044
--------------
IN:
0x00001f38:  nop
--------------
IN:
0x00002044:  sethi  %hi(0x10001000), %l5
0x00002048:  or  %l5, 4, %l5    ! 0x10001004
0x0000204c:  lda  [ %l5 ] #ASI_M_BYPASS, %l7
0x00002050:  sethi  %hi(0x10001000), %l4
0x00002054:  lda  [ %l4 ] #ASI_M_BYPASS, %l6
0x00002058:  sethi  %hi(0x80000000), %l5
0x0000205c:  btst  %l6, %l5
0x00002060:  be  0x20bc
0x00002064:  nop

--------------
IN:
0x000020bc:  mov  0x400, %l5    ! 0x400
0x000020c0:  lda  [ %l5 ] #ASI_M_MMUREGS, %l7
0x000020c4:  nop
0x000020c8:  mov  0x300, %l4    ! 0x300
0x000020cc:  lda  [ %l4 ] #ASI_M_MMUREGS, %l6
0x000020d0:  sethi  %hi(0x7c00), %l5
0x000020d4:  or  %l5, 0x1c, %l5 ! 0x7c1c
0x000020d8:  btst  %l6, %l5
0x000020dc:  be  0x2134
0x000020e0:  nop

--------------
IN:
0x00002134:  sethi  %hi(0x8400), %i0


The "Trap Priority >" test (which passed) also produced some
interesting qemu.log:


0x700030f4:  fdivs  %f1, %f2, %f3
0x700030f8:  st  %f3, [ %l6 ]
0x700030fc:  nop
0x70003100:  cmp  %g0, %g5
0x70003104:  bne,a   0x70003a1c

--------------
IN:
0x00000080:  sethi  %hi(0x1c00), %l4

############## Here, double trap?!
--------------
IN:
0x00000080:  sethi  %hi(0x1c00), %l4

--------------
IN:
0x00000084:  or  %l4, 0x324, %l4        ! 0x1f24
0x00000088:  jmp  %l4
0x0000008c:  rd  %psr, %l0

--------------
IN:
0x00001f24:  rd  %tbr, %l3
0x00001f28:  srl  %l3, 4, %l3
0x00001f2c:  and  %l3, 0xff, %l3
0x00001f30:  cmp  %l3, %g5
Artyom Tarasenko April 16, 2010, 2:37 p.m. UTC | #2
2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
> 2010/4/15 Blue Swirl <blauwirbel@gmail.com>:
>> On 4/15/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
>>> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>>>
>>> > One of LX's tests crashes pretty hard, causing qemu abort.
>>>  > I've tried to look how does the execution flow works with -d in_asm.
>>>  > Does the address in the log show the guest's PC register?
>>>
>>>
>>> It's probably sort of a "timing" issue.
>>>
>>>  Can we check exceptions not just on jumps, but also on floating poit
>>>  operations which may cause a trap?
>>>  These traps are supposed to be syncronous.
>>
>> Yes, the bug is that PC and NPC are not saved before executing FPU
>> instructions. Please try this patch.
>
> The patch gets it a couple of tests further:
>
> FPU SP Invalid CEXC Test
> FPU SP Overflow CEXC Test
> FPU SP Divide-by-0 CEXC Test
> FPU SP Inexact CEXC Test
> FPU SP Trap Priority >  Test Unassigned mem write access of 4 bytes to
> 000000008421f000 from 700030f8
>
> FPU SP Trap Priority <  Test
>     ERROR : Unexpected Synchronous Trap Taken, Trap Type = 00000008,
> PSR = 414010c4, PC = 70003190, TBR = 00000080
>     STATUS : Entering scope loop .... Press <A> key to Abort!qemu:
> fatal: Trap 0x03 while interrupts disabled, Error state
> pc: 0000217c  npc: 00003170
> General Registers:
> %g0-7: 00000000 00003170 00000055 00000001 00000002 00000000 00000000 00000000
>
> Current Register Window:
> %o0-7: 00000000 00000999 00000000 00000000 00000000 00000000 0001fba0 7000971c
> %l0-7: 0002fff8 00000000 00000000 00000000 00000000 ffffffff 00000000 00000000
> %i0-7: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>
> Floating Point Registers:
> %f00: 000000002.890625 000000025.000000 000000000.000000 000000000.000000
> %f04: 000000002.890625 000000000.000000 000000002.890625 000000000.000000
> %f08: 000000003.390625 000000000.000000 000000002.250000 000000000.000000
> %f12: 000000002.890625 000000000.000000 000000002.312500 000000000.000000
> %f16: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
> %f20: 000000002.718750 000000000.000000 000000002.562500 000000000.000000
> %f24: 000000002.890625 000000000.000000 000000002.968750 000000000.000000
> %f28: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
> psr: 41000000 (icc: ---- SPE: ---) wim: 00000002
> fsr: 0f884002 y: 00000000
> Aborted
>
>
> The code:
>
>   0x70003174:  sethi  %hi(0x41c80000), %l3
>   0x70003178:  add  %l4, 2, %l5
>   0x7000317c:  st  %l3, [ %l4 ]
>   0x70003180:  ld  [ %l4 ], %f1
>   0x70003184:  clr  [ %l4 ]
>   0x70003188:  ld  [ %l4 ], %f2
>   0x7000318c:  mov  7, %g5
>   0x70003190:  fdivs  %f1, %f2, %f3

And what is even more strange it looks in qemu.log like if trap is taken,
gdb doesn't stop at the 0x080 breakpoint after this operation.
Whether I do a stepi or nexti, it just continues up to the crash.
Let me know if I can provide more information.

Breakpoint 2, 0x00000080 in ?? ()
(gdb) cont
Continuing.

Breakpoint 6, 0x70003190 in ?? ()
(gdb) stepi
Remote connection closed
(gdb)
Artyom Tarasenko April 20, 2010, 11:28 p.m. UTC | #3
2010/4/16 Artyom Tarasenko <atar4qemu@googlemail.com>:
> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>> 2010/4/15 Blue Swirl <blauwirbel@gmail.com>:
>>> On 4/15/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
>>>> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>>>>
>>>> > One of LX's tests crashes pretty hard, causing qemu abort.
>>>>  > I've tried to look how does the execution flow works with -d in_asm.
>>>>  > Does the address in the log show the guest's PC register?
>>>>
>>>>
>>>> It's probably sort of a "timing" issue.
>>>>
>>>>  Can we check exceptions not just on jumps, but also on floating poit
>>>>  operations which may cause a trap?
>>>>  These traps are supposed to be syncronous.
>>>
>>> Yes, the bug is that PC and NPC are not saved before executing FPU
>>> instructions. Please try this patch.
>>
>> The patch gets it a couple of tests further:
>>
>> FPU SP Invalid CEXC Test
>> FPU SP Overflow CEXC Test
>> FPU SP Divide-by-0 CEXC Test
>> FPU SP Inexact CEXC Test
>> FPU SP Trap Priority >  Test Unassigned mem write access of 4 bytes to
>> 000000008421f000 from 700030f8
>>
>> FPU SP Trap Priority <  Test
>>     ERROR : Unexpected Synchronous Trap Taken, Trap Type = 00000008,
>> PSR = 414010c4, PC = 70003190, TBR = 00000080
>>     STATUS : Entering scope loop .... Press <A> key to Abort!qemu:
>> fatal: Trap 0x03 while interrupts disabled, Error state
>> pc: 0000217c  npc: 00003170
>> General Registers:
>> %g0-7: 00000000 00003170 00000055 00000001 00000002 00000000 00000000 00000000
>>
>> Current Register Window:
>> %o0-7: 00000000 00000999 00000000 00000000 00000000 00000000 0001fba0 7000971c
>> %l0-7: 0002fff8 00000000 00000000 00000000 00000000 ffffffff 00000000 00000000
>> %i0-7: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>>
>> Floating Point Registers:
>> %f00: 000000002.890625 000000025.000000 000000000.000000 000000000.000000
>> %f04: 000000002.890625 000000000.000000 000000002.890625 000000000.000000
>> %f08: 000000003.390625 000000000.000000 000000002.250000 000000000.000000
>> %f12: 000000002.890625 000000000.000000 000000002.312500 000000000.000000
>> %f16: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
>> %f20: 000000002.718750 000000000.000000 000000002.562500 000000000.000000
>> %f24: 000000002.890625 000000000.000000 000000002.968750 000000000.000000
>> %f28: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
>> psr: 41000000 (icc: ---- SPE: ---) wim: 00000002
>> fsr: 0f884002 y: 00000000
>> Aborted
>>
>>
>> The code:
>>
>>   0x70003174:  sethi  %hi(0x41c80000), %l3
>>   0x70003178:  add  %l4, 2, %l5
>>   0x7000317c:  st  %l3, [ %l4 ]
>>   0x70003180:  ld  [ %l4 ], %f1
>>   0x70003184:  clr  [ %l4 ]
>>   0x70003188:  ld  [ %l4 ], %f2
>>   0x7000318c:  mov  7, %g5
>>   0x70003190:  fdivs  %f1, %f2, %f3
>
> And what is even more strange it looks in qemu.log like if trap is taken,
> gdb doesn't stop at the 0x080 breakpoint after this operation.
> Whether I do a stepi or nexti, it just continues up to the crash.
> Let me know if I can provide more information.
>
> Breakpoint 2, 0x00000080 in ?? ()
> (gdb) cont
> Continuing.
>
> Breakpoint 6, 0x70003190 in ?? ()
> (gdb) stepi
> Remote connection closed
> (gdb)

The trick was not to set the breakpoint at 0x70003190. Then the
breakpoint at 0x80 works.
And I think I found a hint:

http://www.cmpe.boun.edu.tr/courses/cmpe511/fall2004/Ozan Aktan -
Supersparc Architecture.doc

"One unique feature of the floating-point unit is that dependent
floating-point instructions may be issued in the same instruction
group as the dependent floating-point operation. As an example, the
following instructions can issue in a single clock cycle:
LDD                   [%i0 + %i1], %f2
FMULD              %f2, %f4, %f6   "

We also have a dependent instructions
0x700030f4:  fdivs  %f1, %f2, %f3
0x700030f8:  st  %f3, [ %l6 ]

which must produce two traps simultaneously: division by zero and
unaligned access. Unaligned access is a higher priority trap, so it
must be processed first.

In the previous test (which passed) the store produces a data access
exception which has lower priority than division by zero. The test
passes because it is bad.
Blue Swirl April 21, 2010, 6:11 p.m. UTC | #4
On 4/21/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
> 2010/4/16 Artyom Tarasenko <atar4qemu@googlemail.com>:
>
> > 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>  >> 2010/4/15 Blue Swirl <blauwirbel@gmail.com>:
>  >>> On 4/15/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
>  >>>> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>  >>>>
>  >>>> > One of LX's tests crashes pretty hard, causing qemu abort.
>  >>>>  > I've tried to look how does the execution flow works with -d in_asm.
>  >>>>  > Does the address in the log show the guest's PC register?
>  >>>>
>  >>>>
>  >>>> It's probably sort of a "timing" issue.
>  >>>>
>  >>>>  Can we check exceptions not just on jumps, but also on floating poit
>  >>>>  operations which may cause a trap?
>  >>>>  These traps are supposed to be syncronous.
>  >>>
>  >>> Yes, the bug is that PC and NPC are not saved before executing FPU
>  >>> instructions. Please try this patch.
>  >>
>  >> The patch gets it a couple of tests further:
>  >>
>  >> FPU SP Invalid CEXC Test
>  >> FPU SP Overflow CEXC Test
>  >> FPU SP Divide-by-0 CEXC Test
>  >> FPU SP Inexact CEXC Test
>  >> FPU SP Trap Priority >  Test Unassigned mem write access of 4 bytes to
>  >> 000000008421f000 from 700030f8
>  >>
>  >> FPU SP Trap Priority <  Test
>  >>     ERROR : Unexpected Synchronous Trap Taken, Trap Type = 00000008,
>  >> PSR = 414010c4, PC = 70003190, TBR = 00000080
>  >>     STATUS : Entering scope loop .... Press <A> key to Abort!qemu:
>  >> fatal: Trap 0x03 while interrupts disabled, Error state
>  >> pc: 0000217c  npc: 00003170
>  >> General Registers:
>  >> %g0-7: 00000000 00003170 00000055 00000001 00000002 00000000 00000000 00000000
>  >>
>  >> Current Register Window:
>  >> %o0-7: 00000000 00000999 00000000 00000000 00000000 00000000 0001fba0 7000971c
>  >> %l0-7: 0002fff8 00000000 00000000 00000000 00000000 ffffffff 00000000 00000000
>  >> %i0-7: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>  >>
>  >> Floating Point Registers:
>  >> %f00: 000000002.890625 000000025.000000 000000000.000000 000000000.000000
>  >> %f04: 000000002.890625 000000000.000000 000000002.890625 000000000.000000
>  >> %f08: 000000003.390625 000000000.000000 000000002.250000 000000000.000000
>  >> %f12: 000000002.890625 000000000.000000 000000002.312500 000000000.000000
>  >> %f16: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
>  >> %f20: 000000002.718750 000000000.000000 000000002.562500 000000000.000000
>  >> %f24: 000000002.890625 000000000.000000 000000002.968750 000000000.000000
>  >> %f28: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
>  >> psr: 41000000 (icc: ---- SPE: ---) wim: 00000002
>  >> fsr: 0f884002 y: 00000000
>  >> Aborted
>  >>
>  >>
>  >> The code:
>  >>
>  >>   0x70003174:  sethi  %hi(0x41c80000), %l3
>  >>   0x70003178:  add  %l4, 2, %l5
>  >>   0x7000317c:  st  %l3, [ %l4 ]
>  >>   0x70003180:  ld  [ %l4 ], %f1
>  >>   0x70003184:  clr  [ %l4 ]
>  >>   0x70003188:  ld  [ %l4 ], %f2
>  >>   0x7000318c:  mov  7, %g5
>  >>   0x70003190:  fdivs  %f1, %f2, %f3
>  >
>  > And what is even more strange it looks in qemu.log like if trap is taken,
>  > gdb doesn't stop at the 0x080 breakpoint after this operation.
>  > Whether I do a stepi or nexti, it just continues up to the crash.
>  > Let me know if I can provide more information.
>  >
>  > Breakpoint 2, 0x00000080 in ?? ()
>  > (gdb) cont
>  > Continuing.
>  >
>  > Breakpoint 6, 0x70003190 in ?? ()
>  > (gdb) stepi
>  > Remote connection closed
>  > (gdb)
>
>
> The trick was not to set the breakpoint at 0x70003190. Then the
>  breakpoint at 0x80 works.
>  And I think I found a hint:
>
>  http://www.cmpe.boun.edu.tr/courses/cmpe511/fall2004/Ozan Aktan -
>  Supersparc Architecture.doc
>
>  "One unique feature of the floating-point unit is that dependent
>  floating-point instructions may be issued in the same instruction
>  group as the dependent floating-point operation. As an example, the
>  following instructions can issue in a single clock cycle:
>  LDD                   [%i0 + %i1], %f2
>  FMULD              %f2, %f4, %f6   "
>
>  We also have a dependent instructions
>
> 0x700030f4:  fdivs  %f1, %f2, %f3
>  0x700030f8:  st  %f3, [ %l6 ]
>
>
> which must produce two traps simultaneously: division by zero and
>  unaligned access. Unaligned access is a higher priority trap, so it
>  must be processed first.
>
>  In the previous test (which passed) the store produces a data access
>  exception which has lower priority than division by zero. The test
>  passes because it is bad.

Currently QEMU executes the IU/FPU instructions synchronously and the
IU/FPU traps always arrive in the issue order. What you are describing
is called deferred traps in the V8 manual chapter Traps. STDFQ
description gives other hints and also Appendix L describes the queue.

But I think it would be very hard to model this accurately, you'd have
to take into account the instruction execution times, which are then
subject to the cache/memory model (in)accuracies.
Artyom Tarasenko April 21, 2010, 9:14 p.m. UTC | #5
2010/4/21 Blue Swirl <blauwirbel@gmail.com>:
> On 4/21/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
>> 2010/4/16 Artyom Tarasenko <atar4qemu@googlemail.com>:
>>
>> > 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>>  >> 2010/4/15 Blue Swirl <blauwirbel@gmail.com>:
>>  >>> On 4/15/10, Artyom Tarasenko <atar4qemu@googlemail.com> wrote:
>>  >>>> 2010/4/15 Artyom Tarasenko <atar4qemu@googlemail.com>:
>>  >>>>
>>  >>>> > One of LX's tests crashes pretty hard, causing qemu abort.
>>  >>>>  > I've tried to look how does the execution flow works with -d in_asm.
>>  >>>>  > Does the address in the log show the guest's PC register?
>>  >>>>
>>  >>>>
>>  >>>> It's probably sort of a "timing" issue.
>>  >>>>
>>  >>>>  Can we check exceptions not just on jumps, but also on floating poit
>>  >>>>  operations which may cause a trap?
>>  >>>>  These traps are supposed to be syncronous.
>>  >>>
>>  >>> Yes, the bug is that PC and NPC are not saved before executing FPU
>>  >>> instructions. Please try this patch.
>>  >>
>>  >> The patch gets it a couple of tests further:
>>  >>
>>  >> FPU SP Invalid CEXC Test
>>  >> FPU SP Overflow CEXC Test
>>  >> FPU SP Divide-by-0 CEXC Test
>>  >> FPU SP Inexact CEXC Test
>>  >> FPU SP Trap Priority >  Test Unassigned mem write access of 4 bytes to
>>  >> 000000008421f000 from 700030f8
>>  >>
>>  >> FPU SP Trap Priority <  Test
>>  >>     ERROR : Unexpected Synchronous Trap Taken, Trap Type = 00000008,
>>  >> PSR = 414010c4, PC = 70003190, TBR = 00000080
>>  >>     STATUS : Entering scope loop .... Press <A> key to Abort!qemu:
>>  >> fatal: Trap 0x03 while interrupts disabled, Error state
>>  >> pc: 0000217c  npc: 00003170
>>  >> General Registers:
>>  >> %g0-7: 00000000 00003170 00000055 00000001 00000002 00000000 00000000 00000000
>>  >>
>>  >> Current Register Window:
>>  >> %o0-7: 00000000 00000999 00000000 00000000 00000000 00000000 0001fba0 7000971c
>>  >> %l0-7: 0002fff8 00000000 00000000 00000000 00000000 ffffffff 00000000 00000000
>>  >> %i0-7: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
>>  >>
>>  >> Floating Point Registers:
>>  >> %f00: 000000002.890625 000000025.000000 000000000.000000 000000000.000000
>>  >> %f04: 000000002.890625 000000000.000000 000000002.890625 000000000.000000
>>  >> %f08: 000000003.390625 000000000.000000 000000002.250000 000000000.000000
>>  >> %f12: 000000002.890625 000000000.000000 000000002.312500 000000000.000000
>>  >> %f16: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
>>  >> %f20: 000000002.718750 000000000.000000 000000002.562500 000000000.000000
>>  >> %f24: 000000002.890625 000000000.000000 000000002.968750 000000000.000000
>>  >> %f28: 000000002.312500 000000000.000000 000000002.890625 000000000.000000
>>  >> psr: 41000000 (icc: ---- SPE: ---) wim: 00000002
>>  >> fsr: 0f884002 y: 00000000
>>  >> Aborted
>>  >>
>>  >>
>>  >> The code:
>>  >>
>>  >>   0x70003174:  sethi  %hi(0x41c80000), %l3
>>  >>   0x70003178:  add  %l4, 2, %l5
>>  >>   0x7000317c:  st  %l3, [ %l4 ]
>>  >>   0x70003180:  ld  [ %l4 ], %f1
>>  >>   0x70003184:  clr  [ %l4 ]
>>  >>   0x70003188:  ld  [ %l4 ], %f2
>>  >>   0x7000318c:  mov  7, %g5
>>  >>   0x70003190:  fdivs  %f1, %f2, %f3
>>  >
>>  > And what is even more strange it looks in qemu.log like if trap is taken,
>>  > gdb doesn't stop at the 0x080 breakpoint after this operation.
>>  > Whether I do a stepi or nexti, it just continues up to the crash.
>>  > Let me know if I can provide more information.
>>  >
>>  > Breakpoint 2, 0x00000080 in ?? ()
>>  > (gdb) cont
>>  > Continuing.
>>  >
>>  > Breakpoint 6, 0x70003190 in ?? ()
>>  > (gdb) stepi
>>  > Remote connection closed
>>  > (gdb)
>>
>>
>> The trick was not to set the breakpoint at 0x70003190. Then the
>>  breakpoint at 0x80 works.
>>  And I think I found a hint:
>>
>>  http://www.cmpe.boun.edu.tr/courses/cmpe511/fall2004/Ozan Aktan -
>>  Supersparc Architecture.doc
>>
>>  "One unique feature of the floating-point unit is that dependent
>>  floating-point instructions may be issued in the same instruction
>>  group as the dependent floating-point operation. As an example, the
>>  following instructions can issue in a single clock cycle:
>>  LDD                   [%i0 + %i1], %f2
>>  FMULD              %f2, %f4, %f6   "
>>
>>  We also have a dependent instructions
>>
>> 0x700030f4:  fdivs  %f1, %f2, %f3
>>  0x700030f8:  st  %f3, [ %l6 ]
>>
>>
>> which must produce two traps simultaneously: division by zero and
>>  unaligned access. Unaligned access is a higher priority trap, so it
>>  must be processed first.
>>
>>  In the previous test (which passed) the store produces a data access
>>  exception which has lower priority than division by zero. The test
>>  passes because it is bad.
>
> Currently QEMU executes the IU/FPU instructions synchronously and the
> IU/FPU traps always arrive in the issue order. What you are describing
> is called deferred traps in the V8 manual chapter Traps. STDFQ
> description gives other hints and also Appendix L describes the queue.
>
> But I think it would be very hard to model this accurately, you'd have
> to take into account the instruction execution times, which are then
> subject to the cache/memory model (in)accuracies.

The question is whether it's worth the effort. Having unaligned access
mixed with floating point operation seems quite artificial to me.

Nevertheless what scares me are window over- and underflow exceptions.

Also, what about v9? There must be also IU deferred traps.
diff mbox

Patch

From 6c7d08b06214337f2b95d865b33c7ca188899fa4 Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Thu, 15 Apr 2010 17:14:28 +0000
Subject: [PATCH] Sparc: fix PC/NPC during FPU traps

All FPU instructions can trap, so save PC/NPC state before
executing them.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 target-sparc/translate.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 2c07385..addb1e1 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2155,6 +2155,7 @@  static void disas_sparc_insn(DisasContext * dc)
                 rs1 = GET_FIELD(insn, 13, 17);
                 rs2 = GET_FIELD(insn, 27, 31);
                 xop = GET_FIELD(insn, 18, 26);
+                save_state(dc, cpu_cond);
                 switch (xop) {
                 case 0x1: /* fmovs */
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
@@ -2468,6 +2469,7 @@  static void disas_sparc_insn(DisasContext * dc)
                 rs1 = GET_FIELD(insn, 13, 17);
                 rs2 = GET_FIELD(insn, 27, 31);
                 xop = GET_FIELD(insn, 18, 26);
+                save_state(dc, cpu_cond);
 #ifdef TARGET_SPARC64
                 if ((xop & 0x11f) == 0x005) { // V9 fmovsr
                     int l1;
-- 
1.5.6.5