LOWLVMOD.JPI 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. (*# call(reg_param => (),
  2. near_call => off,
  3. ds_eq_ss => off) *)
  4. (*# data(near_ptr => off) *)
  5. (*# check(range => off) *)
  6. IMPLEMENTATION MODULE LowLevel;
  7. (*
  8. * REPERTOIRE
  9. * Release 1.6
  10. * By Charles Bradford and Cole Brecheen
  11. * (c) Copyright 1985-1990 PMI
  12. * Portland, Oregon
  13. * All rights reserved
  14. * (503) 236-1788
  15. *
  16. * $Header: D:/logfiles/masters/lowlvmod.jpv 1.3 17 Mar 1991 18:06:52 coleb $
  17. *
  18. *)
  19. (* JPI version *)
  20. IMPORT FAPI;
  21. IMPORT Lib, SYSTEM;
  22. PROCEDURE AddAddr( TheAdr: SYSTEM.ADDRESS; bytes: CARDINAL ):
  23. SYSTEM.ADDRESS;
  24. VAR
  25. tmp : Address8086;
  26. BEGIN
  27. tmp.a := TheAdr;
  28. INC( tmp.off, bytes );
  29. RETURN tmp.a;
  30. END AddAddr;
  31. PROCEDURE BitwiseAnd(val1, val2: WORD): WORD;
  32. BEGIN
  33. RETURN (BITSET(val1) * BITSET(val2));
  34. END BitwiseAnd;
  35. PROCEDURE DecAddr( VAR TheAdr: SYSTEM.ADDRESS; bytes: CARDINAL );
  36. VAR
  37. tmp : Address8086;
  38. BEGIN
  39. tmp.a := TheAdr;
  40. DEC( tmp.off, bytes );
  41. TheAdr := tmp.a;
  42. END DecAddr;
  43. PROCEDURE EMInterrupt( VAR TheRegs : regpack; Function: CARDINAL );
  44. BEGIN
  45. TheRegs.a.h := CHR(Function);
  46. Interrupt( 67H, TheRegs );
  47. END EMInterrupt;
  48. PROCEDURE Fill(dest : SYSTEM.ADDRESS; size : CARDINAL; thefill
  49. : SYSTEM.BYTE);
  50. (* Starting at source address fill with size bytes of thefill *)
  51. BEGIN
  52. Lib.Fill( dest, size, thefill );
  53. END Fill;
  54. PROCEDURE FillWord(dest : SYSTEM.ADDRESS; size : CARDINAL;
  55. thefill : SYSTEM.WORD);
  56. BEGIN
  57. Lib.WordFill( dest, size, thefill );
  58. END FillWord;
  59. PROCEDURE FlaggedError(TheFlags : BITSET) : BOOLEAN;
  60. (*Detects the PC/MS-DOS error signal in the carry flag.*)
  61. BEGIN
  62. RETURN 0 IN TheFlags;
  63. END FlaggedError;
  64. PROCEDURE InByte( port: CARDINAL; VAR value: SYSTEM.BYTE );
  65. BEGIN
  66. value := SYSTEM.In( port );
  67. END InByte;
  68. PROCEDURE IncAddr( VAR TheAdr: SYSTEM.ADDRESS; bytes: CARDINAL );
  69. VAR
  70. tmp : Address8086;
  71. BEGIN
  72. tmp.a := TheAdr;
  73. INC( tmp.off, bytes );
  74. TheAdr := tmp.a;
  75. END IncAddr;
  76. PROCEDURE Interrupt( InterruptNumber: CARDINAL; VAR
  77. TheRegs : regpack );
  78. BEGIN
  79. Lib.Intr( SYSTEM.Registers(TheRegs), InterruptNumber );
  80. END Interrupt;
  81. PROCEDURE InWord( port: CARDINAL; VAR value: SYSTEM.WORD );
  82. VAR
  83. tmp: DataRegister;
  84. BEGIN
  85. tmp.h := CHAR(SYSTEM.In( port ));
  86. tmp.l := CHAR(SYSTEM.In( port ));
  87. value := tmp.x;
  88. END InWord;
  89. PROCEDURE Move(source, dest : SYSTEM.ADDRESS; size : CARDINAL);
  90. (* Copy size bytes from source address to dest address *)
  91. BEGIN
  92. Lib.Move( source, dest, size );
  93. END Move;
  94. PROCEDURE msdos(VAR TheRegs : regpack);
  95. VAR
  96. R : SYSTEM.Registers ;
  97. BEGIN
  98. R := SYSTEM.Registers(TheRegs) ;
  99. (*
  100. Lib.Dos(R);
  101. *)
  102. TheRegs.a.x := R.AX ;
  103. IF (*OutputStatus=Output*) TRUE THEN
  104. TheRegs := regpack(R) ;
  105. END;
  106. TheRegs.flags := BITSET(CARDINAL(R.Flags * {0..7}));
  107. END msdos;
  108. PROCEDURE ofs(TheAddr : SYSTEM.ADDRESS) : CARDINAL;
  109. VAR
  110. bufaddr : Address8086;
  111. BEGIN
  112. RETURN (SYSTEM.Ofs(TheAddr^));
  113. END ofs;
  114. PROCEDURE OutByte( port: CARDINAL; value: SYSTEM.BYTE );
  115. BEGIN
  116. SYSTEM.Out( port, value );
  117. END OutByte;
  118. PROCEDURE OutWord( port: CARDINAL; value: SYSTEM.WORD );
  119. VAR
  120. tmp: DataRegister;
  121. BEGIN
  122. tmp.x := value;
  123. SYSTEM.Out( port, SHORTCARD(tmp.l) );
  124. SYSTEM.Out( port, SHORTCARD(tmp.h) );
  125. END OutWord;
  126. PROCEDURE PeekByte(segm, offs : CARDINAL) : CHAR;
  127. VAR
  128. tmpc : CHAR;
  129. TmpPtr : Address8086;
  130. BEGIN
  131. tmpc := CHAR([segm:offs]^);
  132. RETURN tmpc;
  133. END PeekByte;
  134. PROCEDURE PeekWord(segm, offs : CARDINAL) : CARDINAL;
  135. BEGIN
  136. RETURN CARDINAL([segm:offs]^) ;
  137. END PeekWord;
  138. PROCEDURE PokeByte(TheByte : CHAR; segm, offs : CARDINAL);
  139. TYPE CP = POINTER TO CHAR ;
  140. BEGIN
  141. [segm:offs CP]^ := TheByte ;
  142. END PokeByte;
  143. PROCEDURE PokeWord(TheWord : CARDINAL; segm, offs : CARDINAL);
  144. BEGIN
  145. [segm:offs]^ := WORD(TheWord) ;
  146. END PokeWord;
  147. PROCEDURE Ptr( segment, offset: CARDINAL ): SYSTEM.ADDRESS;
  148. VAR
  149. tmp: Address8086;
  150. BEGIN
  151. (*
  152. tmp.off := offset;
  153. tmp.seg := segment;
  154. RETURN tmp.a;
  155. *)
  156. RETURN [segment:offset];
  157. END Ptr;
  158. PROCEDURE ScanEQ(size : INTEGER; lookfor : SYSTEM.BYTE; start :
  159. SYSTEM.ADDRESS) : INTEGER;
  160. (* Starting at the address start, scan size bytes at most,
  161. looking for lookfor. If size is negative, look backwards
  162. from start. Result is number of bytes skipped to get to
  163. lookfor, or size if not found *)
  164. BEGIN
  165. IF size>=0 THEN
  166. RETURN INTEGER(Lib.ScanR(start,CARDINAL(size),lookfor));
  167. ELSE
  168. RETURN -INTEGER(Lib.ScanL(start,CARDINAL(-size),lookfor));
  169. END;
  170. END ScanEQ;
  171. PROCEDURE ScanNE(size : INTEGER; lookfor : SYSTEM.BYTE; start :
  172. SYSTEM.ADDRESS) : INTEGER;
  173. (* Starting at the address start, scan size bytes at most,
  174. until find a BYTE unequal to lookfor. If size is negative,
  175. look backwards from start. Result is number of bytes
  176. skipped to get to lookfor, or size if not found *)
  177. BEGIN
  178. IF size>=0 THEN
  179. RETURN INTEGER(Lib.ScanNeR(start,CARDINAL(size),lookfor));
  180. ELSE
  181. RETURN -INTEGER(Lib.ScanNeL(start,CARDINAL(-size),lookfor));
  182. END;
  183. END ScanNE;
  184. PROCEDURE seg(TheAddr : SYSTEM.ADDRESS) : CARDINAL;
  185. VAR
  186. bufaddr : Address8086;
  187. BEGIN
  188. RETURN (SYSTEM.Seg(TheAddr^));
  189. END seg;
  190. PROCEDURE ShiftArrayLeft( TheAdr: SYSTEM.ADDRESS; TheSize,
  191. distance: CARDINAL );
  192. BEGIN
  193. IF distance < TheSize THEN
  194. Move( SYSTEM.ADDRESS(LONGCARD(TheAdr) +
  195. LONGCARD(distance)), TheAdr, TheSize - distance );
  196. END;
  197. END ShiftArrayLeft;
  198. PROCEDURE ShiftArrayRight( TheAdr: SYSTEM.ADDRESS; TheSize,
  199. distance: CARDINAL );
  200. BEGIN
  201. (*JPI M2 can use Move when copying even in this direction.*)
  202. IF distance < TheSize THEN
  203. Move( TheAdr, SYSTEM.ADDRESS(LONGCARD(TheAdr) + LONGCARD(distance)),
  204. TheSize - distance );
  205. END;
  206. END ShiftArrayRight;
  207. PROCEDURE ShiftLeft(VAR TheWord : SYSTEM.WORD; HowMany : CARDINAL);
  208. BEGIN
  209. TheWord := CARDINAL(TheWord) << HowMany;
  210. END ShiftLeft;
  211. PROCEDURE ShiftRight(VAR TheWord : SYSTEM.WORD; HowMany : CARDINAL);
  212. BEGIN
  213. TheWord := CARDINAL(TheWord) >> HowMany;
  214. END ShiftRight;
  215. PROCEDURE SubAddr( TheAdr: SYSTEM.ADDRESS; bytes: CARDINAL ): SYSTEM.ADDRESS;
  216. VAR
  217. tmp : Address8086;
  218. BEGIN
  219. tmp.a := TheAdr;
  220. DEC( tmp.off, bytes );
  221. RETURN tmp.a;
  222. END SubAddr;
  223. PROCEDURE VideoInterrupt(VAR TheRegs : regpack);
  224. BEGIN
  225. Interrupt(10H, TheRegs);
  226. END VideoInterrupt;
  227. (*
  228. TYPE CODE = ARRAY[0..60] OF SHORTCARD;
  229. CONST CodeArray = CODE(
  230. 055H, (* PUSH BP *)
  231. 089H,0E5H, (* MOV BP,SP *)
  232. 056H, (* PUSH SI *)
  233. 057H, (* PUSH DI *)
  234. 01EH, (* PUSH DS *)
  235. 006H, (* PUSH ES *)
  236. 08BH,04EH,006H, (* MOV CX,[BP+06] *)
  237. 0C4H,07EH,008H, (* LES DI,[BP+08] *)
  238. 0C5H,076H,00CH, (* LDS SI,[BP+0C] *)
  239. 0BAH,0DAH,003H, (* MOV DX,03DA *)
  240. (*Top1:*) 0ECH, (* IN AL,DX ; wait until Vert retrace *)
  241. 0A8H,008H, (* TEST AL,08 ; not in progress *)
  242. 075H,0FBH, (* JNZ Top1 *)
  243. 0F7H,0C1H,0FFH,0FFH, (* TEST CX,FFFF *)
  244. (*CHKH:*) 074H,017H, (* JZ END1 ; exit if nothing to write *)
  245. (*TOP2:*) 0ECH, (* IN AL,DX ; wait until Horiz. retrace *)
  246. 0A8H,001H, (* TEST AL,01 ; not in progress *)
  247. 074H,0FBH, (* JZ Top2 *)
  248. 0ECH, (* IN AL,DX ; IF in Vertical retrace *)
  249. 0A8H,008H, (* TEST AL,08 ; goto block move *)
  250. 075H,00BH, (* JNZ TopV *)
  251. 0FAH, (* CLI *)
  252. (*TOPH:*) 0ECH, (* IN AL,DX ; wait until Horiz. retrace*)
  253. 0A8H,001H, (* TEST AL,01 ; in progress *)
  254. 074H,0FBH, (* JZ TopH *)
  255. 0A4H, (* MOVSB ; write one byte *)
  256. 0FBH, (* STI *)
  257. 049H, (* DEC CX ec count and go to top *)
  258. 0EBH,0E9H, (* JMP ChkH *)
  259. (*TOPV:*) 0F3H, (* REPZ ; then move line *)
  260. 0A4H, (* MOVSB *)
  261. (*END1:*) 007H, (* POP ES *)
  262. 01FH, (* POP DS *)
  263. 05FH, (* POP DI *)
  264. 05EH, (* POP SI *)
  265. 05DH, (* POP BP *)
  266. 0CAH,00AH,000H); (* RETF 000A *)
  267. TYPE
  268. MoveDMAProc = PROCEDURE( SYSTEM.ADDRESS, SYSTEM.ADDRESS, CARDINAL);
  269. VAR
  270. MoveDMA : MoveDMAProc;
  271. *)
  272. PROCEDURE WriteDMANoSnow( FromAddr, ToAddr: SYSTEM.ADDRESS; size: CARDINAL);
  273. BEGIN
  274. (* JPI users will have to put up with snow on CGA monitors
  275. until we figure out why the CodeArray approach above
  276. doesn't work, or until we figure out a decent way to
  277. connect this compiler with MASM.*)
  278. Move( FromAddr, ToAddr, size );
  279. END WriteDMANoSnow;
  280. VAR
  281. Initialized : BOOLEAN;
  282. PROCEDURE Init();
  283. BEGIN
  284. IF Initialized THEN
  285. RETURN;
  286. ELSE
  287. Initialized := TRUE;
  288. END;
  289. FAPI._api_init();
  290. END Init;
  291. BEGIN
  292. Initialized := FALSE;
  293. Init();
  294. (*
  295. MoveDMA := MoveDMAProc(ADR(CodeArray));
  296. *)
  297. END LowLevel.