Jump to content

Recommended Posts

Posted

Hey guys.

I've been bugged by this for ages, and I've not been able to find out anything about it... I hope one of you knows what's going on here...

It's about the math for calculating addresses for arrays. Here's an example. I have nested arrays of structs that look like

track[n].step[m].something.

EVERY single time it needs to calculate an address for one of the arrays, it does the same damned pointer math like this:

n*0x9e+0*0x07+something

; ;multiply lit val:0x9e by variable r0x00 and store in r0x00
; ;Unrolled 8 X 8 multiplication
; ;FIXME: the function does not support result==WREG
;	.line	100; vxevents.c	track[(TRK)].step[(STP)].param1 = P1;
	MOVF	r0x00, W
	MULLW	0x9e
	MOVFF	PRODL, r0x00
	MOVFF	PRODH, r0x03
	MOVLW	LOW(_track)
	ADDWF	r0x00, F
	MOVLW	HIGH(_track)
	ADDWFC	r0x03, F
	MOVLW	0x12
	ADDWF	r0x00, F
	BTFSC	STATUS, 0
	INCF	r0x03, F
; ;multiply lit val:0x07 by variable r0x01 and store in r0x01
; ;Unrolled 8 X 8 multiplication
; ;FIXME: the function does not support result==WREG
	MOVF	r0x01, W
	MULLW	0x07
	MOVFF	PRODL, r0x01
	MOVF	r0x01, W
	ADDWF	r0x00, F
	CLRF	WREG
	ADDWFC	r0x03, F
	MOVLW	0x02
	ADDWF	r0x00, F
	BTFSC	STATUS, 0
	INCF	r0x03, F
	MOVFF	r0x00, FSR0L
	MOVFF	r0x03, FSR0H
	MOVFF	r0x02, INDF0
	MOVFF	PREINC1, r0x03
	MOVFF	PREINC1, r0x02
	MOVFF	PREINC1, r0x01
	MOVFF	PREINC1, r0x00
	MOVFF	PREINC1, FSR2L
	RETURN	

Is there some way of making the compiler be sane and have a function that can be called to do this, so I don't have the same damned code repeated a thousand times?

Posted

I'm going to get things wrong in this post - I don't have time to correct it, but you'll understand the technique.

I'm assuming you understand the calculation:

n*0x9e+0*0x07+something

(ie you realize 0x9e is the size of an entry in the larger array, and 0x07 is the size of an entry in the smaller array).

If you wrote a function, something like:

step* calcOffset(int n, int m)

{

  return n*0x9e + m * 0x07

}

then you could use

step* ptr = &track[0] + calcOffset(n, m)

or just access it with (step*  (&track[0] + calcOffset(n, m)))->something.

Will this give you better code? probably not.  But see what happens..

Posted

Yeh that's the kind of thing I mean :)

It just seems strange to me that the compiler doesn't do that already? I mean, why do the same unrolled multiply every time the array is accessed when a much simpler way is, as you demonstrated, to have one function which calculates the address, and call that....

I figured that it might be because of the need to pass 4 bytes worth of variables around creating slower code, and maybe I needed to tell it to optimise for code size (--opt-code-size) but that didn't work :( I tried some of the other optimiser flags that are currently not used, but no joy there either...

I tried using a pointer to the array but no good, it just used slightly larger pointer math each time ::).... But I didn't try forcing it to use a function of my own to calculate the pointer, I suspect that will do the trick nicely. I will have to do that soon anyway when I move the non-realtime data to SRAM, so it's on the cards...

One tricky part is the size of the elements of the array... Obviously, SDCC calculates this on the fly but if I employ this method, then if I change the array, it's all screwy....But again, I'll have to work with that when it's all in SRAM anyway.

I guess I'd like to solve these problems before I go ahead with my project, even though it won't benefit me right now, I think it'd be nice to have solutions here for future development.... Like the big arrays thing... I now see why TK breaks his seq data into small chunks of nice even sizes, and I'll be doing the same... but I just had to know! :D

Posted

Assuming you're accessing your array data sequentially, you could keep a running pointer to the current step, and just increment it by sizeof(step) to get to the next step.  You'd have to do it smart though, since any extraneous variables in the track that aren't part of the steps will need to be skipped over.

Posted

Yeh, but then it does the sizeof() every time :(

There must be a way to automate this without creating new overheads...... I'm gonna take it up over at SDCC land and see what I can find....

Posted

the sizeof is static.. just calculate it and put the value in the code, add a comment at the struct declaration reminding yourself to update the value.

edit: or just have a global int that gets calculated at startup

char sizeofStep = sizeof(step);

then just use that in your additions..

Cheers,

Tom

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...