crt0i-rloc.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by the
  12. * Free Software Foundation; either version 2, or (at your option) any
  13. * later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. *
  24. * In other words, you are welcome to use, share and improve this program.
  25. * You are forbidden to forbid anyone else to use, share and improve
  26. * what you give them. Help stamp out software-hoarding!
  27. *
  28. * $Id: crt0i.c 3714 2005-04-02 13:13:53Z vrokas $
  29. */
  30. extern stack;
  31. extern stack_end;
  32. extern TBLPTRU;
  33. extern TBLPTRH;
  34. extern TBLPTRL;
  35. extern FSR0L;
  36. extern FSR0H;
  37. extern TABLAT;
  38. extern POSTINC0;
  39. #if 1
  40. /* global variable for forcing gplink to add _cinit section */
  41. char __uflags = 0;
  42. #endif
  43. /* external reference to the user's main routine */
  44. extern void main (void);
  45. /* prototype for the startup function */
  46. void _entry (void) __naked __interrupt 0;
  47. void _startup (void) __naked;
  48. /* prototype for the initialized data setup */
  49. void _do_cinit (void) __naked;
  50. /*
  51. * entry function, placed at interrupt vector 0 (RESET)
  52. */
  53. void _entry (void) __naked __interrupt 0
  54. {
  55. __asm goto __startup __endasm;
  56. }
  57. void _startup (void) __naked
  58. {
  59. __asm
  60. // Initialize the stack pointer
  61. lfsr 1, _stack_end
  62. lfsr 2, _stack_end
  63. clrf _TBLPTRU, 0 // 1st silicon doesn't do this on POR
  64. // initialize the flash memory access configuration. this is harmless
  65. // for non-flash devices, so we do it on all parts.
  66. bsf 0xa6, 7, 0
  67. bcf 0xa6, 6, 0
  68. __endasm ;
  69. _do_cinit();
  70. /* Call the user's main routine */
  71. main();
  72. loop:
  73. /* return from main will lock up */
  74. goto loop;
  75. }
  76. /* the cinit table will be filled by the linker */
  77. extern __code struct
  78. {
  79. unsigned short num_init;
  80. struct _init_entry {
  81. unsigned long from;
  82. unsigned long to;
  83. unsigned long size;
  84. } entries[];
  85. } cinit;
  86. #define TBLRDPOSTINC tblrd*+
  87. #define prom 0x00 /* 0x00 0x01 0x02*/
  88. #define curr_byte 0x03 /* 0x03 0x04 */
  89. #define curr_entry 0x05 /* 0x05 0x06 */
  90. #define data_ptr 0x07 /* 0x07 0x08 0x09 */
  91. /*
  92. * static short long _do_cinit_prom;
  93. * static unsigned short _do_cinit_curr_byte;
  94. * static unsigned short _do_cinit_curr_entry;
  95. * static short long _do_cinit_data_ptr;
  96. */
  97. /* the variable initialisation routine */
  98. void _do_cinit (void) __naked
  99. {
  100. /*
  101. * access registers 0x00 - 0x09 are not saved in this function
  102. */
  103. __asm
  104. ; TBLPTR = &cinit
  105. movlw low(_cinit)
  106. movwf _TBLPTRL
  107. movlw high(_cinit)
  108. movwf _TBLPTRH
  109. movlw upper(_cinit)
  110. movwf _TBLPTRU
  111. ; curr_entry = cinit.num_init
  112. ; movlb data_ptr
  113. TBLRDPOSTINC
  114. movf _TABLAT, w
  115. movwf curr_entry
  116. TBLRDPOSTINC
  117. movf _TABLAT, w
  118. movwf curr_entry+1
  119. ; while (curr_entry) {
  120. test:
  121. bnz cont1 ;;done1
  122. tstfsz curr_entry, 1
  123. bra cont1
  124. done1:
  125. goto done
  126. cont1:
  127. ; Count down so we only have to look up the data in _cinit once.
  128. ; At this point we know that TBLPTR points to the top of the current
  129. ; entry in _cinit, so we can just start reading the from, to, and
  130. ; size values.
  131. ; read the source address low
  132. TBLRDPOSTINC
  133. movf _TABLAT, w
  134. movwf prom
  135. ; source address high
  136. TBLRDPOSTINC
  137. movf _TABLAT, w
  138. movwf prom + 1
  139. ; source address upper
  140. TBLRDPOSTINC
  141. movf _TABLAT, w
  142. movwf prom + 2
  143. ; skip a byte since it is stored as a 32bit int
  144. TBLRDPOSTINC
  145. ; read the destination address directly into FSR0
  146. ; destination address low
  147. TBLRDPOSTINC
  148. movf _TABLAT, w
  149. movwf _FSR0L
  150. ; destination address high
  151. TBLRDPOSTINC
  152. movf _TABLAT, w
  153. movwf _FSR0H
  154. ; skip two bytes since it is stored as a 32bit int
  155. TBLRDPOSTINC
  156. TBLRDPOSTINC
  157. ; read the size of data to transfer destination address
  158. TBLRDPOSTINC
  159. movf _TABLAT, w
  160. movwf curr_byte
  161. TBLRDPOSTINC
  162. movf _TABLAT, w
  163. movwf curr_byte+1
  164. ; skip two bytes since it is stored as a 32bit int
  165. TBLRDPOSTINC
  166. TBLRDPOSTINC
  167. ; prom = data_ptr->from;
  168. ; FSR0 = data_ptr->to;
  169. ; curr_byte = (unsigned short) data_ptr->size;
  170. ; the table pointer now points to the next entry. Save it
  171. ; off since we will be using the table pointer to do the copying
  172. ; for the entry
  173. ; data_ptr = TBLPTR
  174. movff _TBLPTRL, data_ptr
  175. movff _TBLPTRH, data_ptr + 1
  176. movff _TBLPTRU, data_ptr + 2
  177. ; now assign the source address to the table pointer
  178. ; TBLPTR = prom
  179. movff prom, _TBLPTRL
  180. movff prom + 1, _TBLPTRH
  181. movff prom + 2, _TBLPTRU
  182. ; do the copy loop
  183. ; determine if we have any more bytes to copy
  184. ; movlb curr_byte
  185. movf curr_byte, w
  186. copy_loop:
  187. bnz copy_one_byte ; copy_one_byte
  188. movf curr_byte + 1, w
  189. bz done_copying
  190. copy_one_byte:
  191. TBLRDPOSTINC
  192. movf _TABLAT, w
  193. movwf _POSTINC0
  194. movff _TABLAT, 0xf7e
  195. ; decrement byte counter
  196. decf curr_byte, f
  197. bc copy_loop ; copy_loop
  198. decf curr_byte + 1, f
  199. bra copy_one_byte
  200. done_copying:
  201. ; restore the table pointer for the next entry
  202. ; TBLPTR = data_ptr
  203. movff data_ptr, _TBLPTRL
  204. movff data_ptr + 1, _TBLPTRH
  205. movff data_ptr + 2, _TBLPTRU
  206. decf curr_entry, f
  207. bc do_next
  208. decf curr_entry + 1, f
  209. do_next:
  210. ; next entry...
  211. ; _do_cinit_curr_entry--;
  212. goto test;
  213. ; emit done label
  214. done:
  215. return
  216. __endasm;
  217. }