avr.inc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. function get_frame:pointer;assembler;nostackframe;
  78. asm
  79. end;
  80. {$ENDIF not INTERNAL_BACKTRACE}
  81. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  82. function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
  83. asm
  84. end;
  85. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  86. function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
  87. asm
  88. end;
  89. {$define FPC_SYSTEM_HAS_SPTR}
  90. Function Sptr : pointer;assembler;nostackframe;
  91. asm
  92. in r24, 0x3d
  93. in r25, 0x3e
  94. end;
  95. function InterLockedDecrement (var Target: longint) : longint;
  96. var
  97. temp_sreg : byte;
  98. begin
  99. { block interrupts }
  100. temp_sreg:=avr_save();
  101. Result:=Target-1;
  102. Target:=Result;
  103. { release interrupts }
  104. avr_restore(temp_sreg);
  105. end;
  106. function InterLockedIncrement (var Target: longint) : longint;
  107. var
  108. temp_sreg : byte;
  109. begin
  110. { block interrupts }
  111. temp_sreg:=avr_save();
  112. Result:=Target+1;
  113. Target:=Result;
  114. { release interrupts }
  115. avr_restore(temp_sreg);
  116. end;
  117. function InterLockedExchange (var Target: longint;Source : longint) : longint;
  118. var
  119. temp_sreg : byte;
  120. begin
  121. { block interrupts }
  122. temp_sreg:=avr_save();
  123. Result:=Target;
  124. Target:=Source;
  125. { release interrupts }
  126. avr_restore(temp_sreg);
  127. end;
  128. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;
  129. var
  130. temp_sreg : byte;
  131. begin
  132. { block interrupts }
  133. temp_sreg:=avr_save();
  134. Result:=Target;
  135. if Result=Comperand then
  136. Target:=NewValue;
  137. { release interrupts }
  138. avr_restore(temp_sreg);
  139. end;
  140. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
  141. var
  142. temp_sreg : byte;
  143. begin
  144. { block interrupts }
  145. temp_sreg:=avr_save();
  146. Result:=Target;
  147. Target:=Result+Source;
  148. { release interrupts }
  149. avr_restore(temp_sreg);
  150. end;
  151. function InterLockedDecrement (var Target: smallint) : smallint;
  152. var
  153. temp_sreg : byte;
  154. begin
  155. { block interrupts }
  156. temp_sreg:=avr_save();
  157. Result:=Target-1;
  158. Target:=Result;
  159. { release interrupts }
  160. avr_restore(temp_sreg);
  161. end;
  162. function InterLockedIncrement (var Target: smallint) : smallint;
  163. var
  164. temp_sreg : byte;
  165. begin
  166. { block interrupts }
  167. temp_sreg:=avr_save();
  168. Result:=Target+1;
  169. Target:=Result;
  170. { release interrupts }
  171. avr_restore(temp_sreg);
  172. end;
  173. function InterLockedExchange (var Target: smallint;Source : smallint) : smallint;
  174. var
  175. temp_sreg : byte;
  176. begin
  177. { block interrupts }
  178. temp_sreg:=avr_save();
  179. Result:=Target;
  180. Target:=Source;
  181. { release interrupts }
  182. avr_restore(temp_sreg);
  183. end;
  184. function InterlockedCompareExchange(var Target: smallint; NewValue: smallint; Comperand: smallint): smallint;
  185. var
  186. temp_sreg : byte;
  187. begin
  188. { block interrupts }
  189. temp_sreg:=avr_save();
  190. Result:=Target;
  191. if Result=Comperand then
  192. Target:=NewValue;
  193. { release interrupts }
  194. avr_restore(temp_sreg);
  195. end;
  196. function InterLockedExchangeAdd (var Target: smallint;Source : smallint) : smallint;
  197. var
  198. temp_sreg : byte;
  199. begin
  200. { block interrupts }
  201. temp_sreg:=avr_save();
  202. Result:=Target;
  203. Target:=Result+Source;
  204. { release interrupts }
  205. avr_restore(temp_sreg);
  206. end;
  207. {include hand-optimized assembler code}
  208. {$i math.inc}