• To: hatari-devel@xxxxxxxxxxxxxxxxxxx, Laurent Sallafranque <laurent.sallafranque@xxxxxxx>
• Subject: [hatari-devel] Re: DSP addressing bug
• From: Douglas Little <doug694@xxxxxxxxxxxxxx>
• Date: Wed, 21 Oct 2015 13:54:31 +0100

Hi,

This one is almost certainly for Laurent.

So I have now (finally) confirmed that the problem described below is a real bug in Hatari's DSP emulation. It behaves differently from real HW (and from the description in the DSP manual).

To summarize....

When using the DSP modulo/ringbuffer addressing mode (Mn > 0) combined with an offset (+/-Nn) the calculated address (or updated address) is wrong when the Nn increment is a multiple of the ringbuffer 2^k bounding size.

This is an important feature when addressing arrays of ringbuffers - which is how I discovered it.

i.e. a normal address update (Rn)+ performs ringbuffer addressing where (Rn)+Nn lets you advance to the next ringbuffer without any modulo... or alternatively (Rn+Nn) allows addressing of equal position in a different ringbuffer.

another example:

Rn = 0
Nn = 8
Mn = 3-1  ; (addr % 3)

; normal wrapping behaviour...
(Rn)+   ; 0->1
(Rn)+   ; 1->2
(Rn)+   ; 2->0
(Rn)+   ; 0->1

; now advance to new ringbuffer
(Rn)+Nn ; 1->9 (1+8 = 9)

..since Nn=8 is twice the 2^k ringbuffer bound of 4, for a mod of 3)

Here Hatari yields a different answer, having performed modulo on the +Nn update instead of a normal increment by Nn.

I have been using a (rather expensive) temporary workaround which looks a bit like this:

move #-1,m1  ; 2 or 4c : disable ring mode
nop          ; 0 or 2c
move (r1)+n1 ; 2c
move #3-1,m1 ; 2 or 4c : restore ring mode

move (r1)+n1 ; 2c
.

Note that this trick only works when Nn is a multiple of the 2^k ringbuffer bound. In any other case it just wraps.

There is one detail I have not checked properly yet - whether this works when (Nn == ringbuffer 2^k bound), and not just a multiple of 2x or more. I suspect it does, according to the manual, but I only tested with Nn = 2x ring size so far... I'll check this separately but it doesn't much affect the bugreport either way.

D

On 9 July 2015 at 10:27, Douglas Little wrote:
Hi,

Since this is a DSP behaviour thing, it might be one for Laurent!

I ran into this case recently and it appears to be a bug (I think). I see something funny when performing an address update in modulo/ringbuffer mode...

r1: \$4020
n1: 8
m1: 2 (3-1, or modulo=3)

> move (r1)+n1

r1: \$4025

I think r1 should actually read \$4028 because there is a special case when +Nn increment is used in modulo mode, where N is a multiple of the 2^n modulo upper bound.

I have actually used this before successfully but in that case the Mn register was set to produce a 2^n modulo (i.e. modulo = 4, buffer size = 4).. That appeared to work correctly at the time.

In this case the modulo is odd (modulo = 3, buffer size = 4) and the result is weird.

Another curious thing is that the earlier case which worked used Nn exactly the size of the ringbuffer (using Nn=Mn+1), and produced this (correct) result in both HW and Hatari:

r1: \$0100
n1: 4
m1: 3 (4-1, or modulo=4)

> move (r1)+n1

r1: \$0104

...however this is what I get with Hatari using Nn=Mn+1 with the odd modulo.

r1: \$0100
n1: 4
m1: 2 (3-1, or modulo=3)

> move (r1)+n1

r1: \$0101

The latter hasn't been confirmed on real HW so I'm less sure about it being a bug. However the updated address should land in the *next* ringbuffer not the current one (using the special rules for +/-Nn updates) so it also seems suspect.

So it seems like 'bug' is as follows:

The modulo is still being applied when Nn = P x 2^k, when it should be ignored.

TBH I haven't been able to test the bug cases on HW yet because it is temporarily packed away :( but I will as soon as I can. The manual does seem to explain it with a diagram though (attached).

If an offset, Nn, is used in the address calculations, the 16-bit absolute value, INnl, must be less than or equal to M for proper modulo addressing. If Nn>M, the result is data dependent and unpredictable, except for the special case where Nn = P x 2k, a multiple of the block size where P is a positive integer. For this special case, when using the (Rn) + Nn addressing mode, the pointer, Rn, will jump linearly to the same relative address in a new buffer, which is P blocks forward in memory (see Figure 5-12).

 Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/