legacyexec.inc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. procedure NewList(list: PList);
  42. begin
  43. with list^ do
  44. begin
  45. lh_Head := pNode(@lh_Tail);
  46. lh_Tail := nil;
  47. lh_TailPred := pNode(@lh_Head);
  48. end;
  49. end;
  50. function CreateMsgPort: PMsgPort; public name '_fpc_amiga_createmsgport';
  51. var
  52. sigbit : ShortInt;
  53. msgPort : PMsgPort;
  54. begin
  55. CreateMsgPort:=nil;
  56. sigbit := AllocSignal(-1);
  57. if sigbit = -1 then
  58. exit;
  59. msgPort := execAllocMem(sizeof(TMsgPort),MEMF_CLEAR);
  60. if not assigned(msgPort) then
  61. begin
  62. FreeSignal(sigbit);
  63. exit;
  64. end;
  65. with msgPort^ do
  66. begin
  67. mp_Node.ln_Name := nil;
  68. mp_Node.ln_Pri := 0;
  69. mp_Node.ln_Type := 4;
  70. mp_Flags := 0;
  71. mp_SigBit := sigbit;
  72. mp_SigTask := FindTask(nil);
  73. end;
  74. NewList(addr(msgPort^.mp_MsgList));
  75. CreateMsgPort := msgPort;
  76. end;
  77. procedure DeleteMsgPort(const msgPort: PMsgPort); public name '_fpc_amiga_deletemsgport';
  78. begin
  79. if assigned(msgPort) then
  80. with msgPort^ do
  81. begin
  82. mp_Node.ln_Type := $FF;
  83. mp_MsgList.lh_Head := PNode(PtrUInt(-1));
  84. FreeSignal(mp_SigBit);
  85. execFreeMem(msgPort, sizeof(TMsgPort));
  86. end;
  87. end;
  88. function CreateIORequest(const msgPort: PMsgPort; size: Longint): PIORequest; public name '_fpc_amiga_createiorequest';
  89. var
  90. IOReq: PIORequest;
  91. begin
  92. IOReq:=nil;
  93. if assigned(msgPort) then
  94. begin
  95. IOReq := execAllocMem(size, MEMF_CLEAR);
  96. if assigned(IOReq) then
  97. with IOReq^ do
  98. begin
  99. io_Message.mn_Node.ln_Type := 7;
  100. io_Message.mn_Length := size;
  101. io_Message.mn_ReplyPort := msgPort;
  102. end;
  103. end;
  104. CreateIORequest := IOReq;
  105. end;
  106. procedure DeleteIORequest(IOReq: PIORequest); public name '_fpc_amiga_deleteiorequest';
  107. begin
  108. if assigned(IOReq) then
  109. with IOReq^ do
  110. begin
  111. io_Message.mn_Node.ln_Type := $FF;
  112. io_Message.mn_ReplyPort := PMsgPort(PtrUInt(-1));
  113. io_Device := PDevice(PtrUInt(-1));
  114. execFreeMem(ioReq, io_Message.mn_Length);
  115. end;
  116. end;
  117. type
  118. TAmigaLegacyPoolEntry = record
  119. pe_node: TMinNode;
  120. pe_size: dword;
  121. end;
  122. PAmigaLegacyPoolEntry = ^TAmigaLegacyPoolEntry;
  123. TAmigaLegacyPool = record
  124. pool_requirements: cardinal;
  125. pool_chain: PAmigaLegacyPoolEntry;
  126. end;
  127. PAmigaLegacyPool = ^TAmigaLegacyPool;
  128. function CreatePool(requirements: Cardinal;
  129. puddleSize : Cardinal;
  130. threshSize : Cardinal): Pointer; public name '_fpc_amiga_createpool';
  131. var
  132. p: PAmigaLegacyPool;
  133. begin
  134. p:=execAllocMem(sizeof(TAmigaLegacyPool),requirements);
  135. if p <> nil then
  136. begin
  137. p^.pool_requirements:=requirements;
  138. p^.pool_chain:=nil;
  139. end;
  140. CreatePool:=p;
  141. end;
  142. function AllocPooled(poolHeader: Pointer;
  143. memSize : Cardinal): Pointer; public name '_fpc_amiga_allocpooled';
  144. var
  145. p: PAmigaLegacyPoolEntry;
  146. ph: PAmigaLegacyPool absolute poolHeader;
  147. begin
  148. p:=execAllocMem(memSize + sizeof(TAmigaLegacyPoolEntry), ph^.pool_requirements);
  149. if p <> nil then
  150. begin
  151. if ph^.pool_chain <> nil then
  152. ph^.pool_chain^.pe_node.mln_Pred:=PMinNode(p);
  153. p^.pe_node.mln_Succ:=PMinNode(ph^.pool_chain);
  154. p^.pe_node.mln_Pred:=nil;
  155. p^.pe_size:=memSize + sizeof(TAmigaLegacyPoolEntry);
  156. ph^.pool_chain:=p;
  157. inc(pointer(p),sizeof(TAmigaLegacyPoolEntry));
  158. end;
  159. AllocPooled:=p;
  160. end;
  161. procedure FreePooled(poolHeader: Pointer;
  162. memory : Pointer;
  163. memSize : Cardinal); public name '_fpc_amiga_freepooled';
  164. var
  165. p: PAmigaLegacyPoolEntry;
  166. ph: PAmigaLegacyPool absolute poolHeader;
  167. begin
  168. if memory <> nil then
  169. begin
  170. p:=PAmigaLegacyPoolEntry(memory-sizeof(TAmigaLegacyPoolEntry));
  171. if p^.pe_node.mln_Succ <> nil then
  172. PAmigaLegacyPoolEntry(p^.pe_node.mln_Succ)^.pe_node.mln_Pred:=p^.pe_node.mln_Pred;
  173. if p^.pe_node.mln_Pred <> nil then
  174. PAmigaLegacyPoolEntry(p^.pe_node.mln_Pred)^.pe_node.mln_Succ:=p^.pe_node.mln_Succ;
  175. if p = ph^.pool_chain then
  176. ph^.pool_chain:=PAmigaLegacyPoolEntry(p^.pe_node.mln_Succ);
  177. execFreeMem(p,p^.pe_size);
  178. end;
  179. end;
  180. procedure DeletePool(poolHeader: Pointer); public name '_fpc_amiga_deletepool';
  181. var
  182. p: PAmigaLegacyPool absolute poolHeader;
  183. pe: PAmigaLegacyPoolEntry;
  184. begin
  185. if p <> nil then
  186. begin
  187. while p^.pool_chain <> nil do
  188. begin
  189. pe:=p^.pool_chain;
  190. FreePooled(poolHeader, pointer(pe) + sizeof(TAmigaLegacyPoolEntry), pe^.pe_size);
  191. end;
  192. execFreeMem(p,sizeof(TAmigaLegacyPool));
  193. end;
  194. end;
  195. {$IFNDEF AMIGA_V2_0_ONLY}
  196. procedure StackSwap(newStack: PStackSwapStruct); assembler; nostackframe; public name '_fpc_amiga_stackswap';
  197. asm
  198. move.l a6,-(sp)
  199. move.l newStack,-(sp)
  200. move.l AOS_ExecBase,a6
  201. sub.l a1,a1
  202. jsr -294(a6) // FindTask()
  203. move.l d0,-(sp)
  204. move.l AOS_ExecBase,a6
  205. jsr -120(a6) // Disable()
  206. move.l (sp)+,a1 // task
  207. move.l (sp)+,a0 // newStack
  208. move.l 58(a1),d0 // task^.tc_SPLower
  209. move.l (a0),58(a1)
  210. move.l d0,(a0)+
  211. move.l 62(a1),d0 // task^.tc_SPUpper
  212. move.l (a0),62(a1)
  213. move.l d0,(a0)+
  214. move.l (sp)+,a6
  215. move.l (sp)+,d0 // return address
  216. move.l (a0),d1
  217. move.l sp,(a0)
  218. move.l d1,sp
  219. move.l d0,-(sp)
  220. move.l a6,-(sp)
  221. move.l AOS_ExecBase,a6
  222. jsr -126(a6) // Enable()
  223. move.l (sp)+,a6
  224. rts
  225. end;
  226. procedure ObtainSemaphoreShared(sigSem: PSignalSemaphore); public name '_fpc_amiga_obtainsemaphoreshared';
  227. begin
  228. { NOTE: this still needs v33+ (OS v1.2 or later) }
  229. { ObtainSemaphoreShared is used by athreads, and simply replacing
  230. it by ObtainSemaphore works, just with a slight performance hit,
  231. at least in the way it's currently used in athreads. }
  232. ObtainSemaphore(sigSem);
  233. end;
  234. {$ENDIF NOT AMIGA_V2_0_ONLY}