stryd_one Posted April 7, 2007 Report Posted April 7, 2007 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? Quote
th0mas Posted April 9, 2007 Report Posted April 9, 2007 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 usestep* 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.. Quote
stryd_one Posted April 10, 2007 Author Report Posted April 10, 2007 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 Quote
th0mas Posted April 10, 2007 Report Posted April 10, 2007 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. Quote
stryd_one Posted April 10, 2007 Author Report Posted April 10, 2007 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.... Quote
th0mas Posted April 10, 2007 Report Posted April 10, 2007 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 startupchar sizeofStep = sizeof(step);then just use that in your additions..Cheers,Tom Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.