2
0

FoxInterpreterBackend.Mod 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. MODULE FoxInterpreterBackend; (** AUTHOR "fof"; PURPOSE "abstract code interpreter"; *)
  2. IMPORT Basic := FoxBasic, SYSTEM, Intermediate := FoxIntermediateCode, Sections := FoxSections, SyntaxTree := FoxSyntaxTree, Options,
  3. IntermediateBackend := FoxIntermediateBackend, Backend := FoxBackend, Global := FoxGlobal, Formats := FoxFormats,
  4. Trace := KernelLog, Streams, SymbolFileFormat := FoxTextualSymbolFile;
  5. CONST
  6. StackSize = 1024;
  7. AddressSize = SIZEOF (ADDRESS);
  8. TYPE
  9. PC = RECORD
  10. section: Intermediate.Section;
  11. index: LONGINT;
  12. END;
  13. Int1 = SHORTINT;
  14. Int2 = INTEGER;
  15. Int4 = LONGINT;
  16. Int8 = HUGEINT;
  17. Float4 = REAL;
  18. Float8 = LONGREAL;
  19. Value = RECORD
  20. int1: Int1;
  21. int2: Int2;
  22. int4: Int4;
  23. int8: Int8;
  24. float4: Float4;
  25. float8: Float8;
  26. END;
  27. Address = LONGINT;
  28. Size = LONGINT;
  29. Memory = POINTER TO ARRAY OF SYSTEM.BYTE;
  30. Heap = OBJECT
  31. VAR
  32. memory: Memory;
  33. currentSize: Size;
  34. PROCEDURE &InitMemory;
  35. BEGIN NEW (memory, 1024); currentSize := 0;
  36. END InitMemory;
  37. PROCEDURE Allocate (size: Size): Address;
  38. VAR address, i: Size; original: Memory;
  39. BEGIN address := currentSize;
  40. ASSERT (size >= 0);
  41. size := ((size + (AddressSize - 1)) DIV AddressSize) * AddressSize;
  42. INC (currentSize, size);
  43. IF currentSize > LEN (memory) THEN
  44. original := memory;
  45. NEW (memory, LEN (original) * 2);
  46. FOR i := 0 TO LEN (original) - 1 DO memory[i] := original[i]; END;
  47. END;
  48. RETURN address;
  49. END Allocate;
  50. PROCEDURE IsValid (address: Address): BOOLEAN;
  51. BEGIN RETURN (address > 0) & (address < currentSize);
  52. END IsValid;
  53. PROCEDURE GetObject (address: Address): OBJECT;
  54. VAR object: OBJECT;
  55. BEGIN
  56. ASSERT (IsValid (address));
  57. ASSERT (address MOD AddressSize = 0);
  58. SYSTEM.GET (ADDRESSOF (memory[address]), object); RETURN object;
  59. END GetObject;
  60. PROCEDURE PutObject (address: Address; object: OBJECT);
  61. BEGIN
  62. ASSERT (IsValid (address));
  63. ASSERT (address MOD AddressSize = 0);
  64. SYSTEM.PUT (ADDRESSOF (memory[address]), object);
  65. END PutObject;
  66. PROCEDURE GetValue (address: Address; CONST type: Intermediate.Type; VAR value: Value);
  67. VAR adr: ADDRESS;
  68. BEGIN
  69. ASSERT (IsValid (address));
  70. adr := ADDRESSOF (memory[address]);
  71. IF type.form = Intermediate.Float THEN
  72. IF type.sizeInBits= 8 THEN SYSTEM.GET (adr, value.float8);
  73. ELSE SYSTEM.GET (adr, value.float4); END;
  74. ELSE
  75. IF type.sizeInBits= 1 THEN SYSTEM.GET (adr, value.int1);
  76. ELSIF type.sizeInBits= 2 THEN SYSTEM.GET (adr, value.int2);
  77. ELSIF type.sizeInBits= 8 THEN SYSTEM.GET (adr, value.int8);
  78. ELSE SYSTEM.GET (adr, value.int4); END;
  79. END;
  80. END GetValue;
  81. PROCEDURE PutValue (address: Address; CONST type: Intermediate.Type; CONST value: Value);
  82. VAR adr: ADDRESS;
  83. BEGIN
  84. ASSERT (IsValid (address));
  85. adr := ADDRESSOF (memory[address]);
  86. IF type.form = Intermediate.Float THEN
  87. IF type.sizeInBits= 8 THEN SYSTEM.PUT (adr, value.float8);
  88. ELSE SYSTEM.PUT (adr, value.float4); END;
  89. ELSE
  90. IF type.sizeInBits= 1 THEN SYSTEM.PUT (adr, value.int1);
  91. ELSIF type.sizeInBits= 2 THEN SYSTEM.PUT (adr, value.int2);
  92. ELSIF type.sizeInBits= 8 THEN SYSTEM.PUT (adr, value.int8);
  93. ELSE SYSTEM.PUT (adr, value.int4); END;
  94. END;
  95. END PutValue;
  96. PROCEDURE Copy (dest, source, size: Address);
  97. BEGIN
  98. ASSERT (IsValid (dest)); ASSERT (IsValid (source));
  99. WHILE size > 0 DO memory[dest] := memory[source]; INC (dest); INC (source); DEC (size); END;
  100. END Copy;
  101. PROCEDURE Fill (dest, size: Address; CONST value: Value; CONST type: Intermediate.Type);
  102. BEGIN
  103. ASSERT (IsValid (dest));
  104. WHILE size > 0 DO PutValue (dest, type, value); INC (dest, type.sizeInBits); DEC (size); END;
  105. END Fill;
  106. END Heap;
  107. Interpreter= OBJECT
  108. VAR
  109. backend: InterpreterBackend;
  110. pc: PC;
  111. sp, fp: Address;
  112. registers: ARRAY 16 OF Value;
  113. addressType: Intermediate.Type;
  114. trace: Streams.Writer;
  115. module: Sections.Module;
  116. PROCEDURE &InitInterpreter (backend: InterpreterBackend; addressSize: SHORTINT; m: Sections.Module);
  117. BEGIN SELF.backend := backend; pc.section := NIL; pc.index := 0; sp := backend.heap.Allocate (StackSize) + StackSize; fp := sp;
  118. addressType := Intermediate.NewType (Intermediate.UnsignedInteger, addressSize);
  119. NEW (trace, Trace.Send, 1);
  120. SELF.module := m
  121. END InitInterpreter;
  122. PROCEDURE Dump (section: Intermediate.Section; address: Address; CONST instruction: Intermediate.Instruction);
  123. VAR string: Basic.SectionName;
  124. BEGIN
  125. Basic.SegmentedNameToString(section.name, string);
  126. trace.String (string); trace.Char ('@'); trace.Int (address, 0); trace.String (": ");
  127. Intermediate.DumpInstruction (trace, instruction); trace.Ln; trace.Update;
  128. Trace.Memory (ADDRESSOF (backend.heap.memory[sp]), StackSize - sp);
  129. END Dump;
  130. PROCEDURE AllocateSection (s: Sections.Section);
  131. VAR i: LONGINT; size: Size; section: Intermediate.Section;
  132. BEGIN
  133. size := 0; section := s(Intermediate.Section);
  134. FOR i := 0 TO section.pc - 1 DO INC (size, GetSizeOf (section.instructions[i])); END;
  135. IF (section.pc = 0) & (section.type = Sections.CodeSection) THEN size := AddressSize; END;
  136. section.SetOffset (backend.heap.Allocate (size));
  137. END AllocateSection;
  138. PROCEDURE InitializeSection (s: Sections.Section);
  139. VAR i: LONGINT; address: Address; section: Intermediate.Section;
  140. BEGIN
  141. section := s(Intermediate.Section);
  142. address := section.offset;
  143. FOR i := 0 TO section.pc - 1 DO
  144. InitializeInstruction (section.instructions[i], address, section);
  145. INC (address, GetSizeOf (section.instructions[i]));
  146. END;
  147. IF (section.pc = 0) & (section.type = Sections.CodeSection) THEN backend.heap.PutObject (address, section); END;
  148. END InitializeSection;
  149. PROCEDURE InitializeInstruction (VAR instruction: Intermediate.Instruction; address: Address; section: Intermediate.Section);
  150. VAR value: Value;
  151. BEGIN
  152. CASE instruction.opcode OF
  153. | Intermediate.data: Evaluate (instruction.op1, value); backend.heap.PutValue (address, instruction.op1.type, value);
  154. | Intermediate.reserve:
  155. ELSE IF address MOD AddressSize = 0 THEN backend.heap.PutObject (address, section); END;
  156. END;
  157. END InitializeInstruction;
  158. PROCEDURE Resolve(VAR op: Intermediate.Operand);
  159. BEGIN
  160. IF op.resolved = NIL THEN
  161. op.resolved := module.allSections.FindByName(op.symbol.name);
  162. END;
  163. END Resolve;
  164. PROCEDURE Designate (VAR operand: Intermediate.Operand): Address;
  165. VAR address: Address;
  166. BEGIN
  167. address := 0;
  168. IF operand.symbol.name # "" THEN
  169. Resolve(operand);
  170. INC (address, operand.resolved.offset);
  171. END;
  172. IF operand.register = Intermediate.SP THEN INC (address, sp);
  173. ELSIF operand.register = Intermediate.FP THEN INC (address, fp);
  174. (*ELSIF operand.register = Intermediate.Result THEN INC (address, GetAddress (result, addressType));*)
  175. ELSIF operand.register # Intermediate.None THEN INC (address, GetAddress (registers[operand.register], addressType));
  176. END;
  177. RETURN address + operand.offset;
  178. END Designate;
  179. PROCEDURE Evaluate (VAR operand: Intermediate.Operand; VAR value: Value);
  180. VAR address: Address; offset: Value;
  181. BEGIN
  182. CASE operand.mode OF
  183. | Intermediate.ModeRegister:
  184. IF operand.register = Intermediate.SP THEN SetInteger (value, operand.type, sp);
  185. ELSIF operand.register = Intermediate.FP THEN SetInteger (value, operand.type, fp);
  186. (*ELSIF operand.register = Intermediate.Result THEN value := result;*)
  187. ELSE value := registers[operand.register]; END;
  188. IF operand.offset # 0 THEN SetInteger (offset, operand.type, operand.offset); Add (value, offset, operand.type); END;
  189. | Intermediate.ModeImmediate:
  190. IF operand.symbol.name # "" THEN SetInteger (value, operand.type, Designate (operand));
  191. ELSIF operand.type.form = Intermediate.Float THEN SetFloat (value, operand.type, operand.floatValue);
  192. ELSE SetInteger (value, operand.type, operand.intValue); END;
  193. | Intermediate.ModeMemory:
  194. address := Designate (operand);
  195. IF backend.heap.IsValid (address) THEN backend.heap.GetValue (address, operand.type, value); ELSE Error ("invalid load address "); END;
  196. END;
  197. END Evaluate;
  198. PROCEDURE EvaluateAddress (VAR operand: Intermediate.Operand): Address;
  199. VAR value: Value; address: Address;
  200. BEGIN
  201. ASSERT (Intermediate.TypeEquals (operand.type, addressType));
  202. Evaluate (operand, value); address := GetAddress (value, addressType);
  203. RETURN address;
  204. END EvaluateAddress;
  205. PROCEDURE Store (VAR operand: Intermediate.Operand; CONST value: Value);
  206. VAR address: Address;
  207. BEGIN
  208. CASE operand.mode OF
  209. | Intermediate.ModeRegister:
  210. ASSERT (operand.offset = 0);
  211. IF operand.register = Intermediate.SP THEN sp := GetAddress (value, operand.type);
  212. ELSIF operand.register = Intermediate.FP THEN fp := GetAddress (value, operand.type);
  213. (*ELSIF operand.register = Intermediate.Result THEN result := value;*)
  214. ELSE registers[operand.register] := value; END;
  215. | Intermediate.ModeMemory:
  216. address := Designate (operand);
  217. IF backend.heap.IsValid (address) THEN backend.heap.PutValue (address, operand.type, value); ELSE Error ("invalid store address "); END;
  218. END;
  219. END Store;
  220. PROCEDURE CallSection (section: Intermediate.Section);
  221. BEGIN Call (section.offset, pc);
  222. END CallSection;
  223. PROCEDURE Run;
  224. BEGIN
  225. TRACE(pc.section);
  226. WHILE pc.section # NIL DO
  227. Execute (pc.section.instructions[pc.index], pc);
  228. IF pc.index >= pc.section.pc THEN
  229. IF sp # StackSize THEN Error ("missing return"); END;
  230. pc.section := NIL;
  231. END;
  232. END;
  233. END Run;
  234. PROCEDURE Stop;
  235. BEGIN pc.index := pc.section.pc;
  236. END Stop;
  237. PROCEDURE Error (CONST msg: ARRAY OF CHAR);
  238. BEGIN backend.Error ("", Basic.invalidPosition, Streams.Invalid, msg); Stop;
  239. END Error;
  240. PROCEDURE Execute (VAR instr: Intermediate.Instruction; VAR pc: PC);
  241. VAR value, temp: Value; operand: Intermediate.Operand;
  242. BEGIN
  243. Dump (pc.section, pc.index, instr);
  244. CASE instr.opcode OF
  245. Intermediate.nop:
  246. |Intermediate.mov: Evaluate (instr.op2, value); Store (instr.op1, value);
  247. |Intermediate.conv: Evaluate (instr.op2, value); Convert (value, instr.op2.type, instr.op1.type); Store (instr.op1, value);
  248. |Intermediate.call: Call (EvaluateAddress (instr.op1), pc); RETURN;
  249. |Intermediate.enter: Intermediate.InitRegister (operand, addressType, Intermediate.GeneralPurposeRegister, Intermediate.FP); Push (operand); fp := sp; DEC (sp, SHORT (instr.op2.intValue));
  250. |Intermediate.leave: sp := fp; Intermediate.InitRegister (operand, addressType, Intermediate.GeneralPurposeRegister, Intermediate.FP); Pop (operand);
  251. |Intermediate.return: Return (pc, SHORT (instr.op2.intValue)); RETURN;
  252. |Intermediate.trap: Error ("trap"); RETURN;
  253. |Intermediate.br: Branch (EvaluateAddress (instr.op1), pc); RETURN;
  254. |Intermediate.breq: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); IF IsEqual (value, temp, instr.op2.type) THEN Branch (EvaluateAddress (instr.op1), pc); RETURN; END;
  255. |Intermediate.brne: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); IF ~IsEqual (value, temp, instr.op2.type) THEN Branch (EvaluateAddress (instr.op1), pc); RETURN; END;
  256. |Intermediate.brge: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); IF ~IsLessThan (value, temp, instr.op2.type) THEN Branch (EvaluateAddress (instr.op1), pc); RETURN; END;
  257. |Intermediate.brlt: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); IF IsLessThan (value, temp, instr.op2.type) THEN Branch (EvaluateAddress (instr.op1), pc); RETURN; END;
  258. |Intermediate.pop: Pop (instr.op1);
  259. |Intermediate.push: Push (instr.op1);
  260. |Intermediate.neg: Evaluate (instr.op2, value); Negate (value, instr.op1.type); Store (instr.op1, value);
  261. |Intermediate.not: Evaluate (instr.op2, value); Complement (value, instr.op1.type); Store (instr.op1, value);
  262. |Intermediate.abs: Evaluate (instr.op2, value); Absolute (value, instr.op1.type); Store (instr.op1, value);
  263. |Intermediate.mul: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Multiply (value, temp, instr.op1.type); Store (instr.op1, value);
  264. |Intermediate.div: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Divide (value, temp, instr.op1.type); Store (instr.op1, value);
  265. |Intermediate.mod: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Modulo (value, temp, instr.op1.type); Store (instr.op1, value);
  266. |Intermediate.sub: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Subtract (value, temp, instr.op1.type); Store (instr.op1, value);
  267. |Intermediate.add: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Add (value, temp, instr.op1.type); Store (instr.op1, value);
  268. |Intermediate.and: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); And (value, temp, instr.op1.type); Store (instr.op1, value);
  269. |Intermediate.or: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Or (value, temp, instr.op1.type); Store (instr.op1, value);
  270. |Intermediate.xor: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); Xor (value, temp, instr.op1.type); Store (instr.op1, value);
  271. |Intermediate.shl: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); ShiftLeft (value, temp, instr.op1.type); Store (instr.op1, value);
  272. |Intermediate.shr: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); ShiftRight (value, temp, instr.op1.type); Store (instr.op1, value);
  273. |Intermediate.rol: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); RotateLeft (value, temp, instr.op1.type); Store (instr.op1, value);
  274. |Intermediate.ror: Evaluate (instr.op2, value); Evaluate (instr.op3, temp); RotateRight (value, temp, instr.op1.type); Store (instr.op1, value);
  275. |Intermediate.copy: backend.heap.Copy (EvaluateAddress (instr.op1), EvaluateAddress (instr.op2), EvaluateAddress (instr.op3));
  276. |Intermediate.fill: Evaluate (instr.op3, value); backend.heap.Fill (EvaluateAddress (instr.op1), EvaluateAddress (instr.op2), value, instr.op3.type);
  277. END;
  278. INC (pc.index);
  279. END Execute;
  280. PROCEDURE Push (VAR operand: Intermediate.Operand);
  281. VAR value: Value;
  282. BEGIN
  283. ASSERT (sp >= operand.type.sizeInBits);
  284. Evaluate (operand, value);
  285. DEC (sp, operand.type.sizeInBits);
  286. backend.heap.PutValue (sp, operand.type, value);
  287. END Push;
  288. PROCEDURE Pop (VAR operand: Intermediate.Operand);
  289. VAR value: Value;
  290. BEGIN
  291. ASSERT (sp <= StackSize - operand.type.sizeInBits);
  292. backend.heap.GetValue (sp, operand.type, value);
  293. INC (sp, operand.type.sizeInBits);
  294. Store (operand, value);
  295. END Pop;
  296. PROCEDURE Branch (address: Address; VAR pc: PC);
  297. VAR object: OBJECT;
  298. BEGIN
  299. IF backend.heap.IsValid (address) THEN
  300. object := backend.heap.GetObject (address - address MOD AddressSize);
  301. pc.section := object(Intermediate.Section);
  302. pc.index := address- pc.section.offset;
  303. ELSE
  304. Error ("invalid branch address");
  305. END;
  306. END Branch;
  307. PROCEDURE Call (address: Address; VAR pc: PC);
  308. VAR link: Intermediate.Operand;
  309. BEGIN
  310. IF pc.section = NIL THEN Intermediate.InitImmediate (link, addressType, 0);
  311. ELSE Intermediate.InitAddress (link, addressType, pc.section.name, 0, pc.index + 1); END;
  312. Push (link); Branch (address, pc);
  313. END Call;
  314. PROCEDURE Return (VAR pc: PC; size: Address);
  315. VAR value: Value; link: Address;
  316. BEGIN
  317. ASSERT (sp <= StackSize - addressType.sizeInBits- size);
  318. backend.heap.GetValue (sp, addressType, value);
  319. INC (sp, addressType.sizeInBits);
  320. link := GetAddress (value, addressType);
  321. IF link = 0 THEN pc.index := pc.section.pc;
  322. ELSE Branch (link, pc); END;
  323. INC (sp, size)
  324. END Return;
  325. END Interpreter;
  326. InterpreterBackend = OBJECT (IntermediateBackend.IntermediateBackend)
  327. VAR
  328. heap: Heap;
  329. addressSize, setSize: LONGINT;
  330. PROCEDURE &InitInterpreterBackend;
  331. BEGIN InitBackend;
  332. END InitInterpreterBackend;
  333. PROCEDURE GetSystem*(): Global.System;
  334. VAR system: Global.System;
  335. BEGIN
  336. NEW (system, 8, 8, 32, 1, 1, 1, 1, addressSize * 2,cooperative);
  337. Global.SetDefaultDeclarations(system,8);
  338. Global.SetDefaultOperators(system);
  339. RETURN system;
  340. END GetSystem;
  341. PROCEDURE ProcessSyntaxTreeModule *(x: SyntaxTree.Module): Formats.GeneratedModule;
  342. VAR module: Sections.Module; section: Sections.Section; interpreter: Interpreter;
  343. BEGIN
  344. module := GenerateIntermediate (x, SupportedInstruction, SupportedImmediate);
  345. NEW (heap); NEW (interpreter, SELF, SHORT (SHORT (addressSize)),module);
  346. Traverse (module.allSections, interpreter.AllocateSection);
  347. Traverse (module.allSections, interpreter.InitializeSection);
  348. IF x.moduleScope.bodyProcedure # NIL THEN
  349. section := module.allSections.FindBySymbol (x.moduleScope.bodyProcedure);
  350. IF section # NIL THEN interpreter.CallSection (section(Intermediate.Section)) END;
  351. END;
  352. interpreter.Run;
  353. RETURN NIL
  354. END ProcessSyntaxTreeModule;
  355. PROCEDURE DefineOptions*(options: Options.Options);
  356. BEGIN DefineOptions^(options);
  357. options.Add("a","addressSize", Options.Integer);
  358. options.Add("s","setSize", Options.Integer);
  359. END DefineOptions;
  360. PROCEDURE GetOptions*(options: Options.Options);
  361. BEGIN GetOptions^(options);
  362. IF ~options.GetInteger("addressSize", addressSize) THEN addressSize := 2 END;
  363. IF ~options.GetInteger("setSize", setSize) THEN setSize := 2 END;
  364. END GetOptions;
  365. PROCEDURE DefaultSymbolFileFormat*(): Formats.SymbolFileFormat;
  366. BEGIN RETURN SymbolFileFormat.Get ();
  367. END DefaultSymbolFileFormat;
  368. END InterpreterBackend;
  369. PROCEDURE GetSizeOf (CONST instruction: Intermediate.Instruction): Size;
  370. BEGIN
  371. CASE instruction.opcode OF
  372. | Intermediate.data: RETURN instruction.op1.type.sizeInBits;
  373. | Intermediate.reserve: ASSERT (SHORT (instruction.op1.intValue) = instruction.op1.intValue); RETURN SHORT (instruction.op1.intValue);
  374. ELSE RETURN 1;
  375. END;
  376. END GetSizeOf;
  377. PROCEDURE SetInteger (VAR value: Value; CONST type: Intermediate.Type; integer: Int8);
  378. BEGIN
  379. ASSERT (type.form # Intermediate.Float);
  380. IF type.sizeInBits= 1 THEN value.int1 := SHORT (SHORT (SHORT (integer)));
  381. ELSIF type.sizeInBits= 2 THEN value.int2 := SHORT (SHORT (integer));
  382. ELSIF type.sizeInBits= 8 THEN value.int8 := integer;
  383. ELSE value.int4 := SHORT (integer); END;
  384. END SetInteger;
  385. PROCEDURE GetAddress (CONST value: Value; CONST type: Intermediate.Type): Address;
  386. BEGIN
  387. ASSERT (type.form = Intermediate.UnsignedInteger);
  388. IF type.sizeInBits= 2 THEN RETURN value.int2;
  389. ELSIF type.sizeInBits= 8 THEN ASSERT (SHORT (value.int8) = value.int8); RETURN SHORT (value.int8);
  390. ELSE RETURN value.int4; END;
  391. END GetAddress;
  392. PROCEDURE SetFloat (VAR value: Value; CONST type: Intermediate.Type; float: Float8);
  393. BEGIN
  394. ASSERT (type.form = Intermediate.Float);
  395. IF type.sizeInBits= 8 THEN value.float8 := float;
  396. ELSE value.float4 := SHORT (float); END;
  397. END SetFloat;
  398. PROCEDURE Convert (VAR value: Value; CONST from, to: Intermediate.Type);
  399. VAR val: LONGREAL;
  400. BEGIN
  401. IF from.form = Intermediate.Float THEN
  402. IF from.sizeInBits= 8 THEN val := value.float8; ELSE val := value.float4; END;
  403. ELSE
  404. IF from.sizeInBits= 1 THEN val := value.int1;
  405. ELSIF from.sizeInBits= 2 THEN val := value.int2;
  406. ELSIF from.sizeInBits= 8 THEN val := value.int8;
  407. ELSE val := value.int4; END;
  408. END;
  409. IF to.form = Intermediate.Float THEN
  410. IF to.sizeInBits= 8 THEN value.float8 := val; ELSE value.float4 := SHORT (val); END;
  411. ELSE
  412. IF to.sizeInBits= 1 THEN value.int1 := SHORT (SHORT (ENTIER (val)));
  413. ELSIF to.sizeInBits= 2 THEN value.int2 := SHORT (ENTIER (val));
  414. ELSIF to.sizeInBits= 8 THEN value.int8 := ENTIER (val);
  415. ELSE value.int4 := ENTIER (val); END;
  416. END;
  417. END Convert;
  418. PROCEDURE Negate (VAR value: Value; CONST type: Intermediate.Type);
  419. BEGIN
  420. IF type.form = Intermediate.Float THEN
  421. IF type.sizeInBits= 8 THEN value.float8 := -value.float8;
  422. ELSE value.float4 := -value.float4; END;
  423. ELSE
  424. IF type.sizeInBits= 1 THEN value.int1 := -value.int1;
  425. ELSIF type.sizeInBits= 2 THEN value.int2 := -value.int2;
  426. ELSIF type.sizeInBits= 8 THEN value.int8 := -value.int8;
  427. ELSE value.int4 := -value.int4; END;
  428. END;
  429. END Negate;
  430. PROCEDURE Complement (VAR value: Value; CONST type: Intermediate.Type);
  431. BEGIN
  432. IF type.form = Intermediate.Float THEN
  433. HALT (1234);
  434. ELSE
  435. IF type.sizeInBits= 1 THEN value.int1 := SYSTEM.VAL (Int1, -SYSTEM.VAL (SET, value.int1));
  436. ELSIF type.sizeInBits= 2 THEN value.int2 := SYSTEM.VAL (Int2, -SYSTEM.VAL (SET, value.int2));
  437. ELSIF type.sizeInBits= 8 THEN value.int8 := SYSTEM.VAL (Int8, -SYSTEM.VAL (SET, value.int8));
  438. ELSE value.int4 := SYSTEM.VAL (Int4, -SYSTEM.VAL (SET, value.int4)); END;
  439. END;
  440. END Complement;
  441. PROCEDURE Absolute (VAR value: Value; CONST type: Intermediate.Type);
  442. BEGIN
  443. IF type.form = Intermediate.Float THEN
  444. IF type.sizeInBits= 8 THEN value.float8 := ABS (value.float8);
  445. ELSE value.float4 := ABS (value.float4); END;
  446. ELSE
  447. IF type.sizeInBits= 1 THEN value.int1 := ABS (value.int1);
  448. ELSIF type.sizeInBits= 2 THEN value.int2 := ABS (value.int2);
  449. (*TRAP: ELSIF type.sizeInBits= 8 THEN value.int8 := ABS (value.int8); *)
  450. ELSE value.int4 := ABS (value.int4); END;
  451. END;
  452. END Absolute;
  453. PROCEDURE Multiply (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  454. BEGIN
  455. IF type.form = Intermediate.Float THEN
  456. IF type.sizeInBits= 8 THEN dest.float8 := dest.float8 * source.float8;
  457. ELSE dest.float4 := dest.float4 * source.float4; END;
  458. ELSE
  459. IF type.sizeInBits= 1 THEN dest.int1 := dest.int1 * source.int1;
  460. ELSIF type.sizeInBits= 2 THEN dest.int2 := dest.int2 * source.int2;
  461. ELSIF type.sizeInBits= 8 THEN dest.int8 := dest.int8 * source.int8;
  462. ELSE dest.int4 := dest.int4 * source.int4; END;
  463. END;
  464. END Multiply;
  465. PROCEDURE Divide (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  466. BEGIN
  467. IF type.form = Intermediate.Float THEN
  468. IF type.sizeInBits= 8 THEN dest.float8 := dest.float8 / source.float8;
  469. ELSE dest.float4 := dest.float4 / source.float4; END;
  470. ELSE
  471. IF type.sizeInBits= 1 THEN dest.int1 := dest.int1 DIV source.int1;
  472. ELSIF type.sizeInBits= 2 THEN dest.int2 := dest.int2 DIV source.int2;
  473. ELSIF type.sizeInBits= 8 THEN dest.int8 := dest.int8 * source.int8;
  474. ELSE dest.int4 := dest.int4 DIV source.int4; END;
  475. END;
  476. END Divide;
  477. PROCEDURE Modulo (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  478. BEGIN
  479. IF type.form = Intermediate.Float THEN
  480. HALT (1234);
  481. ELSE
  482. IF type.sizeInBits= 1 THEN dest.int1 := dest.int1 MOD source.int1;
  483. ELSIF type.sizeInBits= 2 THEN dest.int2 := dest.int2 MOD source.int2;
  484. (*TRAP: ELSIF type.sizeInBits= 8 THEN dest.int8 := dest.int8 MOD source.int8; *)
  485. ELSE dest.int4 := dest.int4 MOD source.int4; END;
  486. END;
  487. END Modulo;
  488. PROCEDURE Subtract (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  489. BEGIN
  490. IF type.form = Intermediate.Float THEN
  491. IF type.sizeInBits= 8 THEN dest.float8 := dest.float8 - source.float8;
  492. ELSE dest.float4 := dest.float4 - source.float4; END;
  493. ELSE
  494. IF type.sizeInBits= 1 THEN dest.int1 := dest.int1 - source.int1;
  495. ELSIF type.sizeInBits= 2 THEN dest.int2 := dest.int2 - source.int2;
  496. ELSIF type.sizeInBits= 8 THEN dest.int8 := dest.int8 - source.int8;
  497. ELSE dest.int4 := dest.int4 - source.int4; END;
  498. END;
  499. END Subtract;
  500. PROCEDURE Add (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  501. BEGIN
  502. IF type.form = Intermediate.Float THEN
  503. IF type.sizeInBits= 8 THEN dest.float8 := dest.float8 + source.float8;
  504. ELSE dest.float4 := dest.float4 + source.float4; END;
  505. ELSE
  506. IF type.sizeInBits= 1 THEN dest.int1 := dest.int1 + source.int1;
  507. ELSIF type.sizeInBits= 2 THEN dest.int2 := dest.int2 + source.int2;
  508. ELSIF type.sizeInBits= 8 THEN dest.int8 := dest.int8 + source.int8;
  509. ELSE dest.int4 := dest.int4 + source.int4; END;
  510. END;
  511. END Add;
  512. PROCEDURE And (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  513. BEGIN
  514. IF type.form = Intermediate.Float THEN
  515. HALT (1234);
  516. ELSE
  517. IF type.sizeInBits= 1 THEN dest.int1 := SYSTEM.VAL (Int1, SYSTEM.VAL (SET, dest.int1) * SYSTEM.VAL (SET, source.int1));
  518. ELSIF type.sizeInBits= 2 THEN dest.int2 := SYSTEM.VAL (Int2, SYSTEM.VAL (SET, dest.int2) * SYSTEM.VAL (SET, source.int2));
  519. ELSIF type.sizeInBits= 8 THEN dest.int8 := SYSTEM.VAL (Int8, SYSTEM.VAL (SET, dest.int8) * SYSTEM.VAL (SET, source.int8));
  520. ELSE dest.int4 := SYSTEM.VAL (Int4, SYSTEM.VAL (SET, dest.int4) * SYSTEM.VAL (SET, source.int4)); END;
  521. END;
  522. END And;
  523. PROCEDURE Or (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  524. BEGIN
  525. IF type.form = Intermediate.Float THEN
  526. HALT (1234);
  527. ELSE
  528. IF type.sizeInBits= 1 THEN dest.int1 := SYSTEM.VAL (Int1, SYSTEM.VAL (SET, dest.int1) + SYSTEM.VAL (SET, source.int1));
  529. ELSIF type.sizeInBits= 2 THEN dest.int2 := SYSTEM.VAL (Int2, SYSTEM.VAL (SET, dest.int2) + SYSTEM.VAL (SET, source.int2));
  530. ELSIF type.sizeInBits= 8 THEN dest.int8 := SYSTEM.VAL (Int8, SYSTEM.VAL (SET, dest.int8) + SYSTEM.VAL (SET, source.int8));
  531. ELSE dest.int4 := SYSTEM.VAL (Int4, SYSTEM.VAL (SET, dest.int4) + SYSTEM.VAL (SET, source.int4)); END;
  532. END;
  533. END Or;
  534. PROCEDURE Xor (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  535. BEGIN
  536. IF type.form = Intermediate.Float THEN
  537. HALT (1234);
  538. ELSE
  539. IF type.sizeInBits= 1 THEN dest.int1 := SYSTEM.VAL (Int1, SYSTEM.VAL (SET, dest.int1) / SYSTEM.VAL (SET, source.int1));
  540. ELSIF type.sizeInBits= 2 THEN dest.int2 := SYSTEM.VAL (Int2, SYSTEM.VAL (SET, dest.int2) / SYSTEM.VAL (SET, source.int2));
  541. ELSIF type.sizeInBits= 8 THEN dest.int8 := SYSTEM.VAL (Int8, SYSTEM.VAL (SET, dest.int8) / SYSTEM.VAL (SET, source.int8));
  542. ELSE dest.int4 := SYSTEM.VAL (Int4, SYSTEM.VAL (SET, dest.int4) / SYSTEM.VAL (SET, source.int4)); END;
  543. END;
  544. END Xor;
  545. PROCEDURE ShiftLeft (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  546. BEGIN
  547. IF type.form = Intermediate.Float THEN
  548. HALT (1234);
  549. ELSE
  550. IF type.sizeInBits= 1 THEN dest.int1 := LSH (dest.int1, source.int1);
  551. ELSIF type.sizeInBits= 2 THEN dest.int2 := LSH (dest.int2, source.int2);
  552. ELSIF type.sizeInBits= 8 THEN dest.int8 := LSH (dest.int8, source.int8);
  553. ELSE dest.int4 := LSH (dest.int4, source.int4); END;
  554. END;
  555. END ShiftLeft;
  556. PROCEDURE ShiftRight (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  557. BEGIN
  558. IF type.form = Intermediate.Float THEN
  559. HALT (1234);
  560. ELSE
  561. IF type.sizeInBits= 1 THEN dest.int1 := LSH (dest.int1, -source.int1);
  562. ELSIF type.sizeInBits= 2 THEN dest.int2 := LSH (dest.int2, -source.int2);
  563. ELSIF type.sizeInBits= 8 THEN dest.int8 := LSH (dest.int8, -source.int8);
  564. ELSE dest.int4 := LSH (dest.int4, -source.int4); END;
  565. END;
  566. END ShiftRight;
  567. PROCEDURE RotateLeft (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  568. BEGIN
  569. IF type.form = Intermediate.Float THEN
  570. HALT (1234);
  571. ELSE
  572. IF type.sizeInBits= 1 THEN dest.int1 := ROT (dest.int1, source.int1);
  573. ELSIF type.sizeInBits= 2 THEN dest.int2 := ROT (dest.int2, source.int2);
  574. ELSIF type.sizeInBits= 8 THEN dest.int8 := ROT (dest.int8, source.int8);
  575. ELSE dest.int4 := ROT (dest.int4, source.int4); END;
  576. END;
  577. END RotateLeft;
  578. PROCEDURE RotateRight (VAR dest: Value; CONST source: Value; CONST type: Intermediate.Type);
  579. BEGIN
  580. IF type.form = Intermediate.Float THEN
  581. HALT (1234);
  582. ELSE
  583. IF type.sizeInBits= 1 THEN dest.int1 := ROT (dest.int1, -source.int1);
  584. ELSIF type.sizeInBits= 2 THEN dest.int2 := ROT (dest.int2, -source.int2);
  585. ELSIF type.sizeInBits= 8 THEN dest.int8 := ROT (dest.int8, -source.int8);
  586. ELSE dest.int4 := ROT (dest.int4, -source.int4); END;
  587. END;
  588. END RotateRight;
  589. PROCEDURE IsEqual (CONST value1, value2: Value; CONST type: Intermediate.Type): BOOLEAN;
  590. BEGIN
  591. IF type.form = Intermediate.Float THEN
  592. IF type.sizeInBits= 8 THEN RETURN value1.float8 = value2.float8;
  593. ELSE RETURN value1.float4 = value2.float4; END;
  594. ELSE
  595. IF type.sizeInBits= 1 THEN RETURN value1.int1 = value2.int1;
  596. ELSIF type.sizeInBits= 2 THEN RETURN value1.int2 = value2.int2;
  597. ELSIF type.sizeInBits= 8 THEN RETURN value1.int8 = value2.int8;
  598. ELSE RETURN value1.int4 = value2.int4; END;
  599. END;
  600. END IsEqual;
  601. PROCEDURE IsLessThan (CONST value1, value2: Value; CONST type: Intermediate.Type): BOOLEAN;
  602. BEGIN
  603. IF type.form = Intermediate.Float THEN
  604. IF type.sizeInBits= 8 THEN RETURN value1.float8 < value2.float8;
  605. ELSE RETURN value1.float4 < value2.float4; END;
  606. ELSIF type.form = Intermediate.UnsignedInteger THEN
  607. IF type.sizeInBits= 1 THEN IF (value1.int1 >= 0) & (value2.int1 >= 0) OR (value1.int1 < 0) & (value2.int1 < 0) THEN RETURN value1.int1 < value2.int1; ELSE RETURN value1.int1 >= value2.int1; END;
  608. ELSIF type.sizeInBits= 2 THEN IF (value1.int2 >= 0) & (value2.int2 >= 0) OR (value1.int2 < 0) & (value2.int2 < 0) THEN RETURN value1.int2 < value2.int2; ELSE RETURN value1.int2 >= value2.int2; END;
  609. ELSIF type.sizeInBits= 8 THEN IF (value1.int8 >= 0) & (value2.int8 >= 0) OR (value1.int8 < 0) & (value2.int8 < 0) THEN RETURN value1.int8 < value2.int8; ELSE RETURN value1.int8 >= value2.int8; END;
  610. ELSE IF (value1.int4 >= 0) & (value2.int4 >= 0) OR (value1.int4 < 0) & (value2.int4 < 0) THEN RETURN value1.int4 < value2.int4; ELSE RETURN value1.int4 >= value2.int4; END; END;
  611. ELSE
  612. IF type.sizeInBits= 1 THEN RETURN value1.int1 < value2.int1;
  613. ELSIF type.sizeInBits= 2 THEN RETURN value1.int2 < value2.int2;
  614. ELSIF type.sizeInBits= 8 THEN RETURN value1.int8 < value2.int8;
  615. ELSE RETURN value1.int4 < value2.int4; END;
  616. END;
  617. END IsLessThan;
  618. PROCEDURE Traverse (list: Sections.SectionList; handle: PROCEDURE {DELEGATE} (section: Sections.Section));
  619. VAR
  620. section: Sections.Section;
  621. i: LONGINT;
  622. BEGIN
  623. FOR i := 0 TO list.Length() - 1 DO
  624. section := list.GetSection(i);
  625. handle(section)
  626. END
  627. END Traverse;
  628. PROCEDURE Get* (): Backend.Backend;
  629. VAR backend: InterpreterBackend;
  630. BEGIN NEW(backend); RETURN backend;
  631. END Get;
  632. END FoxInterpreterBackend.
  633. System.Free FoxInterpreterBackend ~
  634. Compiler.Compile -b=Interpreter Test.Mod ~
  635. TextCompiler.CompileSelection -b=Interpreter ~
  636. MODULE Test;
  637. VAR a: INTEGER;
  638. BEGIN
  639. a := 0;
  640. ASSERT(a = 0);
  641. END Test.