* device/lib/Makefile.in: removed comment line with model-pic16,
[fw/sdcc] / device / lib / pic16 / startup / crt0iz.c
1 /*
2  * crt0iz.c - SDCC pic16 port runtime start code with
3  *            initialisation and RAM memory zero
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
15 extern TBLPTRU;
16 extern TBLPTRH;
17 extern TBLPTRL;
18 extern FSR0L;
19 extern FSR0H;
20 extern TABLAT;
21 extern POSTINC0;
22 extern POSTDEC0;
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
50                 lfsr 2, _stack
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         /* cleanup the RAM */
61         _asm
62                 /* load FSR0 with top of RAM memory */
63                 movlw 0xff
64                 movwf _FSR0L, 0
65                 movlw 0x0e
66                 movwf _FSR0H, 0
67                 
68                 /* place a 1 at address 0x00, as a marker 
69                  * we haven't reached yet to it */
70                 movlw 1
71                 movwf 0x00, 0
72                 
73                 /* load WREG with zero */
74                 movlw 0x00
75                 
76 clear_loop:
77                 movwf _POSTDEC0, 0
78                 movf 0x00, 1, 0
79                 bnz clear_loop
80         _endasm ;
81
82
83         _do_cinit();
84
85         /* Call the user's main routine */
86         main ();
87
88 loop:
89         /* return from main will lock up */
90         goto loop;
91 }
92
93
94 /* the cinit table will be filled by the linker */
95 extern code struct
96 {
97   unsigned short num_init;
98   struct _init_entry {
99     unsigned long from;
100     unsigned long to;
101     unsigned long size;
102   } entries[];
103 } cinit;
104
105
106 #define tblrdpostinc    tblrd*+
107
108 /* the variable initialisation routine */
109 void _do_cinit (void)
110 {
111   /*
112    * we'll make the assumption in the following code that these statics
113    * will be allocated into the same bank.
114    */
115   static short long prom;
116   static unsigned short curr_byte;
117   static unsigned short curr_entry;
118   static short long data_ptr;
119
120
121         /* TBLPTR = &cinit */
122         _asm
123                 movlw low(_cinit)
124                 movwf _TBLPTRL, 0
125                 movlw high(_cinit)
126                 movwf _TBLPTRH, 0
127                 movlw upper(_cinit)
128                 movwf _TBLPTRU, 0
129         _endasm;
130
131         
132         /* curr_entry = cinit.num_init */
133         _asm
134                 movlb __do_cinit_data_ptr_1_1
135                 tblrdpostinc
136                 movf _TABLAT, 0, 0
137                 movwf __do_cinit_curr_entry_1_1, 1
138                 tblrdpostinc
139                 movf _TABLAT, 0, 0
140                 movwf __do_cinit_curr_entry_1_1+1, 1
141         _endasm;
142
143
144         //while (curr_entry) {
145         _asm
146 test:
147         bnz done1
148         tstfsz __do_cinit_curr_entry_1_1, 1
149         bra cont1
150
151 done1:
152         goto done
153
154 cont1:
155         _endasm;
156
157
158       /* Count down so we only have to look up the data in _cinit
159        * once.
160        *
161        * At this point we know that TBLPTR points to the top of the current
162        * entry in _cinit, so we can just start reading the from, to, and
163        * size values.
164        */
165         _asm
166                 
167                 /* read the source address low */
168                 tblrdpostinc
169                 movf _TABLAT, 0, 0
170                 movwf __do_cinit_prom_1_1, 1
171                 
172                 /* source address high */
173                 tblrdpostinc
174                 movf _TABLAT, 0, 0
175                 movwf __do_cinit_prom_1_1 + 1, 1
176
177                 /* source address upper */
178                 tblrdpostinc
179                 movf _TABLAT, 0, 0
180                 movwf __do_cinit_prom_1_1 + 2, 1
181
182                 /* skip a byte since it's stored as a 32bit int */
183                 tblrdpostinc
184
185                 /* read the destination address directly into FSR0 */
186                 /* destination address low */
187                 tblrdpostinc
188                 movf _TABLAT, 0, 0
189                 movwf _FSR0L, 0
190
191                 /* destination address high */
192                 tblrdpostinc
193                 movf _TABLAT, 0, 0
194                 movwf _FSR0H, 0
195
196                 /* skip two bytes since it's stored as a 32bit int */
197                 tblrdpostinc
198                 tblrdpostinc
199
200                 /* read the destination address directly into FSR0 */
201                 tblrdpostinc
202                 movf _TABLAT, 0, 0
203                 movwf __do_cinit_curr_byte_1_1, 1
204                 tblrdpostinc
205                 movf _TABLAT, 0, 0
206                 movwf __do_cinit_curr_byte_1_1+1, 1
207
208                 /* skip two bytes since it's stored as a 32bit int */
209                 tblrdpostinc
210                 tblrdpostinc
211         _endasm;
212
213         //prom = data_ptr->from;
214         //FSR0 = data_ptr->to;
215         //curr_byte = (unsigned short) data_ptr->size;
216         /* the table pointer now points to the next entry. Save it
217          * off since we'll be using the table pointer to do the copying
218          * for the entry */
219   
220         /*  data_ptr = TBLPTR */
221         _asm
222                 movff _TBLPTRL, __do_cinit_data_ptr_1_1
223                 movff _TBLPTRH, __do_cinit_data_ptr_1_1 + 1
224                 movff _TBLPTRU, __do_cinit_data_ptr_1_1 + 2
225         _endasm;
226   
227       
228         /* now assign the source address to the table pointer */
229         /*  TBLPTR = prom */
230         _asm
231                 movff __do_cinit_prom_1_1, _TBLPTRL
232                 movff __do_cinit_prom_1_1 + 1, _TBLPTRH
233                 movff __do_cinit_prom_1_1 + 2, _TBLPTRU
234         _endasm;
235
236         /* do the copy loop */
237         _asm
238
239                 /* determine if we have any more bytes to copy */
240                 movlb __do_cinit_curr_byte_1_1
241                 movf __do_cinit_curr_byte_1_1, 1, 1
242 copy_loop:
243                 bnz copy_one_byte // copy_one_byte
244                 movf __do_cinit_curr_byte_1_1 + 1, 1, 1
245                 bz done_copying
246
247 copy_one_byte:
248                 tblrdpostinc
249                 movf _TABLAT, 0, 0
250                 movwf _POSTINC0, 0
251
252                 /* decrement byte counter */
253                 decf __do_cinit_curr_byte_1_1, 1, 1
254                 bnc copy_loop // copy_loop
255                 decf __do_cinit_curr_byte_1_1 + 1, 1, 1
256
257                 bra copy_loop
258 done_copying:
259         _endasm;
260   
261         /* restore the table pointer for the next entry */
262         /*  TBLPTR = data_ptr */
263         _asm
264                 movff __do_cinit_data_ptr_1_1, _TBLPTRL
265                 movff __do_cinit_data_ptr_1_1 + 1, _TBLPTRH
266                 movff __do_cinit_data_ptr_1_1 + 2, _TBLPTRU
267         _endasm;
268
269   
270         /* next entry... */
271         curr_entry--;
272
273         _asm
274                 goto test;
275
276         /* emit done label */
277 done:
278         _endasm;
279 }
280