aa-dav wrote: ↑Mon Jun 29, 2020 9:44 pm
vbc wrote: ↑Mon Jun 29, 2020 7:49 am
...
Cool! Could you test this example please:
Code: Select all
void str_cpy(char *d,char *s)
{
while ( *d++ = *s++ ) {};
}
vbcc does not like the post-increment in the loop condition too much and makes a copy of the pointers:
Code: Select all
;vcprmin=10000
section text
global _str_cpy
_str_cpy:
lda r3
sta r7
lda r2
sta r6
inc r2
bne l20
inc r3
l20:
lda r1
sta r5
lda r0
sta r4
inc r0
bne l21
inc r1
l21:
ldy #0
lda (r6),y
sta (r4),y
cmp #0
beq l7
l6:
lda r3
sta r7
lda r2
sta r6
inc r2
bne l22
inc r3
l22:
lda r1
sta r5
lda r0
sta r4
inc r0
bne l23
inc r1
l23:
ldy #0
lda (r6),y
sta (r4),y
cmp #0
bne l6
l7:
rts
Much better code gets generated when slightly rewriting the function:
Code: Select all
void str_cpy(char *s1,char *s2)
{
char c;
do{
c=*s2++;
*s1++=c;
}while(c);
}
compiles to:
Code: Select all
;vcprmin=10000
section text
global _str_cpy
_str_cpy:
l7:
ldy #0
lda (r2),y
inc r2
bne l15
inc r3
l15:
sta (r0),y
inc r0
bne l16
inc r1
l16:
cmp #0
bne l7
rts
cc65 -Oisr generates:
Code: Select all
.proc _str_cpy: near
.segment "CODE"
jsr pushax
jsr decsp1
L0002: ldy #$02
lda (sp),y
tax
dey
lda (sp),y
sta regsave
stx regsave+1
clc
adc #$01
bcc L0007
inx
L0007: jsr staxysp
ldy #$00
lda (regsave),y
sta (sp),y
ldy #$04
lda (sp),y
tax
dey
lda (sp),y
sta regsave
stx regsave+1
clc
adc #$01
bcc L0009
inx
L0009: jsr staxysp
ldy #$00
lda (sp),y
sta (regsave),y
lda (sp),y
bne L0002
jmp incsp5
.endproc
Looks like your compiler analizes call tree and places parameters in global variables if possible. Is it true?
It uses zero page locations as registers and passes parameters in a number of registers. But the calling convention is using a fixed ABI (unless the function call is inlined in which case the parameters are used directly).
But does it support recursion?
Yes, for example samples/calc.c uses recursion.
If yes, what code will be generated if parameters will be in stack?
Adding some dummy parameters to the memcpy example will force the parameters onto the stack:
Code: Select all
void memcpy_s(int d1,int d2,int d3,int d4,char *d,char *s,unsigned int n)
{
while(n){*d++=*s++;n--;}
}
The generated code now has to pull the arguments from the software stack into registers:
Code: Select all
;vcprmin=10000
section text
global _memcpy_s
_memcpy_s:
ldy #5
lda (sp),y
sta r5
dey
lda (sp),y
sta r4
dey
lda (sp),y
sta r3
dey
lda (sp),y
sta r2
dey
lda (sp),y
sta r1
dey
lda (sp),y
sta r0
lda r5
bne l22
lda r4
beq l9
l22:
l8:
ldy #0
lda (r2),y
sta (r0),y
inc r2
bne l23
inc r3
l23:
inc r0
bne l24
inc r1
l24:
lda r4
bne l25
dec r5
l25:
dec r4
lda r5
bne l8
lda r4
bne l8
l9:
rts[/quote]