I have an impression that __code acts oposite as intendend: if __code is defined, then _cinit is assumed to be in data memory - see the generated asm with BANKSELs, which is wrong.
Here is a copy from idata.c:
70 unsigned num, size;
71 __code cinit_t *cptr;
72 __code char *src;
73 __data char *dst;
I think *cptr is not takes place in code memory rather in data memory.
So the __code modifier shouldn't be in line 71. I tried it, and it is
working for me. The generated code is more beautiful:
; .line 76; "../idata.c" cptr = &cinit.entry;
MOVLW high (_cinit + 2)
MOVLW (_cinit + 2)