memset is referenced in <strings.h> and not in <stdlib.h> but i can't seem to find the source. i'll write a small program and check the disassembly listing file..
it wasn't in the disassembly file
so i looked at the generated assembly
#include <string.h>
#include <xc.h>
unsigned char framebuffer[1024]__attribute__((aligned (2)));
int main() {
memset(framebuffer,0,sizeof(framebuffer));
while(1) {
Nop();
}
return 0;
}
before calling the functions the working registers are loaded with the call arguments
W0 with the address of framebuffer (0x1000)
W1 with the value, in this case 0
W2 with the size of framebuffer, 0x400
the generated assembly for memset, using -O0. On the left the address, on the right the assembly
02E4 MOV W0,W3
02E6 BRA 0x2EC ;This points to three lines lower, 0x2EC is the absolute address
02E8 MOV.B W1, [W3++]
02EA DEC W2,W2
02EC CP0 W2
02EE BRA NZ, 0x2E8 ;This points to three lines UP
02F0 RETURN
with -O1 (@rt, it's included in free mode however. and it arelady makes TONS of useful optimizations. in this case the code generated with -O0 is especially slow because of the two branches. you have many cycles penalities on branches on dspic33e because you have to recreate the pipeline, which dspic33F and dspic30F don't have, as they are slower cores)
02E4 MOV #0x1000, W0
02E6 REPEAT #0x1FF
02E8 CLR [W0++]
this was also visible in the disassembly listing file
BONUS: memset to another value
;memset(framebuffer,1,sizeof(framebuffer));
02E4 MOV #0x0101, W2
02E6 MOV #0x1000, W0
02E8 REPEAT #0x1FF
02EA MOV W2, [W0++]
instead of clearing, the repeated instruction is a copy from one register to the memory location pointed to by W0. W2 is loaded to 0x0101 because (of course) the memory in the dsPIC is word addressable so one 16bit move takes 1 cycle, 8 bit move takes 1 cycle (so better combine them) 32 bit move however takes 2 cycles.
BONUS2: and what happens if the memset target has an odd number of bytes?
yep, what you expect
;char framebuffer[1025];
;memset(framebuffer,2,sizeof(framebuffer));
02E4 MOV #0x0202, W2
02E6 MOV #0x1000, W0
02E8 REPEAT #0x1FF
02EA MOV W2, [W0++]
02EC MOV.B W2, [W0++]
same code, with a single MOV.B added. don't have to modify W2 because with byte instructions (.B) only the lower byte of the accumulator is used