* .version: bumped version number to 2.4.8
[fw/sdcc] / device / lib / pic16 / startup / crt0i.c
1 /*
2  * crt0i.c - SDCC pic16 port runtime start code with
3  *           initialisation
4  *
5  * Converted for SDCC and pic16 port
6  * by Vangelis Rokas (vrokas@otenet.gr)
7  *
8  * based on Microchip MPLAB-C18 startup files
9  *
10  * $Id$
11  */
12
13 extern stack;
14 extern stack_end;
15
16 extern TBLPTRU;
17 extern TBLPTRH;
18 extern TBLPTRL;
19 extern FSR0L;
20 extern FSR0H;
21 extern TABLAT;
22 extern POSTINC0;
23
24 /* global variable for forcing gplink to add _cinit section */
25 char __uflags = 0;
26
27 /* external reference to the user's main routine */
28 extern void main (void);
29
30 /* prototype for the startup function */
31 void _entry (void) _naked interrupt 0;
32 void _startup (void) _naked;
33
34 /* prototype for the initialized data setup */
35 void _do_cinit (void);
36
37
38 /*
39  * entry function, placed at interrupt vector 0 (RESET)
40  */
41
42 void _entry (void) _naked interrupt 0
43 {
44   _asm goto __startup _endasm;
45 }
46
47
48 void _startup (void) _naked
49 {
50         _asm
51                 // Initialize the stack pointer
52                 lfsr 1, _stack_end
53                 lfsr 2, _stack_end
54                 clrf _TBLPTRU, 0        // 1st silicon doesn't do this on POR
55     
56                 // initialize the flash memory access configuration. this is harmless
57                 // for non-flash devices, so we do it on all parts.
58                 bsf 0xa6, 7, 0
59                 bcf 0xa6, 6, 0
60
61         _endasm ;
62     
63         _do_cinit();
64
65         /* Call the user's main routine */
66         main ();
67
68 loop:
69         /* return from main will lock up */
70         goto loop;
71 }
72
73
74 /* the cinit table will be filled by the linker */
75 extern code struct
76 {
77   unsigned short num_init;
78   struct _init_entry {
79     unsigned long from;
80     unsigned long to;
81     unsigned long size;
82   } entries[];
83 } cinit;
84
85
86 #define tblrdpostinc    tblrd*+
87
88
89 /* the variable initialisation routine */
90 void _do_cinit (void)
91 {
92   /*
93    * we'll make the assumption in the following code that these statics
94    * will be allocated into the same bank.
95    */
96   static short long prom;
97   static unsigned short curr_byte;
98   static unsigned short curr_entry;
99   static short long data_ptr;
100
101
102         /* TBLPTR = &cinit */
103         _asm
104                 movlw low(_cinit)
105                 movwf _TBLPTRL, 0
106                 movlw high(_cinit)
107                 movwf _TBLPTRH, 0
108                 movlw upper(_cinit)
109                 movwf _TBLPTRU, 0
110         _endasm;
111
112         
113         /* curr_entry = cinit.num_init */
114         _asm
115                 movlb __do_cinit_data_ptr_1_1
116                 tblrdpostinc
117                 movf _TABLAT, 0, 0
118                 movwf __do_cinit_curr_entry_1_1, 1
119                 tblrdpostinc
120                 movf _TABLAT, 0, 0
121                 movwf __do_cinit_curr_entry_1_1+1, 1
122         _endasm;
123
124
125         //while (curr_entry) {
126         _asm
127 test:
128         bnz done1
129         tstfsz __do_cinit_curr_entry_1_1, 1
130         bra cont1
131
132 done1:
133         goto done
134
135 cont1:
136         _endasm;
137
138
139       /* Count down so we only have to look up the data in _cinit
140        * once.
141        *
142        * At this point we know that TBLPTR points to the top of the current
143        * entry in _cinit, so we can just start reading the from, to, and
144        * size values.
145        */
146         _asm
147                 
148                 /* read the source address low */
149                 tblrdpostinc
150                 movf _TABLAT, 0, 0
151                 movwf __do_cinit_prom_1_1, 1
152                 
153                 /* source address high */
154                 tblrdpostinc
155                 movf _TABLAT, 0, 0
156                 movwf __do_cinit_prom_1_1 + 1, 1
157
158                 /* source address upper */
159                 tblrdpostinc
160                 movf _TABLAT, 0, 0
161                 movwf __do_cinit_prom_1_1 + 2, 1
162
163                 /* skip a byte since it's stored as a 32bit int */
164                 tblrdpostinc
165
166                 /* read the destination address directly into FSR0 */
167                 /* destination address low */
168                 tblrdpostinc
169                 movf _TABLAT, 0, 0
170                 movwf _FSR0L, 0
171
172                 /* destination address high */
173                 tblrdpostinc
174                 movf _TABLAT, 0, 0
175                 movwf _FSR0H, 0
176
177                 /* skip two bytes since it's stored as a 32bit int */
178                 tblrdpostinc
179                 tblrdpostinc
180
181                 /* read the destination address directly into FSR0 */
182                 tblrdpostinc
183                 movf _TABLAT, 0, 0
184                 movwf __do_cinit_curr_byte_1_1, 1
185                 tblrdpostinc
186                 movf _TABLAT, 0, 0
187                 movwf __do_cinit_curr_byte_1_1+1, 1
188
189                 /* skip two bytes since it's stored as a 32bit int */
190                 tblrdpostinc
191                 tblrdpostinc
192         _endasm;
193
194         //prom = data_ptr->from;
195         //FSR0 = data_ptr->to;
196         //curr_byte = (unsigned short) data_ptr->size;
197         /* the table pointer now points to the next entry. Save it
198          * off since we'll be using the table pointer to do the copying
199          * for the entry */
200   
201         /*  data_ptr = TBLPTR */
202         _asm
203                 movff _TBLPTRL, __do_cinit_data_ptr_1_1
204                 movff _TBLPTRH, __do_cinit_data_ptr_1_1 + 1
205                 movff _TBLPTRU, __do_cinit_data_ptr_1_1 + 2
206         _endasm;
207   
208       
209         /* now assign the source address to the table pointer */
210         /*  TBLPTR = prom */
211         _asm
212                 movff __do_cinit_prom_1_1, _TBLPTRL
213                 movff __do_cinit_prom_1_1 + 1, _TBLPTRH
214                 movff __do_cinit_prom_1_1 + 2, _TBLPTRU
215         _endasm;
216
217         /* do the copy loop */
218         _asm
219
220                 /* determine if we have any more bytes to copy */
221                 movlb __do_cinit_curr_byte_1_1
222                 movf __do_cinit_curr_byte_1_1, 1, 1
223 copy_loop:
224                 bnz copy_one_byte // copy_one_byte
225                 movf __do_cinit_curr_byte_1_1 + 1, 1, 1
226                 bz done_copying
227
228 copy_one_byte:
229                 tblrdpostinc
230                 movf _TABLAT, 0, 0
231                 movwf _POSTINC0, 0
232
233                 /* decrement byte counter */
234                 decf __do_cinit_curr_byte_1_1, 1, 1
235                 bnc copy_loop // copy_loop
236                 decf __do_cinit_curr_byte_1_1 + 1, 1, 1
237
238                 bra copy_loop
239 done_copying:
240         _endasm;
241   
242         /* restore the table pointer for the next entry */
243         /*  TBLPTR = data_ptr */
244         _asm
245                 movff __do_cinit_data_ptr_1_1, _TBLPTRL
246                 movff __do_cinit_data_ptr_1_1 + 1, _TBLPTRH
247                 movff __do_cinit_data_ptr_1_1 + 2, _TBLPTRU
248         _endasm;
249
250   
251         /* next entry... */
252         curr_entry--;
253
254         _asm
255                 goto test;
256
257         /* emit done label */
258 done:
259         _endasm;
260 }
261