[hatari-devel] Interrupt assert triggered by video.c
Eero Tamminen
eerot at users.berlios.de
Fri Jul 10 22:01:11 CEST 2009
Hi,
(I found a potential culprit, see the end)
On Thursday 09 July 2009, npomarede at corp.free.fr wrote:
> From the trace, it seems the assert is showing a bug that is not related
> to video.c but was already present in dmasnd.c
I just managed to get this assert triggered also by video.c:
#3 0xb7bbd5be in __assert_fail () from /lib/i686/cmov/libc.so.6
#4 0x080615de in Int_AddRelativeInterruptWithOffset (CycleTime=-59622,
CycleType=1, Handler=INTERRUPT_VIDEO_ENDLINE, CycleOffset=0) at
int.c:392
#5 0x08061607 in Int_AddRelativeInterrupt (CycleTime=-59622, CycleType=1,
Handler=INTERRUPT_VIDEO_ENDLINE) at int.c:352
#6 0x0807493c in Video_AddInterrupt (Pos=-59622,
Handler=INTERRUPT_VIDEO_ENDLINE) at video.c:2539
<one-liner static Video_AddInterruptTimerB() function's missing here>
#7 0x08077772 in Video_Sync_WriteByte () at video.c:2552
#8 0x08061d27 in IoMem_wput (addr=16744970, val=512) at ioMem.c:400
#9 0x080cbf32 in op_31fc_0_ff (opcode=12796) at memory.h:118
#10 0x0807c533 in m68k_go (may_quit=1) at newcpu.c:1709
#11 0x08063e29 in M68000_Start () at m68000.c:224
#12 0x08064969 in main (argc=11, argv=Cannot access memory at address 0x12b5
) at main.c:712
This happened with Falcon emulation when AceTracker (demo) switched
from the GEM file selector back to the tracker screen that has a different
resolution.
First checking "Pos"...
(gdb) up
...
#6 0x0807493c in Video_AddInterrupt (Pos=-59622,
Handler=INTERRUPT_VIDEO_ENDLINE) at video.c:2539
2539 Int_AddRelativeInterrupt ( Pos - LineCycles +
nCyclesPerLine , INT_CPU_CYCLE, Handler );
(gdb) info locals
FrameCycles = 124766
HblCounterVideo = 264
LineCycles = 60534
(gdb) up
#7 0x08077772 in Video_Sync_WriteByte () at video.c:2552
2552 Video_AddInterrupt ( Pos , INTERRUPT_VIDEO_ENDLINE );
(gdb) info locals
FrameCycles = <value optimized out>
HblCounterVideo = 264
LineCycles = 60546
Freq = 2 '\002'
line 2552:
--------
static void Video_AddInterruptTimerB ( int Pos )
{
Video_AddInterrupt ( Pos , INTERRUPT_VIDEO_ENDLINE );
}
--------
Video_Sync_WriteByte () :
--------
...
/* Update Timer B's position */
LineTimerBCycle = Video_TimerB_GetPos ( HblCounterVideo );
Video_AddInterruptTimerB ( LineTimerBCycle );
...
---------
Video_TimerB_GetPos ():
---------
int Video_TimerB_GetPos ( int LineNumber )
...
if ( ( IoMem[0xfffa03] & ( 1 << 3 ) ) == 0 ) /*
we're counting end of line events */
{
Pos = ShifterFrame.ShifterLines[
LineNumber ].DisplayEndCycle + TIMERB_VIDEO_CYCLE_OFFSET;
}
else /*
we're counting start of line events */
{
Pos = ShifterFrame.ShifterLines[
LineNumber ].DisplayStartCycle + TIMERB_VIDEO_CYCLE_OFFSET;
}
#endif
return Pos;
---------
Nothing funny there though:
---------
(gdb) print ShifterFrame.ShifterLines[ 264 ].DisplayStartCycle
$3 = -1
(gdb) print ShifterFrame.ShifterLines[264].DisplayEndCycle
$4 = 376
---------
And from how it's used:
---------
static void Video_AddInterrupt ( int Pos , interrupt_id Handler )
{
int FrameCycles , HblCounterVideo , LineCycles;
Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
if ( LineCycles < Pos ) /* changed before reaching
the new Pos on the current line */
Int_AddRelativeInterrupt ( Pos - LineCycles , INT_CPU_CYCLE,
Handler );
else /* Pos will be applied on
next line */
Int_AddRelativeInterrupt ( Pos - LineCycles +
nCyclesPerLine , INT_CPU_CYCLE, Handler );
}
------------
I can see that Gdb shows the "Pos" value wrong in above backtrace because
it gives the same value as for CycleTime which in above code will obviously
gets a different value when LineCycles differs from zero. So I think Pos
value is fine.
Btw. If value's passed in a register and this value doesn't need to be
recovered after the function returns, GCC doesn't do that nor provide info
about the previous value (in higher stack frames), at least for optimized
code.
One might not be able to trust local values either in optimized code, but
static/global variables one can. So...
FrameCycles value seems to be shown right:
(gdb) print nCyclesCounter[1]
$5 = 124766
And LineCycles is the culprit:
(gdb) print nHBL
$6 = 263
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ nHBL ].StartCycle
$7 = -63724
There seems to be a pretty obvious bug in Video_ConvertPosition():
-------
*pHBL = nHBL;
*pLineCycles = FrameCycles - ShifterFrame.ShifterLines[
nHBL ].StartCycle;
if ( *pLineCycles < 0 ) /* reading
from the previous video line */
{
*pHBL = nHBL-1;
*pLineCycles = FrameCycles - ShifterFrame.ShifterLines[
nHBL ].StartCycle;
===> "nHBL" instead of "nHBL-1"
}
else if ( *pLineCycles >= nCyclesPerLine ) /* reading
on the next line, but HBL int was delayed */
{
*pHBL = nHBL+1;
*pLineCycles -= nCyclesPerLine;
}
-------
I would rewrite this as:
-------
*pLineCycles = FrameCycles - ShifterFrame.ShifterLines[
nHBL ].StartCycle;
if ( *pLineCycles < 0 ) /* reading
from the previous video line */
{
assert(nHBL > 0);
*pHBL = nHBL-1;
*pLineCycles = FrameCycles - ShifterFrame.ShifterLines[
nHBL-1 ].StartCycle;
assert(*pLineCycles >= 0);
}
else if ( *pLineCycles >= nCyclesPerLine ) /* reading
on the next line, but HBL int was delayed */
{
*pHBL = nHBL+1;
*pLineCycles -= nCyclesPerLine;
}
else
*pHBL = nHBL;
-------
However, even that might not help because:
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ nHBL-1 ].StartCycle
$8 = -63500
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ 200 ].StartCycle
$9 = -47752
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ 100 ].StartCycle
$10 = -22352
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ 50 ].StartCycle
$11 = -9652
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ 25 ].StartCycle
$12 = -4656
(gdb) print FrameCycles - ShifterFrame.ShifterLines[ 0 ].StartCycle
$13 = 0
But hopefully that happened because of the above bug...
- Eero
PS. The current code is pretty horrible read with the mass of ifdefs,
I hope you can clean it soon. :-)
More information about the hatari-devel
mailing list