Hi,
First of all: I'm using a XE167FM-72 microcontroller. I'm stuck using the va_* family of functions. I've looked into the generated assembler code, it seems that it passes the first parameters directly via registers, and put the rest on the userstack.
Example for a call:
task7_va(3,2,3,4,0,0,0,0); give me
00C0512A E004 MOV R4,#0x00 00C0512C 8840 MOV [-R0],R4 00C0512E E004 MOV R4,#0x00 00C05130 8840 MOV [-R0],R4 00C05132 E004 MOV R4,#0x00 00C05134 8840 MOV [-R0],R4 00C05136 E00C MOV R12,#0x00 00C05138 E04B MOV R11,#0x04 00C0513A E03A MOV R10,#0x03 00C0513C E029 MOV R9,#0x02 00C0513E E038 MOV R8,#0x03 00C05140 DAC0CC4F CALLS task7_va(0xC04FCC)
va_start(vl,count); in task7_va give me
00C0501A E6F41000 MOV R4,#0x0010 00C0501E 0040 ADD R4,R0 00C05020 66F4FF3F AND R4,#0x3FFF 00C05024 F2F504FE MOV R5,DPP3:0x3E04 //comment from me: loads DPP2 (0x380) into R5 00C05028 C4400200 MOV [R0+#0x0002],R4 00C0502C C4500400 MOV [R0+#0x0004],R5
arg = va_arg(vl,int); in task7_va give me
00C05036 E026 MOV R6,#0x02 00C05038 D4500400 MOV R5,[R0+#0x0004] 00C0503C D4400200 MOV R4,[R0+#0x0002] 00C05040 0046 ADD R4,R6 00C05042 C4400200 MOV [R0+#0x0002],R4 00C05046 D4500400 MOV R5,[R0+#0x0004] 00C0504A D4400200 MOV R4,[R0+#0x0002] 00C0504E E026 MOV R6,#0x02 00C05050 2046 SUB R4,R6 00C05052 DC55 EXTP R5,#2 00C05054 A9C4 MOVB RL6,[R4] 00C05056 F4D40100 MOVB RH6,[R4+#0x0001] 00C0505A F046 MOV R4,R6 00C0505C C4400C00 MOV [R0+#0x000C],R4
I don't see where the direct access to the registers r8...r12 are happening. I have problems not getting the correct values, that's why I'm digging into this a bit deeper. I hope that it doesn't make any assumption where the userstack (R0) and the register bank (CP) are (there are of course an legal positions for the microcontroller point of view) - I need to change them via assembler.
Best regards, Michael Fritscher
Thanks for the quick answer.
The prototype is
void far task7_va(int count,...)
for which the initcode
00C04FCC 88C0 MOV [-R0],R12 00C04FCE 88B0 MOV [-R0],R11 00C04FD0 88A0 MOV [-R0],R10 00C04FD2 8890 MOV [-R0],R9 00C04FD4 8880 MOV [-R0],R8 00C04FD6 06F0F2FF ADD R0,#0xFFF2
is created.
So it follow the rules, doesn't it?
Looks like you just found those accesses to the arguments passed in registers r8 etc. that you missed earlier, doesn't it?
It appears as if those pushes are intended to set up the environment to allow the va_* macros to work. They push register arguments on the stack, where va_start/va_arg can acces them uniformly with those that were passed on the stack from the start.
This kind of push-back operation is part of the price to be paid for the efficiency of partly register-based calling conventions.
Ah, thats right :-) Thanks a lot! Two eyes aren't enough sometimes it seems ;-) I'll look after it tomorrow when I'm back at university - seems that I've broken the userstack badly or something similiar.
ok, I've analysed the assembler line-by-line.
it seems that error is the line MOV R5, DPP3:0x3E04 in va_start(), which in turn points to 0xFE04, which points to DPP2, which is 0x380 - so it points nowhere, that's why I get wrong data.
It it would save DPP3 instead it would work yust fine. Is that an error in the compiler or did I make an mistake?
Additional notes: 0x380 points to the first PSRAM-position.
even if I set #NOFD, it sets during va_start R4 to 0x121a and R5 to 0x381 - with the same result... What do I miss here?
Ok, I see the problem now: Keil assigns the userstack to PSRAM, while I set the userstack to DSRAM - hence the different DPP-Registers. Thanks for the help :-) I try to embedd my private userstack into the userstack created by keil to circumvent these problems, I don't care whether the userstack is in PSRAM or in DSRAM.
I don't care whether the userstack is in PSRAM or in DSRAM. Placing the userstack in the DSRAM will give you better system performance verses in the PSRAM.