avr.inc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2008 by the Free Pascal development team.
  4. Processor dependent implementation for the system unit for
  5. AVR
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$asmmode gas}
  13. const
  14. {$i cpuinnr.inc}
  15. { Reads SREG and then disables interrupts, returns contents of SREG }
  16. function avr_save: byte;[INTERNPROC: in_avr_save];
  17. { Restores SREG }
  18. procedure avr_restore(old_sreg: byte); [INTERNPROC: in_avr_restore];
  19. procedure fpc_cpuinit;{$ifdef SYSTEMINLINE}inline;{$endif}
  20. begin
  21. end;
  22. {$if not(defined(CPUAVR_16_REGS)) and defined(CPUAVR_HAS_MOVW)}
  23. {$define FPC_SYSTEM_HAS_MOVE}
  24. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE']; assembler; nostackframe;
  25. asm
  26. push r28
  27. push r29
  28. movw r26, r24 // Src=X
  29. movw r28, r22 // Dest=Y
  30. movw r30, r20 // Count=Z
  31. cp r1, r30
  32. cpc r1, r31
  33. brge .Lexit // if 0 >= Count
  34. cp r28, r26
  35. cpc r29, r27
  36. breq .Lexit // if dest = source
  37. brlo .LForwardMove // if dest < source
  38. // Add count to both pointers
  39. add r26, r30
  40. adc r27, r31
  41. add r28, r30
  42. adc r29, r31
  43. .LBackwardMove:
  44. ld r18, -X
  45. st -Y, r18
  46. sbiw r30, 1
  47. brne .LBackwardMove
  48. rjmp .Lexit
  49. .LForwardMove:
  50. ld r18, X+
  51. st Y+, r18
  52. sbiw r30, 1
  53. brne .LForwardMove
  54. .Lexit:
  55. pop r29
  56. pop r28
  57. end;
  58. {$endif not(defined(CPUAVR_16_REGS)) and defined(CPUAVR_HAS_MOVW)}
  59. {$define FPC_SYSTEM_HAS_FILLCHAR}
  60. Procedure FillChar(var x;count:SizeInt;value:byte);
  61. var
  62. pdest,pend : pbyte;
  63. v : ptruint;
  64. begin
  65. if count <= 0 then
  66. exit;
  67. pdest:=@x;
  68. pend:=pdest+count;
  69. while pdest<pend do
  70. begin
  71. pdest^:=value;
  72. inc(pdest);
  73. end;
  74. end;
  75. {$IFNDEF INTERNAL_BACKTRACE}
  76. {$define FPC_SYSTEM_HAS_GET_FRAME}
  77. { this is never going to work on avr properly this way, so inline and return nil so the compiler
  78. can optimize it }
  79. function get_frame:pointer;inline;
  80. begin
  81. result:=nil;
  82. end;
  83. {$ENDIF not INTERNAL_BACKTRACE}
  84. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  85. { this is never going to work on avr properly this way, so inline and return nil so the compiler
  86. can optimize it }
  87. function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;inline;
  88. begin
  89. result:=nil;
  90. end;
  91. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  92. { this is never going to work on avr properly this way, so inline and return nil so the compiler
  93. can optimize it }
  94. function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;inline;
  95. begin
  96. result:=nil;
  97. end;
  98. {$define FPC_SYSTEM_HAS_SPTR}
  99. Function Sptr : pointer;assembler;nostackframe;
  100. asm
  101. in r24, 0x3d
  102. in r25, 0x3e
  103. end;
  104. function InterLockedDecrement (var Target: longint) : longint;
  105. var
  106. temp_sreg : byte;
  107. begin
  108. { block interrupts }
  109. temp_sreg:=avr_save();
  110. Result:=Target-1;
  111. Target:=Result;
  112. { release interrupts }
  113. avr_restore(temp_sreg);
  114. end;
  115. function InterLockedIncrement (var Target: longint) : longint;
  116. var
  117. temp_sreg : byte;
  118. begin
  119. { block interrupts }
  120. temp_sreg:=avr_save();
  121. Result:=Target+1;
  122. Target:=Result;
  123. { release interrupts }
  124. avr_restore(temp_sreg);
  125. end;
  126. function InterLockedExchange (var Target: longint;Source : longint) : longint;
  127. var
  128. temp_sreg : byte;
  129. begin
  130. { block interrupts }
  131. temp_sreg:=avr_save();
  132. Result:=Target;
  133. Target:=Source;
  134. { release interrupts }
  135. avr_restore(temp_sreg);
  136. end;
  137. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;
  138. var
  139. temp_sreg : byte;
  140. begin
  141. { block interrupts }
  142. temp_sreg:=avr_save();
  143. Result:=Target;
  144. if Result=Comperand then
  145. Target:=NewValue;
  146. { release interrupts }
  147. avr_restore(temp_sreg);
  148. end;
  149. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
  150. var
  151. temp_sreg : byte;
  152. begin
  153. { block interrupts }
  154. temp_sreg:=avr_save();
  155. Result:=Target;
  156. Target:=Result+Source;
  157. { release interrupts }
  158. avr_restore(temp_sreg);
  159. end;
  160. function InterLockedDecrement (var Target: smallint) : smallint;
  161. var
  162. temp_sreg : byte;
  163. begin
  164. { block interrupts }
  165. temp_sreg:=avr_save();
  166. Result:=Target-1;
  167. Target:=Result;
  168. { release interrupts }
  169. avr_restore(temp_sreg);
  170. end;
  171. function InterLockedIncrement (var Target: smallint) : smallint;
  172. var
  173. temp_sreg : byte;
  174. begin
  175. { block interrupts }
  176. temp_sreg:=avr_save();
  177. Result:=Target+1;
  178. Target:=Result;
  179. { release interrupts }
  180. avr_restore(temp_sreg);
  181. end;
  182. function InterLockedExchange (var Target: smallint;Source : smallint) : smallint;
  183. var
  184. temp_sreg : byte;
  185. begin
  186. { block interrupts }
  187. temp_sreg:=avr_save();
  188. Result:=Target;
  189. Target:=Source;
  190. { release interrupts }
  191. avr_restore(temp_sreg);
  192. end;
  193. function InterlockedCompareExchange(var Target: smallint; NewValue: smallint; Comperand: smallint): smallint;
  194. var
  195. temp_sreg : byte;
  196. begin
  197. { block interrupts }
  198. temp_sreg:=avr_save();
  199. Result:=Target;
  200. if Result=Comperand then
  201. Target:=NewValue;
  202. { release interrupts }
  203. avr_restore(temp_sreg);
  204. end;
  205. function InterLockedExchangeAdd (var Target: smallint;Source : smallint) : smallint;
  206. var
  207. temp_sreg : byte;
  208. begin
  209. { block interrupts }
  210. temp_sreg:=avr_save();
  211. Result:=Target;
  212. Target:=Result+Source;
  213. { release interrupts }
  214. avr_restore(temp_sreg);
  215. end;
  216. {include hand-optimized assembler code}
  217. {$i math.inc}