GP2X Problems With Inline Asm.


MadDog

Member
Joined
Mar 4, 2006
Messages
262
Age
54
Location
UK
Website
www.maddoggames.com
I'm trying to write a bit of inline asm for clearing the screen. Its not the best code because i'm more intrested at the mo in learning how to do it. :)

Anyway, i've getting the error
.\source\GPU.c(246): error: impossible constraint in 'asm'
on the current code at the first line, any ideas?

asm ( [Says error is on this line.]
"mov r3,#76800 \n"
"mov r4,%0 \n"
"orr r4,r4,r4,lsl#8 \n"
"orr r4,r4,r4,lsl#16 \n"
"mov r5,%2 \n"
"clear_screen_loop: \n"
" mov [r5],r4 \n"
" add r5,r5,4 \n"
" subs r3,r3,1 \n"
"bne clear_screen_loop \n"
:/*no output*/
:"r"(cmd->paletteindex), "a"(reg.display.rt)
:"r3", "r4" , "r5" );
 
MadDog posted on May 22 2006 at 10:12 AM said:
I'm trying to write a bit of inline asm for clearing the screen. Its not the best code because i'm more intrested at the mo in learning how to do it. :)

Anyway, i've getting the error
.\source\GPU.c(246): error: impossible constraint in 'asm'
on the current code at the first line, any ideas?

asm ( [Says error is on this line.]
"mov r3,#76800 \n"
"mov r4,%0 \n"
"orr r4,r4,r4,lsl#8 \n"
"orr r4,r4,r4,lsl#16 \n"
"mov r5,%2 \n"
"clear_screen_loop: \n"
" mov [r5],r4 \n"
" add r5,r5,4 \n"
" subs r3,r3,1 \n"
"bne clear_screen_loop \n"
:/*no output*/
:"r"(cmd->paletteindex), "a"(reg.display.rt)
:"r3", "r4" , "r5" );
I don't know, but maybe it's the use of %2 in the code (which doesn't seem to be defined) or maybe the compiler can't handle cmd->paletteindex or reg.display.rt as parameters. Just guesses.
 
Last edited by a moderator:
Nice catch on the typo, still no joy though. I've also changed the params to local vars and still I get that odd error. Bit more googling may find the answer.


Thanks.
 
Fixed it, in the param list I had an "a" instead of "r" for the dest address. Odd thing is that im sure I read in the gcc docs that "r" was for an address, or maybe I missunderstood. Once I fixed all the errors with the code showed up. It works now, although for some reason not clearing the bottom part of the screen. There are lots of things I can do to speed the clear up. Its a simple task thats good to learn the instruction set with. Glad I did not just cut'n'past it. ;)
 
Hmm, the screen is 320x240x16 bit. That's 153600 bytes. How come your clearing 307200 bytes? (76800x4)

I'd look into the 'stm' instruction, too.
 
Squidge posted on May 22 2006 at 03:31 PM said:
Hmm, the screen is 320x240x16 bit. That's 153600 bytes. How come your clearing 307200 bytes? (76800x4)

I'd look into the 'stm' instruction, too.
Yeah, if you're looking for a routine to actually clear the screen (instead of just using it as a programming exercise), there's a pretty efficient one in my demo examples, which I'll reproduce here. It assumes a 16 bit pixels; cut the 4800 to 2400 for 8-bit pixels. Using the blitter might be a little bit faster.

ClearScreen:
stmfd sp!, {r4-r10} @ remember registers 4-10
mov r2, #4800 @ we will run the loop 4800 times to copy the screen
mov r3, #0 @ load up the registers with zeros
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
mov r9, #0
mov r10, #0
.ClearScreenLoop:
stmia r0!, {r3-r10} @ write the 32 bytes of zeros to the destination
subs r2, r2, #1 @ decrement the loop counter
bne .ClearScreenLoop @ if we're not done, do it again
ldmfd sp!, {r4-r10} @ restore the registers
mov pc, lr @ return
 
Last edited by a moderator:
Hmmm, here's an interesting optimisation.

Would it be faster to move lr into pc like you do in that snippet of code, or would pushing r14 onto the stack and then popping it into r15 at the end be a slight amount quicker due to one less instruction fetch?

Ie. instead of:
stmfd sp!, {r4-r10,r14} @ remember registers 4-10
[...]
subs r2, r2, #1 @ decrement the loop counter
bne .ClearScreenLoop @ if we're not done, do it again
ldmfd sp!, {r4-r10} @ restore the registers
mov pc, lr @ return

do:

stmfd sp!, {r4-r10,r14} @ remember registers 4-10
[...]
subs r2, r2, #1 @ decrement the loop counter
bne .ClearScreenLoop @ if we're not done, do it again
ldmfd sp!, {r4-r10,r15} @ restore the registers

Just something that caught my eye :) No idea if it would be faster or not. Of course the easiest way to speed it up would be to write an entire line (640 bytes) between each loop, as istr that arm's don't like branches.
 
Squidge posted on May 23 2006 at 12:28 AM said:
Just something that caught my eye :) No idea if it would be faster or not. Of course the easiest way to speed it up would be to write an entire line (640 bytes) between each loop, as istr that arm's don't like branches.
You're right, partially unrolling the loop would help some. That could save 3 or 4 cycles per loop iteration; since each one is taking about 100 cycles or so right now, that would increase the speed by a few percent.
 
Last edited by a moderator:
Squidge posted on May 22 2006 at 10:31 PM said:
Hmm, the screen is 320x240x16 bit. That's 153600 bytes. How come your clearing 307200 bytes? (76800x4)

I'd look into the 'stm' instruction, too.

Yup, once I got round my syntax error in the asm block i got lots of errors etc.... Anyway after I did a bit of reading of my books and built a routine I looked at the demo code and its almost identical, except I build a 32bit clear value from my 8 bit clear index. I'm running with a pallatised screen res.

asm (
"mov r0,#0x0000780 \n"
"mov r1,%1 \n"
"mov r2,%0 \n"
"orr r2,r2,r2,lsl #8 \n"
"orr r2,r2,r2,lsl #16 \n"
"mov r3,r2 \n"
"mov r4,r2 \n"
"mov r5,r2 \n"
"mov r6,r2 \n"
"mov r7,r2 \n"
"mov r8,r2 \n"
"mov r9,r2 \n"
"mov r10,r2 \n"
"mov r11,r2 \n"
"clear_screen_loop: \n"
" stmia r1!,{r2-r11} \n"
" subs r0,r0,#1 \n"
"bne clear_screen_loop \n"
:
:"r"(cmd->paletteindex), "r"(reg.display.rt)
:"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11" );

There are prob ways to tweek it, like you say unrolling the scan lines. I don't know too much about the addressing modes but did wonder if I could do an indirect addessing to remove the loop counter subtraction. But then I would guess the cc bits are not updated based on the addressing mode. Don't know if this is legal but something like...


stmia [r1 - r0,#0x28],{r2-r11} - Write to r1 - r0, dec r0 by 40, set cc zero flag when zero.
 
Last edited by a moderator:
Back
Top