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