figured it out and fixed it. i forget to set the "transfer request" flag to kick off DMA.
in another routine, it sees that this flag is clear and assumes that a word has already been read using DMA, so it reads a crap value and then sets the transfer request flag again to start the next DMA transfer. that "crap value" pushes the valid data forward by one word.
on to the next issues: randomly the ATN register mailbox flag gets set but the data in it is stale. also, the status interface register will randomly get read from by the host.
I think these are two facets of the same problem: the mailbox flags sometimes respond when you access a register that they are not supposed to be monitoring!