2
0

FoxTRMInstructionSet.Mod 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. MODULE FoxTRMInstructionSet; (** AUTHOR "fof"; PURPOSE "Tiny Register Machine Instruction Set"; *)
  2. IMPORT Commands, Options, Streams, Sections := FoxSections, BinaryCode := FoxBinaryCode, Global := FoxGlobal, Basic := FoxBasic, D := Debugging, ObjectFile, Disassembler := FoxDisassembler,
  3. Files, BitSets;
  4. CONST
  5. checkMnemonic=TRUE;
  6. maxMnemonicNameLength=8;
  7. maxNumberInstructions=100;
  8. (* mnemonics , unsorted
  9. FoxProgTools.Enum -e -l=8
  10. opMOV opNOT
  11. opADD opFADD
  12. opSUB opFSUB
  13. opAND opBIC opOR opXOR
  14. opMUL opFMUL
  15. opLDH opROR opBLR opBR opSPSR opIRET opLD opST opBL
  16. opBEQ opBNE opBAE opBB opBN opBNN opBO opBNO opBA opBBE opBGE opBLT opBGT opBLE opBT opBF
  17. opBZS opBZC opBCS opBCC opBNS opBNC opBVS opBVC opHADD opFHADD
  18. numberMnemonics
  19. ~
  20. *)
  21. (*Variable instruction width related. All other bitcaounts derived.*)
  22. (*instructionW=24;*) (*Number of bits an instruction word holds. default 18*)
  23. regselW=3; (*number of bits to select a register. default 3*)
  24. opcodeW=4;(*Number of bits for the opcode. default 4*)
  25. conditionW=4; (*Number of bits fot the branch condition*)
  26. opMOV*= 0; opNOT*= 1; opADD*= 2; opFADD*= 3; opSUB*= 4; opFSUB*= 5; opAND*= 6; opBIC*= 7;
  27. opOR*= 8; opXOR*= 9; opMUL*= 10; opFMUL*= 11; opLDH*= 12; opROR*= 13; opBLR*= 14; opBR*= 15;
  28. opSPSR*= 16; opIRET*= 17; opLD*= 18; opST*= 19; opBL*= 20; opBEQ*= 21; opBNE*= 22; opBAE*= 23;
  29. opBB*= 24; opBN*= 25; opBNN*= 26; opBO*= 27; opBNO*= 28; opBA*= 29; opBBE*= 30; opBGE*= 31;
  30. opBLT*= 32; opBGT*= 33; opBLE*= 34; opBT*= 35; opBF*= 36; opBZS*= 37; opBZC*= 38; opBCS*= 39;
  31. opBCC*= 40; opBNS*= 41; opBNC*= 42; opBVS*= 43; opBVC*= 44; opHADD*= 45; opFHADD*= 46; numberMnemonics*= 47;
  32. (* operand format types *)
  33. None*=-1; (* no operand *)
  34. Rd=0; (* destination register, encoded at bits 11..13 *)
  35. Rs=1; (* source register, encoded at bits 0..2 *)
  36. VRd=2; (* vector destination register, encoded at bits 11..13 *)
  37. VRs=3; (* vector source register, encoded at bits 0..2 *)
  38. Imm10=4; (* 10 bit immediate, unsigned, encoded at bits 0..9 *) (*gets wider with wider instruction word.*)
  39. SignedImm10=5; (* 10 bit immediate, signed, encoded at bits 0..9 *)
  40. Imm14=6; (* 14 bit signed immediate, encoded at bits 0..13 *)
  41. MemRegImm7=7; (* memory operand of the form [reg +imm] with 7 bit immediate, encoded at reg = 0..2, imm= 3..9 *)
  42. VRd0=8; (* vector register, being restricted to register number 0 *)
  43. ZeroRegister* = 7;
  44. (* operand types *)
  45. Register*=1;
  46. Immediate*=2;
  47. Memory*=3;
  48. (* special registers *)
  49. LR*=7; (* pc link register *)
  50. SP*=6; (* stack pointer register *)
  51. globalP*=5; (* global variable link register *)
  52. FP*=4; (* frame pointer register *)
  53. (*
  54. registers 0 .. 7 : general purpose registers (integer, 32 bit)
  55. registers 16..23: vector registers
  56. *)
  57. TYPE
  58. OperandType = INTEGER;
  59. OperandFormatType = INTEGER;
  60. RegisterIndex = LONGINT;
  61. InstructionFormat* = RECORD
  62. mnemonic-: LONGINT;
  63. code, mask: SET;
  64. capabilities-: SET; (* what kind of capabilities an architecture must have to support this instruction *)
  65. op1, op2: OperandFormatType;
  66. END;
  67. Mnemonic* = RECORD
  68. name-: ARRAY maxMnemonicNameLength OF CHAR;
  69. number-: LONGINT;
  70. firstInstructionFormat, lastInstructionFormat: LONGINT;
  71. END;
  72. NumberedName=RECORD (* for sorting mnemonics *)
  73. name: ARRAY maxMnemonicNameLength OF CHAR;
  74. number: LONGINT;
  75. END;
  76. Operand*=RECORD
  77. type-: OperandType;
  78. size: LONGINT; (* size in bits *)
  79. register-: RegisterIndex; (* register index *)
  80. imm-: LONGINT; (* value *)
  81. fixup-: BinaryCode.Fixup;
  82. END;
  83. Instruction*=RECORD
  84. format-: LONGINT;
  85. op1-, op2-: Operand;
  86. END;
  87. InstructionSet *=OBJECT
  88. VAR mnemonics-: ARRAY numberMnemonics OF Mnemonic;
  89. mnemonicsSorted-: ARRAY numberMnemonics OF NumberedName;
  90. instructionFormats-: ARRAY maxNumberInstructions OF InstructionFormat;
  91. numberInstructionFormats-: LONGINT;
  92. inverseCondition-: ARRAY numberMnemonics OF LONGINT;
  93. instructionW-: LONGINT;
  94. RelativeBranchFixupBits-: LONGINT;
  95. BranchAndLinkFixupBits-: LONGINT;
  96. ImmediateFixupBits-: LONGINT;
  97. MemoryOffsetFixupBits-: LONGINT;
  98. PROCEDURE & InitInstructionSet * (instructionWidth: LONGINT);
  99. BEGIN
  100. ASSERT(instructionWidth>0);
  101. instructionW:=instructionWidth;
  102. RelativeBranchFixupBits:=instructionW-opcodeW-regselW-1;
  103. BranchAndLinkFixupBits:=instructionW-opcodeW;
  104. ImmediateFixupBits:=instructionW-opcodeW-regselW-1;
  105. MemoryOffsetFixupBits:=instructionW-11; (*!todo: look up how that actually comes to pass*)
  106. InitInstructions();
  107. END InitInstructionSet;
  108. (*
  109. public functions:
  110. makeinstruction
  111. isvalidinstruction
  112. encode
  113. decode
  114. emitinst
  115. emit
  116. findmnem
  117. findreg
  118. initreg
  119. initimm
  120. initmem
  121. initfix
  122. addfix
  123. initop
  124. dumpop
  125. dumpinst
  126. dumpbits
  127. dumpinsformat
  128. disas
  129. *)
  130. PROCEDURE FindInstructionFormat(mnem: LONGINT; op1, op2: Operand): LONGINT;
  131. VAR i: LONGINT; instructionFormat: InstructionFormat;
  132. PROCEDURE Matches(operand: Operand; operandFormatType: OperandType): BOOLEAN;
  133. BEGIN
  134. CASE operand.type OF
  135. Register : RETURN (operandFormatType IN {Rd, Rs}) & (operand.register < 16) OR (operandFormatType IN {VRd,VRs}) & (operand.register >= 16)
  136. OR (operandFormatType = VRd0) & (operand.register = 16)
  137. ;
  138. | Immediate : RETURN operandFormatType IN {Imm10, SignedImm10, Imm14};
  139. | Memory : RETURN (operandFormatType=MemRegImm7);
  140. | None : RETURN operandFormatType = None;
  141. END;
  142. END Matches;
  143. BEGIN
  144. i := mnemonics[mnem].firstInstructionFormat;
  145. WHILE i <= mnemonics[mnem].lastInstructionFormat DO
  146. instructionFormat := instructionFormats[i];
  147. IF Matches(op1, instructionFormat.op1) & Matches(op2, instructionFormat.op2) THEN
  148. RETURN i
  149. END;
  150. INC(i);
  151. END;
  152. D.String("could not find instruction for "); D.String(mnemonics[mnem].name); D.String(" ");
  153. DumpOperand(D.Log, op1); D.String(", ");
  154. DumpOperand(D.Log, op2); D.String(", ");
  155. D.Ln;
  156. i := mnemonics[mnem].firstInstructionFormat;
  157. D.Int(i,0);D.Ln;
  158. WHILE i <= mnemonics[mnem].lastInstructionFormat DO
  159. D.Int(i,0);D.Ln;
  160. instructionFormat := instructionFormats[i];
  161. IF ~Matches(op1, instructionFormat.op1) THEN
  162. D.String("op1 doesn't match");
  163. END;
  164. IF ~Matches(op2, instructionFormat.op2) THEN
  165. D.String("op2 doesn't match");
  166. END;
  167. IF Matches(op1, instructionFormat.op1) & Matches(op2, instructionFormat.op2) THEN
  168. D.String("MATCH!");
  169. ELSE
  170. D.String("NO MATCH!");
  171. END;
  172. D.Log.Ln;
  173. INC(i);
  174. END;
  175. D.Update;
  176. RETURN None;
  177. END FindInstructionFormat;
  178. PROCEDURE MakeInstruction*(VAR instruction: Instruction; mnemonic: LONGINT; op1, op2: Operand);
  179. VAR instructionFormat: LONGINT;
  180. BEGIN
  181. instructionFormat := FindInstructionFormat(mnemonic, op1, op2);
  182. instruction.format := instructionFormat;
  183. instruction.op1 := op1;
  184. instruction.op2 := op2;
  185. END MakeInstruction;
  186. PROCEDURE IsValidInstruction*(CONST instruction: Instruction): BOOLEAN;
  187. BEGIN RETURN instruction.format # None
  188. END IsValidInstruction;
  189. PROCEDURE Encode*(CONST instruction: Instruction): LONGINT;
  190. VAR codeSet: SET; instructionFormat: InstructionFormat; error: BOOLEAN;
  191. PROCEDURE Unsigned(val: LONGINT; from, to: LONGINT);
  192. VAR i: LONGINT;
  193. BEGIN
  194. ASSERT ( from <= to );
  195. FOR i := from TO to DO
  196. IF ODD(val) THEN INCL(codeSet, i) END;
  197. val := val DIV 2;
  198. END;
  199. IF val # 0 THEN error := TRUE END;
  200. ASSERT(val = 0);
  201. END Unsigned;
  202. PROCEDURE Signed(val: LONGINT; from, to: LONGINT);
  203. VAR i: LONGINT;
  204. BEGIN
  205. ASSERT ( from <= to );
  206. FOR i := from TO to-1 DO
  207. IF ODD(val) THEN INCL(codeSet, i) END;
  208. val := val DIV 2;
  209. END;
  210. IF val = -1 THEN INCL(codeSet, to)
  211. ELSIF val # 0 THEN HALT(100) (* overflow *)
  212. END;
  213. END Signed;
  214. PROCEDURE EncodeOperand(op: Operand; type: OperandFormatType);
  215. VAR imm: LONGINT;
  216. PROCEDURE Fixup(from, to: LONGINT);
  217. VAR patterns: ObjectFile.FixupPatterns; displacement: LONGINT; mode: SHORTINT;
  218. BEGIN
  219. NEW(patterns, 1);
  220. patterns[0].offset := from; patterns[0].bits := to-from+1;
  221. IF (opBL <= instructionFormat.mnemonic) & (instructionFormat.mnemonic <= opBF) THEN
  222. mode := BinaryCode.Relative;
  223. displacement := op.fixup.displacement-1;
  224. ELSE
  225. mode := BinaryCode.Absolute;
  226. displacement := op.fixup.displacement;
  227. END;
  228. op.fixup.InitFixup(mode, 0, op.fixup.symbol, op.fixup.symbolOffset, displacement, 0, patterns);
  229. END Fixup;
  230. BEGIN
  231. imm := op.imm; (* for debugging *)
  232. CASE type OF
  233. None: (* do nothing *)
  234. |Rd: Unsigned(op.register,instructionW-opcodeW-regselW,instructionW-opcodeW-1);
  235. |Rs: Unsigned(op.register, 0, regselW-1);
  236. |VRd: Unsigned(op.register MOD 16,instructionW-opcodeW-regselW,instructionW-opcodeW-1);
  237. |VRd0: Unsigned(0, instructionW-opcodeW-regselW,instructionW-opcodeW-1);
  238. |VRs: Unsigned(op.register MOD 16,0,regselW-1);
  239. |Imm10: Unsigned(op.imm, 0, instructionW-opcodeW-regselW-2);
  240. IF op.fixup # NIL THEN Fixup(0, instructionW-opcodeW-regselW-2) END;
  241. |SignedImm10: Signed(op.imm, 0, instructionW-opcodeW-regselW-2);
  242. IF op.fixup # NIL THEN Fixup(0, instructionW-opcodeW-regselW-2) END;
  243. |Imm14: Signed(op.imm, 0, BranchAndLinkFixupBits-1);
  244. IF op.fixup # NIL THEN Fixup(0, BranchAndLinkFixupBits-1) END;
  245. |MemRegImm7: Unsigned(op.register, 0, 2); Unsigned(op.imm, regselW, instructionW-opcodeW-regselW-2);
  246. IF op.fixup # NIL THEN Fixup(regselW, instructionW-opcodeW-regselW-2) END;
  247. END;
  248. END EncodeOperand;
  249. BEGIN
  250. ASSERT(instruction.format # None);
  251. instructionFormat := instructionFormats[instruction.format];
  252. codeSet := instructionFormat.code;
  253. EncodeOperand(instruction.op1, instructionFormat.op1);
  254. EncodeOperand(instruction.op2, instructionFormat.op2);
  255. RETURN SetToNumber(codeSet);
  256. END Encode;
  257. PROCEDURE Decode*(code: LONGINT; VAR instruction: Instruction);
  258. VAR instructionFormat: InstructionFormat; i: LONGINT; codeSet: SET;
  259. PROCEDURE Unsigned(from, to: LONGINT): LONGINT;
  260. VAR val, i: LONGINT;
  261. BEGIN
  262. val := 0;
  263. FOR i := to TO from BY -1 DO
  264. val := val*2;
  265. IF i IN codeSet THEN INC(val) END;
  266. END;
  267. RETURN val
  268. END Unsigned;
  269. PROCEDURE Signed(from, to: LONGINT): LONGINT;
  270. VAR val, i: LONGINT; negative:BOOLEAN;
  271. BEGIN
  272. val := 0;
  273. negative := to IN codeSet; (* two's complement negate *)
  274. FOR i := to-1 TO from BY -1 DO
  275. val := val*2;
  276. IF (i IN codeSet) THEN
  277. IF ~negative THEN INC(val) END;
  278. ELSIF negative THEN
  279. INC(val)
  280. END;
  281. END;
  282. IF negative THEN INC(val); val := -val END;
  283. RETURN val
  284. END Signed;
  285. PROCEDURE Matches(CONST instructionFormat: InstructionFormat): BOOLEAN;
  286. BEGIN
  287. RETURN instructionFormat.mask*codeSet = instructionFormat.code * instructionFormat.mask;
  288. END Matches;
  289. PROCEDURE DecodeOperand(VAR op: Operand; type: OperandFormatType);
  290. BEGIN
  291. InitOperand(op);
  292. CASE type OF
  293. None: op.type := None;
  294. |Rd: InitRegister(op,Unsigned(instructionW-opcodeW-regselW,instructionW-opcodeW-1));
  295. |Rs: InitRegister(op,Unsigned(0,regselW-1));
  296. |VRd: InitRegister(op,Unsigned(instructionW-opcodeW-regselW,instructionW-opcodeW-1)+16);
  297. |VRs: InitRegister(op,Unsigned(0,regselW-1)+16);
  298. |Imm10: InitImmediate(op,ImmediateFixupBits,Unsigned(0,ImmediateFixupBits-1));
  299. |SignedImm10: InitImmediate(op,ImmediateFixupBits,Signed(0,ImmediateFixupBits-1));
  300. |Imm14: InitImmediate(op,BranchAndLinkFixupBits,Signed(0,BranchAndLinkFixupBits-1));
  301. |MemRegImm7: InitMemory(op,Unsigned(0,regselW-1), Unsigned(regselW, ImmediateFixupBits-1)); (*load/store offsets*)
  302. END;
  303. END DecodeOperand;
  304. BEGIN
  305. codeSet := NumberToSet(code);
  306. i := 0;
  307. WHILE ~Matches(instructionFormats[i]) DO
  308. INC(i);
  309. END;
  310. instructionFormat := instructionFormats[i];
  311. instruction.format := i;
  312. DecodeOperand(instruction.op1, instructionFormat.op1);
  313. DecodeOperand(instruction.op2, instructionFormat.op2);
  314. END Decode;
  315. PROCEDURE EmitInstruction*(CONST instruction: Instruction; mnem: LONGINT; code: BinaryCode.Section);
  316. VAR encoding: LONGINT;
  317. PROCEDURE PatchFixup(op: Operand; type: OperandFormatType);
  318. BEGIN
  319. IF op.fixup # NIL THEN
  320. op.fixup.SetFixupOffset(code.pc);
  321. code.fixupList.AddFixup(op.fixup);
  322. END;
  323. END PatchFixup;
  324. PROCEDURE PatchFixups;
  325. VAR instructionFormat: InstructionFormat;
  326. BEGIN
  327. instructionFormat := instructionFormats[instruction.format];
  328. PatchFixup(instruction.op1, instructionFormat.op1);
  329. PatchFixup(instruction.op2, instructionFormat.op2);
  330. END PatchFixups;
  331. BEGIN
  332. IF (code.comments # NIL) THEN
  333. DumpInstruction(code.comments, instruction);
  334. code.comments.Ln;
  335. code.comments.Update;
  336. END;
  337. encoding := Encode(instruction);
  338. PatchFixups();
  339. code.PutBits(encoding, instructionW);
  340. (*make sure it is really a section set up to take code and not for example data.*)
  341. ASSERT(code.os.unit =instructionW); ASSERT(code.os.bits.GetSize() MOD instructionW = 0);
  342. END EmitInstruction;
  343. PROCEDURE Emit*(mnem: LONGINT; CONST op1, op2: Operand; code: BinaryCode.Section);
  344. VAR instruction: Instruction;
  345. BEGIN
  346. MakeInstruction(instruction, mnem, op1, op2);
  347. EmitInstruction(instruction, mnem, code);
  348. END Emit;
  349. (* perform a binary search for the index of the specified mnemonic *)
  350. PROCEDURE FindMnemonic* (CONST mnem: ARRAY OF CHAR): LONGINT;
  351. VAR l, r, m: LONGINT;
  352. BEGIN
  353. (*
  354. IF mnem = "LD" THEN
  355. IF vectorSupport THEN RETURN opLD ELSE RETURN opLDS END;
  356. ELSIF mnem = "ST" THEN
  357. IF vectorSupport THEN RETURN opST ELSE RETURN opSTS END;
  358. END;
  359. *)
  360. l := 0;
  361. r := numberMnemonics;
  362. WHILE l # r DO
  363. m := (l + r) DIV 2;
  364. IF mnem < mnemonicsSorted[m].name THEN r := m;
  365. ELSIF mnem > mnemonicsSorted[m].name THEN l := m + 1;
  366. ELSE RETURN mnemonicsSorted[m].number;
  367. END
  368. END;
  369. RETURN None;
  370. END FindMnemonic;
  371. PROCEDURE FindRegister*(CONST name: ARRAY OF CHAR): SHORTINT;
  372. BEGIN
  373. IF name[0] = "R" THEN
  374. IF name[2] = 0X THEN
  375. IF ("0" <= name[1]) & (name[1] <= "9") THEN
  376. RETURN SHORT(ORD(name[1])-ORD("0"));
  377. ELSE RETURN None
  378. END;
  379. ELSIF ("0"<=name[2]) & (name[2] <= "5") THEN
  380. IF name[1] = "1" THEN
  381. RETURN SHORT(ORD(name[2])-ORD("0")+10);
  382. ELSE RETURN None
  383. END;
  384. ELSE RETURN None
  385. END;
  386. ELSIF name[0] = "V" THEN
  387. IF name[1] = "R" THEN
  388. IF ("0" <= name[2]) & (name[2] <= "8") THEN
  389. RETURN SHORT(ORD(name[2])-ORD("0"))+16;
  390. ELSIF name[2] = 0X THEN (* VR as shortcut for VR0 *)
  391. RETURN 16
  392. ELSE
  393. RETURN None
  394. END;
  395. END;
  396. RETURN None;
  397. ELSIF name = "SP" THEN
  398. RETURN SP
  399. ELSIF name = "LR" THEN
  400. RETURN LR
  401. ELSE
  402. RETURN None
  403. END;
  404. END FindRegister;
  405. PROCEDURE NumberToSet(code: LONGINT): SET;
  406. VAR i: LONGINT; set: SET;
  407. BEGIN
  408. ASSERT(MAX(SET) >= 31);
  409. set := {};
  410. FOR i := 0 TO 31 DO
  411. IF ODD(code) THEN INCL(set, i) END;
  412. code := code DIV 2;
  413. END;
  414. RETURN set
  415. END NumberToSet;
  416. PROCEDURE SetToNumber(set: SET): LONGINT;
  417. VAR i, num: LONGINT;
  418. BEGIN
  419. ASSERT(MAX(SET) >= 31);
  420. num := 0;
  421. FOR i := 0 TO 31 DO
  422. IF i IN set THEN INC(num, ASH(1, i)) END;
  423. END;
  424. RETURN num
  425. END SetToNumber;
  426. (** setup instruction and mnemonic tables **)
  427. PROCEDURE InitInstructions;
  428. VAR curMnemonic: LONGINT;
  429. checkMnemonics: ARRAY numberMnemonics OF BOOLEAN;
  430. isimmP,isfloatP,isvecP: LONGINT; (*shorthands for positions iside the instruction word*)
  431. isSpecialBR:LONGINT;
  432. opcodeP,capabilityP,currOpCode, brModesP, brCondP:SET;
  433. PROCEDURE SortMnemonics(lo, hi: LONGINT);
  434. VAR i, j: LONGINT; x, t: NumberedName;
  435. BEGIN
  436. i := lo; j := hi;
  437. x := mnemonicsSorted[(lo+hi) DIV 2];
  438. WHILE (i <= j) DO
  439. WHILE (mnemonicsSorted[i].name < x.name) DO INC(i) END;
  440. WHILE (x.name < mnemonicsSorted[j].name) DO DEC(j) END;
  441. IF (i <= j) THEN
  442. t := mnemonicsSorted[i]; mnemonicsSorted[i] := mnemonicsSorted[j]; mnemonicsSorted[j] := t;
  443. INC(i); DEC(j)
  444. END
  445. END;
  446. IF (lo < j) THEN SortMnemonics(lo, j) END;
  447. IF (i < hi) THEN SortMnemonics(i, hi) END
  448. END SortMnemonics;
  449. PROCEDURE AddMnemonic(number: LONGINT; CONST name: ARRAY OF CHAR);
  450. BEGIN
  451. ASSERT(number<numberMnemonics);
  452. IF checkMnemonic THEN checkMnemonics[number] := TRUE END;
  453. curMnemonic := number;
  454. COPY (name, mnemonics[number].name);
  455. COPY (name, mnemonicsSorted[number].name);
  456. mnemonicsSorted[number].number := number;
  457. mnemonics[number].firstInstructionFormat := numberInstructionFormats;
  458. END AddMnemonic;
  459. PROCEDURE AddAlias(alias,number: LONGINT; CONST name: ARRAY OF CHAR);
  460. BEGIN
  461. IF checkMnemonic THEN checkMnemonics[alias] := TRUE END;
  462. COPY(name, mnemonicsSorted[alias].name);
  463. COPY(name, mnemonics[alias].name);
  464. mnemonicsSorted[alias].number := alias;
  465. mnemonics[alias].firstInstructionFormat := mnemonics[number].firstInstructionFormat;
  466. END AddAlias;
  467. PROCEDURE EndMnemonic;
  468. BEGIN
  469. mnemonics[curMnemonic].lastInstructionFormat := numberInstructionFormats-1;
  470. END EndMnemonic;
  471. PROCEDURE AddInstruction(code, mask: SET; op1, op2: OperandType; capabilities: SET);
  472. VAR instructionFormat: InstructionFormat;
  473. BEGIN
  474. instructionFormat.mnemonic := curMnemonic;
  475. instructionFormat.code := code;
  476. instructionFormat.mask := mask;
  477. instructionFormat.op1 := op1;
  478. instructionFormat.op2 := op2;
  479. instructionFormat.capabilities:= capabilities;
  480. instructionFormats[numberInstructionFormats] := instructionFormat;
  481. INC(numberInstructionFormats);
  482. END AddInstruction;
  483. PROCEDURE CheckMnemonics;
  484. VAR i : LONGINT;
  485. BEGIN
  486. FOR i := 0 TO numberMnemonics-1 DO
  487. ASSERT(checkMnemonics[i]);
  488. END;
  489. END CheckMnemonics;
  490. PROCEDURE Inverse(mnem1, mnem2: LONGINT);
  491. BEGIN
  492. inverseCondition[mnem1] := mnem2;
  493. inverseCondition[mnem2] := mnem1
  494. END Inverse;
  495. (*Turn a number into a set of bits at the start of an instruction word*)
  496. PROCEDURE makeOpcode(num: LONGINT) :SET;
  497. VAR shifted: LONGINT;
  498. BEGIN
  499. (*left shift then convert to set*)
  500. shifted:=LSL(num,( instructionW-opcodeW ) );
  501. RETURN NumberToSet(shifted);
  502. END makeOpcode;
  503. PROCEDURE makeCondition(num:LONGINT):SET;
  504. VAR shifted: LONGINT;
  505. BEGIN
  506. shifted:=LSL(num,( instructionW-opcodeW-conditionW) );
  507. RETURN NumberToSet(shifted);
  508. END makeCondition;
  509. BEGIN
  510. FOR curMnemonic := 0 TO numberMnemonics-1 DO
  511. checkMnemonics[curMnemonic] := FALSE;
  512. inverseCondition[curMnemonic] := -1;
  513. END;
  514. curMnemonic := -1;
  515. numberInstructionFormats := 0;
  516. (*
  517. oooo ddd 0 nnnnnnnnnn
  518. oooo ddd 1 xxxxxxxsss
  519. *)
  520. isimmP:=instructionW-1-opcodeW-regselW; (*18bit inW=> bit 10. If this bit is NOT set, there is an immediate.*)
  521. isfloatP:=isimmP-2; (*18 bit insW => bit 8*)
  522. isvecP:=isimmP-1; (*18 bit insW=> bit 9*)
  523. isSpecialBR:=isimmP;
  524. opcodeP:={(instructionW-opcodeW)..(instructionW-1)}; (*normally 14..17*)
  525. capabilityP:={isfloatP-1..isimmP}; (*normally 7..10*)
  526. brModesP:={(instructionW-opcodeW-regselW-3)..(instructionW-opcodeW-regselW-1)}; (*18bit=> 8..10*)
  527. brCondP:={(instructionW-opcodeW-4)..(instructionW-opcodeW-1)}; (*18bit => 10..13*)
  528. (*Note the actual opcode is the first argument in addinstruction, independent of mnemonic number *)
  529. (*Note: mov with isimm=1 and bit 3 becomes LDH*)
  530. currOpCode:=makeOpcode(0);
  531. AddMnemonic(opMOV, "MOV");
  532. AddInstruction({}, opcodeP+{isimmP}, Rd, Imm10,{});
  533. AddInstruction({isimmP}, {3}+capabilityP+opcodeP, Rd, Rs,{});
  534. AddInstruction({isvecP, isimmP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability}); (* TODO index *)
  535. AddInstruction({isvecP, isimmP}, capabilityP+opcodeP, Rd, VRs,{Global.VectorCapability}); (* TODO index *)
  536. EndMnemonic;
  537. (* LDH: oooo = 0000 *)
  538. AddMnemonic(opLDH, "LDH");
  539. AddInstruction({3, isimmP}, {3}+capabilityP+opcodeP, Rd, None,{});
  540. AddInstruction({3, isvecP, isimmP}, {3}+capabilityP+opcodeP, VRd, None,{Global.VectorCapability}); (* TODO index *)
  541. EndMnemonic;
  542. (* NOT: oooo = 0001 *)
  543. currOpCode:=makeOpcode(1);
  544. AddMnemonic(opNOT, "NOT");
  545. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  546. AddInstruction({isimmP}+currOpCode, capabilityP+opcodeP, Rd, Rs,{});
  547. AddInstruction({isimmP,isfloatP}+currOpCode, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  548. EndMnemonic;
  549. (* ADD: oooo = 0010 *)
  550. currOpCode:=makeOpcode(2);
  551. AddMnemonic(opADD, "ADD");
  552. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  553. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  554. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  555. EndMnemonic;
  556. (* bit 9 indicates a usage of vector registers, bit 8 indicates floating point instructions *)
  557. AddMnemonic(opFADD, "FADD");
  558. AddInstruction(currOpCode+{isimmP,isfloatP}, capabilityP+opcodeP, Rd, Rs,{Global.FloatingPointCapability});
  559. AddInstruction(currOpCode+{isimmP,isfloatP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.FloatingPointCapability,Global.VectorCapability});
  560. EndMnemonic;
  561. (*No idea what bit 7 does. Appears to be a capability that is defunct in hardware.*)
  562. AddMnemonic(opHADD, "HADD");
  563. AddInstruction(currOpCode+{isimmP,isfloatP,7}, capabilityP+opcodeP, Rd, VRs,{Global.VectorCapability});
  564. EndMnemonic;
  565. AddMnemonic(opFHADD, "FHADD");
  566. AddInstruction(currOpCode+{isimmP,isfloatP,isvecP,7}, capabilityP+opcodeP, Rd, VRs,{Global.FloatingPointCapability, Global.VectorCapability});
  567. EndMnemonic;
  568. (* SUB: oooo = 0011 *)
  569. currOpCode:=makeOpcode(3);
  570. AddMnemonic(opSUB, "SUB");
  571. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  572. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  573. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  574. EndMnemonic;
  575. AddMnemonic(opFSUB, "FSUB");
  576. AddInstruction(currOpCode+{isimmP,isfloatP}, capabilityP+opcodeP, Rd, Rs,{Global.FloatingPointCapability});
  577. AddInstruction(currOpCode+{isimmP,isfloatP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.FloatingPointCapability, Global.VectorCapability});
  578. EndMnemonic;
  579. (* AND: oooo = 0100 *)
  580. currOpCode:=makeOpcode(4);
  581. AddMnemonic(opAND, "AND");
  582. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  583. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  584. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  585. EndMnemonic;
  586. (* BIC: oooo = 0101 *)
  587. currOpCode:=makeOpcode(5);
  588. AddMnemonic(opBIC, "BIC");
  589. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  590. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  591. AddInstruction(currOpCode+{isvecP,isimmP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  592. EndMnemonic;
  593. (* OR: oooo = 0110 *)
  594. currOpCode:=makeOpcode(6);
  595. AddMnemonic(opOR, "OR");
  596. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  597. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  598. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  599. EndMnemonic;
  600. (* XOR: oooo = 0111 *)
  601. currOpCode:=makeOpcode(7);
  602. AddMnemonic(opXOR, "XOR");
  603. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  604. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  605. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  606. EndMnemonic;
  607. (* MUL: oooo = 1000 *)
  608. currOpCode:=makeOpcode(8);
  609. AddMnemonic(opMUL, "MUL");
  610. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  611. AddInstruction(currOpCode+{isimmP}, capabilityP+opcodeP, Rd, Rs,{});
  612. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  613. EndMnemonic;
  614. AddMnemonic(opFMUL, "FMUL");
  615. AddInstruction(currOpCode+{isimmP,isfloatP}, capabilityP+opcodeP, Rd, Rs,{Global.FloatingPointCapability});
  616. AddInstruction(currOpCode+{isfloatP,isvecP,isimmP}, capabilityP+opcodeP, VRd, VRs,{Global.FloatingPointCapability,Global.VectorCapability});
  617. EndMnemonic;
  618. (*opcode 9 wuld be div, is disabled.*)
  619. (* ROR: oooo = 1010 *)
  620. currOpCode:=makeOpcode(10);
  621. AddMnemonic(opROR, "ROR");
  622. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, Imm10,{});
  623. AddInstruction(currOpCode+{isimmP}, {isimmP}+opcodeP, Rd, Rs,{});
  624. AddInstruction(currOpCode+{isimmP,isvecP}, capabilityP+opcodeP, VRd, VRs,{Global.VectorCapability});
  625. AddInstruction(currOpCode+{isfloatP,isvecP,isimmP}, capabilityP+opcodeP, VRd0, Rs,{Global.VectorCapability});
  626. EndMnemonic;
  627. (* BR: oooo = 1011 *)
  628. currOpCode:=makeOpcode(11);
  629. AddMnemonic(opBR, "BR");
  630. AddInstruction(currOpCode+{isSpecialBR}, brModesP+opcodeP, Rs, None,{});
  631. EndMnemonic;
  632. (* SPSR: oooo = 1011 *)
  633. AddMnemonic(opSPSR, "SPSR");
  634. AddInstruction(currOpCode, {isSpecialBR}+opcodeP, Imm10, None,{});
  635. EndMnemonic;
  636. (* BLR: oooo = 1011 *)
  637. (* BLR Rd, Rs <--> Rd := PC+1; PC := Rs *)
  638. AddMnemonic(opBLR, "BLR");
  639. AddInstruction(currOpCode+{isSpecialBR,isSpecialBR-1}, brModesP+opcodeP, Rd, Rs,{});
  640. EndMnemonic;
  641. (* RTI: oooo = 1011 *)
  642. AddMnemonic(opIRET, "IRET");
  643. AddInstruction(currOpCode+{isSpecialBR,isSpecialBR-2}, brModesP+opcodeP, Rs, None,{});
  644. EndMnemonic;
  645. (* LD: 1100 ddd xnnnnnnn sss *)
  646. currOpCode:=makeOpcode(12);
  647. AddMnemonic(opLD, "LD");
  648. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, MemRegImm7,{});
  649. AddInstruction(currOpCode+{isimmP}, {isimmP}+opcodeP, VRd, MemRegImm7,{Global.VectorCapability});
  650. EndMnemonic;
  651. (* ST: 1101 ddd xnnnnnnn sss *)
  652. currOpCode:=makeOpcode(13);
  653. AddMnemonic(opST, "ST");
  654. AddInstruction(currOpCode, {isimmP}+opcodeP, Rd, MemRegImm7,{});
  655. AddInstruction(currOpCode+{isimmP}, {isimmP}+opcodeP, VRd, MemRegImm7,{Global.VectorCapability});
  656. EndMnemonic;
  657. (* BC
  658. 1110 cond nnnnnnnnnn
  659. cond
  660. 0000 Z Zero / equal BEQ
  661. 0001 ~Z Non-zero / unequal BNE
  662. 0010 C Carry / above or equal (unsigned) BAE
  663. 0011 ~C No carry / below (unsigned) BB
  664. 0100 N Negative BN
  665. 0101 ~N Not negative BNN
  666. 0110 V Overflow BO
  667. 0111 ~V No overflow BNO
  668. 1000 ~(~C | Z) Carry and no zero / above (unsigned) BA
  669. 1001 ~C | Z No carry or zero / below or equal (unsigned) BBE
  670. 1010 ~(N V) N=V / greater or equal (signed) BGE
  671. 1011 N V N V / less (signed) BLT
  672. 1100 ~((N V) | Z) greater or equal and ~ZF / greater (signed) BGT
  673. 1101 (N V) | Z less or Z / less or equal (signed) BLE
  674. 1110 TRUE Always BT
  675. 1111 FALSE Never BF
  676. *)
  677. currOpCode:=makeOpcode(14);
  678. AddMnemonic(opBEQ, "BEQ"); AddInstruction(currOpCode+makeCondition(0), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  679. AddMnemonic(opBNE, "BNE"); AddInstruction(currOpCode+makeCondition(1), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  680. AddMnemonic(opBAE, "BAE"); AddInstruction(currOpCode+makeCondition(2), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  681. AddMnemonic(opBB, "BB"); AddInstruction(currOpCode+makeCondition(3), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  682. AddMnemonic(opBN, "BN"); AddInstruction(currOpCode+makeCondition(4), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  683. AddMnemonic(opBNN, "BNN"); AddInstruction(currOpCode+makeCondition(5), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  684. AddMnemonic(opBO, "BO"); AddInstruction(currOpCode+makeCondition(6), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  685. AddMnemonic(opBNO, "BNO"); AddInstruction(currOpCode+makeCondition(7), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  686. AddMnemonic(opBA, "BA"); AddInstruction(currOpCode+makeCondition(8), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  687. AddMnemonic(opBBE, "BBE"); AddInstruction(currOpCode+makeCondition(9), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  688. AddMnemonic(opBGE, "BGE"); AddInstruction(currOpCode+makeCondition(10), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  689. AddMnemonic(opBLT, "BLT"); AddInstruction(currOpCode+makeCondition(11), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  690. AddMnemonic(opBGT, "BGT"); AddInstruction(currOpCode+makeCondition(12), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  691. AddMnemonic(opBLE, "BLE"); AddInstruction(currOpCode+makeCondition(13), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  692. AddMnemonic(opBT, "BT"); AddInstruction(currOpCode+makeCondition(14), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  693. AddMnemonic(opBF, "BF"); AddInstruction(currOpCode+makeCondition(15), opcodeP+brCondP, SignedImm10, None,{}); EndMnemonic;
  694. Inverse(opBEQ, opBNE);
  695. Inverse(opBAE, opBB);
  696. Inverse(opBN, opBNN);
  697. Inverse(opBO, opBNO);
  698. Inverse(opBA, opBBE);
  699. Inverse(opBGE, opBLT);
  700. Inverse(opBGT, opBLE);
  701. Inverse(opBT, opBF);
  702. AddAlias(opBZS,opBEQ,"BZS");
  703. AddAlias(opBZC,opBNE,"BZC");
  704. AddAlias(opBCS,opBAE,"BCS");
  705. AddAlias(opBCC,opBB,"BCC");
  706. AddAlias(opBNS,opBN,"BNS");
  707. AddAlias(opBNC,opBNN,"BNC");
  708. AddAlias(opBVS,opBO,"BVS");
  709. AddAlias(opBVC,opBNO,"BVC");
  710. (* BL: 1111 nnnnnnnnnnnnnn *)
  711. currOpCode:=makeOpcode(15);
  712. AddMnemonic(opBL, "BL");
  713. AddInstruction(currOpCode, opcodeP, Imm14, None,{});
  714. EndMnemonic;
  715. SortMnemonics(0, numberMnemonics-1);
  716. IF checkMnemonic THEN CheckMnemonics END;
  717. END InitInstructions;
  718. PROCEDURE InitRegister*(VAR operand: Operand; reg: LONGINT);
  719. BEGIN
  720. operand.type := Register;
  721. operand.register := SHORT(reg);
  722. END InitRegister;
  723. PROCEDURE InitImmediate*(VAR operand: Operand; bits: LONGINT; imm: LONGINT);
  724. BEGIN
  725. operand.type := Immediate;
  726. operand.size := bits;
  727. operand.imm := imm;
  728. END InitImmediate;
  729. PROCEDURE InitMemory*(VAR operand: Operand; reg1: RegisterIndex; imm: LONGINT);
  730. BEGIN
  731. operand.type := Memory;
  732. operand.register := reg1;
  733. operand.imm := imm;
  734. IF reg1 < 0 THEN
  735. operand.register := ZeroRegister;
  736. END;
  737. END InitMemory;
  738. (* generate immediate operand with fixup *)
  739. PROCEDURE InitFixup*(VAR operand: Operand; bits: SHORTINT; fixup: BinaryCode.Fixup (*symbol: Sections.Section; offset, displacement: LONGINT *));
  740. BEGIN
  741. operand.type := Immediate;
  742. operand.imm := 0;
  743. operand.size := bits;
  744. operand.fixup := fixup;
  745. (*
  746. operand.fixup := BinaryCode.NewFixup(BinaryCode.Absolute, 0, symbol, offset, displacement, 0, NIL);
  747. *)
  748. (*
  749. operand.symbol := symbol;
  750. operand.symbolOffset := offset;
  751. operand.displacement := displacement;
  752. *)
  753. END InitFixup;
  754. PROCEDURE AddFixup*(VAR operand: Operand; fixup: BinaryCode.Fixup);
  755. BEGIN
  756. ASSERT(operand.type IN {Immediate, Memory});
  757. operand.fixup := fixup
  758. END AddFixup;
  759. PROCEDURE InitOperand*(VAR operand: Operand);
  760. BEGIN
  761. operand.type := None;
  762. operand.register := None;
  763. operand.imm := 0;
  764. operand.fixup := NIL;
  765. (*
  766. operand.symbol := NIL;
  767. operand.symbolOffset := 0;
  768. operand.displacement := 0;
  769. *)
  770. END InitOperand;
  771. PROCEDURE DumpOperand*(w: Streams.Writer; CONST operand: Operand);
  772. BEGIN
  773. IF operand.type = None THEN RETURN END;
  774. CASE operand.type OF
  775. Register: IF operand.register >= 16 THEN w.String("V"); END; w.String("R"); w.Int(operand.register MOD 16, 1);
  776. |Immediate:
  777. IF operand.fixup # NIL THEN
  778. operand.fixup.Dump(w);
  779. ELSE
  780. w.Int(operand.imm, 1);
  781. END;
  782. |Memory:
  783. w.String("[");
  784. IF operand.register # 7 THEN
  785. w.String("R"); w.Int(operand.register, 1);
  786. IF operand.fixup # NIL THEN w.String("+"); operand.fixup.Dump(w)
  787. ELSIF operand.imm > 0 THEN w.String("+"); w.Int(operand.imm, 1)
  788. ELSIF operand.imm < 0 THEN w.String("-"); w.Int(-operand.imm, 1)
  789. END;
  790. ELSE
  791. w.Int(operand.imm, 1)
  792. END;
  793. w.String("]");
  794. END;
  795. END DumpOperand;
  796. PROCEDURE DumpInstruction*(w: Streams.Writer; CONST instruction: Instruction);
  797. VAR instructionFormat: InstructionFormat; first: BOOLEAN;
  798. PROCEDURE DumpOp(op: Operand);
  799. BEGIN
  800. IF op.type = None THEN RETURN END;
  801. IF first THEN w.String(" "); first := FALSE; ELSE w.String(", ") END;
  802. DumpOperand(w, op);
  803. END DumpOp;
  804. BEGIN
  805. IF instruction.format = None THEN
  806. w.String(" no format")
  807. ELSE
  808. instructionFormat := instructionFormats[instruction.format];
  809. w.String(mnemonics[instructionFormat.mnemonic].name);
  810. first := TRUE;
  811. DumpOp(instruction.op1);
  812. DumpOp(instruction.op2);
  813. END;
  814. END DumpInstruction;
  815. PROCEDURE DumpBits*(w: Streams.Writer; set: SET; numberBits: LONGINT);
  816. VAR i: LONGINT;
  817. BEGIN
  818. FOR i := numberBits-1 TO 0 BY -1 DO
  819. IF i IN set THEN w.String("1") ELSE w.String("0") END;
  820. END;
  821. END DumpBits;
  822. PROCEDURE DumpInstructionFormats*(context: Commands.Context);
  823. VAR i, j, k, mnemNum: LONGINT; instr: InstructionFormat; first: BOOLEAN; mnemonic: Mnemonic; options: Options.Options; sorted: BOOLEAN;
  824. PROCEDURE DumpType(type: INTEGER);
  825. BEGIN
  826. IF type = None THEN RETURN END;
  827. IF first THEN context.out.String(" "); first := FALSE; ELSE context.out.String(", ") END;
  828. CASE type OF
  829. |Rd: context.out.String("Rd")
  830. |Rs: context.out.String("Rs")
  831. |Imm10: context.out.String("imm10");
  832. |SignedImm10: context.out.String("SignedImm10");
  833. |Imm14: context.out.String("imm14");
  834. |MemRegImm7: context.out.String("MemRegImm7");
  835. ELSE
  836. context.out.String("error: type not found: DumpType ("); context.out.Int(type, 0); context.out.String(")");
  837. context.out.Ln;
  838. END;
  839. END DumpType;
  840. BEGIN
  841. NEW(options);
  842. options.Add("s", "sorted", Options.Flag);
  843. IF options.Parse(context.arg, context.error) THEN
  844. sorted := options.GetFlag("s");
  845. FOR i := 0 TO numberMnemonics-1 DO
  846. IF sorted THEN
  847. mnemNum := mnemonicsSorted[i].number
  848. ELSE
  849. mnemNum := i
  850. END;
  851. mnemonic := mnemonics[mnemNum];
  852. FOR j := mnemonic.firstInstructionFormat TO mnemonic.lastInstructionFormat DO
  853. instr := instructionFormats[j];
  854. ASSERT(mnemNum = instr.mnemonic);
  855. context.out.Int(j, 2); context.out.String(" ");
  856. context.out.String(mnemonic.name);
  857. k := 0; first := TRUE;
  858. DumpType(instr.op1);
  859. DumpType(instr.op2);
  860. context.out.Ln; context.out.String(" mask = "); DumpBits(context.out, instr.mask, 18);
  861. context.out.Ln; context.out.String(" code = "); DumpBits(context.out, instr.code, 18);
  862. context.out.Ln;
  863. END;
  864. END;
  865. END;
  866. END DumpInstructionFormats;
  867. END InstructionSet;
  868. PROCEDURE Hex(ch: CHAR): LONGINT;
  869. BEGIN
  870. IF (ch <= 'F') & (ch >= 'A') THEN RETURN ORD(ch)-ORD('A')+10
  871. ELSIF (ch <= 'f') & (ch >= 'a') THEN RETURN ORD(ch)-ORD('a')+10
  872. ELSIF (ch>='0') & (ch <='9') THEN RETURN ORD(ch)-ORD('0')
  873. ELSE HALT(100)
  874. END;
  875. END Hex;
  876. PROCEDURE ReadCode(file: Files.File): BitSets.BitSet;
  877. VAR r: Files.Reader; val, val2: LONGINT;line: ARRAY 10 OF CHAR; lineNr: LONGINT; bitSet: BitSets.BitSet; i: LONGINT;
  878. BEGIN
  879. (*todo: probably screws up on anything but 18 bit double packed*)
  880. IF file = NIL THEN RETURN NIL END;
  881. lineNr := 0;
  882. NEW(r, file, 0);
  883. NEW(bitSet,0);
  884. WHILE r.Available()>0 DO
  885. r.Ln(line);
  886. val:=0;
  887. i:=0;
  888. WHILE ORD(line[i])>0 DO(*read entire line*)
  889. val:=val*10H;
  890. val:=val+Hex(line[i]);
  891. INC(i);
  892. END;
  893. INC(lineNr);
  894. bitSet.Resize(lineNr*36);(*bitset is treated as series of 36 bit slots into which the individual words fit left aligned.*)
  895. bitSet.SetBits((lineNr-1)*36,decodeInstance.instructionW,val); (*extract word*)
  896. END;
  897. RETURN bitSet
  898. END ReadCode;
  899. PROCEDURE ReadData(file: Files.File): BitSets.BitSet;
  900. VAR r: Files.Reader; val, val2: LONGINT;line: ARRAY 10 OF CHAR; lineNr: LONGINT; bitSet: BitSets.BitSet; i: LONGINT;
  901. BEGIN
  902. IF file = NIL THEN RETURN NIL END;
  903. lineNr := 0;
  904. NEW(r, file, 0);
  905. NEW(bitSet,0);
  906. WHILE r.Available()>0 DO
  907. r.Ln(line);
  908. val := 0;
  909. FOR i := 0 TO 7 DO
  910. val := val*10H;
  911. val := val + Hex(line[i]);
  912. END;
  913. INC(lineNr);
  914. bitSet.Resize(lineNr*32);
  915. bitSet.SetBits((lineNr-1)*32, 32, val);
  916. END;
  917. RETURN bitSet
  918. END ReadData;
  919. PROCEDURE Disassemble*(context: Commands.Context);
  920. TYPE
  921. Disasm = OBJECT (Disassembler.Disassembler)
  922. PROCEDURE DisassembleInstruction(bitSet: BitSets.BitSet; VAR adr: LONGINT; maxInstructionSize: LONGINT; w:Streams.Writer);
  923. VAR instruction: Instruction; value: WORD; mnemonic: LONGINT;
  924. BEGIN
  925. (* maxInstructionSize can be ignored here *)
  926. value := bitSet.GetBits(adr*36,decodeInstance.instructionW); (*bitset treated as series of 36 bit slots, individual words left aligned.*)
  927. decodeInstance.Decode(value, instruction);
  928. decodeInstance.DumpInstruction(w, instruction);
  929. IF instruction.format # None THEN
  930. mnemonic := decodeInstance.instructionFormats[instruction.format].mnemonic;
  931. IF (mnemonic >= opBEQ) & (mnemonic <= opBF) OR (mnemonic = opBL) THEN
  932. WriteReference(instruction.op1.imm+adr+1, TRUE, w);
  933. ELSIF (mnemonic = opLD) OR (mnemonic = opST) THEN
  934. IF (instruction.op2.register = ZeroRegister) THEN
  935. WriteReference(instruction.op2.imm, FALSE, w);
  936. END;
  937. END;
  938. END;
  939. INC(adr);
  940. END DisassembleInstruction;
  941. END Disasm;
  942. VAR disassembler: Disasm; codeFileName, dataFileName, logFileName: Files.FileName; codeFile, dataFile, logFile: Files.File;code, data: BitSets.BitSet; options: Options.Options;
  943. address: LONGINT;
  944. instructionWidth: LONGINT;
  945. BEGIN
  946. IF context.arg.GetString(codeFileName) THEN
  947. codeFile := Files.Old(codeFileName);
  948. IF codeFile = NIL THEN context.out.String("file not found "); context.out.String(codeFileName); RETURN END;
  949. IF context.arg.GetString(dataFileName) THEN
  950. dataFile := Files.Old(dataFileName)
  951. ELSE
  952. dataFile := NIL;
  953. END;
  954. NEW(options);
  955. options.Add("l","logFile", Options.String);
  956. options.Add("a","address",Options.Integer);
  957. options.Add("w","instructionWidth",Options.Integer);
  958. IF options.Parse(context.arg, context.error) THEN
  959. IF ~options.GetInteger("w",instructionWidth) THEN instructionWidth:=18 END;
  960. TRACE(instructionWidth);
  961. IF ~options.GetInteger("a", address) THEN address := 0 END;
  962. NEW(decodeInstance,instructionWidth);
  963. NEW(disassembler, context.out);
  964. code := ReadCode(codeFile);
  965. data := ReadData(dataFile);
  966. IF options.GetString("logFile",logFileName) THEN
  967. logFile := Files.Old(logFileName);
  968. ELSE
  969. logFile := disassembler.GetLogFile(codeFileName)
  970. END;
  971. disassembler.Disassemble(code, data, 36, 32, logFile, address);
  972. END;
  973. END;
  974. END Disassemble;
  975. VAR
  976. decodeInstance: InstructionSet;
  977. BEGIN
  978. NEW(decodeInstance,18);
  979. END FoxTRMInstructionSet.
  980. System.FreeDownTo FoxTRMInstructionSet ~
  981. FoxTRMInstructionSet.DumpInstructionFormats -s ~
  982. FoxTRMInstructionSet.Test ~
  983. FoxTRMInstructionSet.Disassemble disastest.mem ~
  984. FoxTRMInstructionSet.Disassemble ins.mem ~