legacyexec.inc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2020 Karoly Balogh, Free Pascal Development team
  4. Amiga exec.library legacy (OS 1.x/2.x) support functions
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {
  12. This unit implements some missing functions of OS 1.x (and some OS 2.x)
  13. exec.library, so the legacy OS support can be implemented with minimal
  14. changes to the normal system unit and common Amiga-like code
  15. Please note that this code doesn't aim to be API feature complete, just
  16. functional enough for the RTL code.
  17. }
  18. {$IFNDEF AMIGA_V2_0_ONLY}
  19. function AllocVec(byteSize : Cardinal;
  20. requirements: Cardinal): Pointer; public name '_fpc_amiga_allocvec';
  21. var
  22. p: pointer;
  23. begin
  24. p:=execAllocMem(byteSize + sizeof(DWord), requirements);
  25. if p <> nil then
  26. begin
  27. PDWord(p)^:=byteSize + sizeof(DWord);
  28. inc(p, sizeof(DWord));
  29. end;
  30. AllocVec:=p;
  31. end;
  32. procedure FreeVec(memoryBlock: Pointer); public name '_fpc_amiga_freevec';
  33. begin
  34. if memoryBlock <> nil then
  35. begin
  36. dec(memoryBlock, sizeof(DWord));
  37. execFreeMem(memoryBlock,PDWord(memoryBlock)^);
  38. end;
  39. end;
  40. {$ENDIF NOT AMIGA_V2_0_ONLY}
  41. type
  42. TAmigaLegacyPoolEntry = record
  43. pe_node: TMinNode;
  44. pe_size: dword;
  45. end;
  46. PAmigaLegacyPoolEntry = ^TAmigaLegacyPoolEntry;
  47. TAmigaLegacyPool = record
  48. pool_requirements: cardinal;
  49. pool_chain: PAmigaLegacyPoolEntry;
  50. end;
  51. PAmigaLegacyPool = ^TAmigaLegacyPool;
  52. function CreatePool(requirements: Cardinal;
  53. puddleSize : Cardinal;
  54. threshSize : Cardinal): Pointer; public name '_fpc_amiga_createpool';
  55. var
  56. p: PAmigaLegacyPool;
  57. begin
  58. p:=execAllocMem(sizeof(TAmigaLegacyPool),requirements);
  59. if p <> nil then
  60. begin
  61. p^.pool_requirements:=requirements;
  62. p^.pool_chain:=nil;
  63. end;
  64. CreatePool:=p;
  65. end;
  66. function AllocPooled(poolHeader: Pointer;
  67. memSize : Cardinal): Pointer; public name '_fpc_amiga_allocpooled';
  68. var
  69. p: PAmigaLegacyPoolEntry;
  70. ph: PAmigaLegacyPool absolute poolHeader;
  71. begin
  72. p:=execAllocMem(memSize + sizeof(TAmigaLegacyPoolEntry), ph^.pool_requirements);
  73. if p <> nil then
  74. begin
  75. if ph^.pool_chain <> nil then
  76. ph^.pool_chain^.pe_node.mln_Pred:=PMinNode(p);
  77. p^.pe_node.mln_Succ:=PMinNode(ph^.pool_chain);
  78. p^.pe_node.mln_Pred:=nil;
  79. p^.pe_size:=memSize + sizeof(TAmigaLegacyPoolEntry);
  80. ph^.pool_chain:=p;
  81. inc(pointer(p),sizeof(TAmigaLegacyPoolEntry));
  82. end;
  83. AllocPooled:=p;
  84. end;
  85. procedure FreePooled(poolHeader: Pointer;
  86. memory : Pointer;
  87. memSize : Cardinal); public name '_fpc_amiga_freepooled';
  88. var
  89. p: PAmigaLegacyPoolEntry;
  90. ph: PAmigaLegacyPool absolute poolHeader;
  91. begin
  92. if memory <> nil then
  93. begin
  94. p:=PAmigaLegacyPoolEntry(memory-sizeof(TAmigaLegacyPoolEntry));
  95. if p^.pe_node.mln_Succ <> nil then
  96. PAmigaLegacyPoolEntry(p^.pe_node.mln_Succ)^.pe_node.mln_Pred:=p^.pe_node.mln_Pred;
  97. if p^.pe_node.mln_Pred <> nil then
  98. PAmigaLegacyPoolEntry(p^.pe_node.mln_Pred)^.pe_node.mln_Succ:=p^.pe_node.mln_Succ;
  99. if p = ph^.pool_chain then
  100. ph^.pool_chain:=PAmigaLegacyPoolEntry(p^.pe_node.mln_Succ);
  101. execFreeMem(p,p^.pe_size);
  102. end;
  103. end;
  104. procedure DeletePool(poolHeader: Pointer); public name '_fpc_amiga_deletepool';
  105. var
  106. p: PAmigaLegacyPool absolute poolHeader;
  107. pe: PAmigaLegacyPoolEntry;
  108. begin
  109. if p <> nil then
  110. begin
  111. while p^.pool_chain <> nil do
  112. begin
  113. pe:=p^.pool_chain;
  114. FreePooled(poolHeader, pointer(pe) + sizeof(TAmigaLegacyPoolEntry), pe^.pe_size);
  115. end;
  116. execFreeMem(p,sizeof(TAmigaLegacyPool));
  117. end;
  118. end;
  119. {$IFNDEF AMIGA_V2_0_ONLY}
  120. procedure StackSwap(newStack: PStackSwapStruct); assembler; nostackframe; public name '_fpc_amiga_stackswap';
  121. asm
  122. move.l a6,-(sp)
  123. move.l newStack,-(sp)
  124. move.l AOS_ExecBase,a6
  125. sub.l a1,a1
  126. jsr -294(a6) // FindTask()
  127. move.l d0,-(sp)
  128. move.l AOS_ExecBase,a6
  129. jsr -120(a6) // Disable()
  130. move.l (sp)+,a1 // task
  131. move.l (sp)+,a0 // newStack
  132. move.l 58(a1),d0 // task^.tc_SPLower
  133. move.l (a0),58(a1)
  134. move.l d0,(a0)+
  135. move.l 62(a1),d0 // task^.tc_SPUpper
  136. move.l (a0),62(a1)
  137. move.l d0,(a0)+
  138. move.l (sp)+,a6
  139. move.l (sp)+,d0 // return address
  140. move.l (a0),d1
  141. move.l sp,(a0)
  142. move.l d1,sp
  143. move.l d0,-(sp)
  144. move.l a6,-(sp)
  145. move.l AOS_ExecBase,a6
  146. jsr -126(a6) // Enable()
  147. move.l (sp)+,a6
  148. rts
  149. end;
  150. procedure ObtainSemaphoreShared(sigSem: PSignalSemaphore); public name '_fpc_amiga_obtainsemaphoreshared';
  151. begin
  152. { NOTE: this still needs v33+ (OS v1.2 or later) }
  153. { ObtainSemaphoreShared is used by athreads, and simply replacing
  154. it by ObtainSemaphore works, just with a slight performance hit,
  155. at least in the way it's currently used in athreads. }
  156. ObtainSemaphore(sigSem);
  157. end;
  158. {$ENDIF NOT AMIGA_V2_0_ONLY}