ARMDecoder.Mod 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. MODULE ARMDecoder;
  2. IMPORT SYSTEM, Decoder, Streams, KernelLog;
  3. CONST
  4. objFileSuffix = "Oba";
  5. none = -1;
  6. (* argument structure *)
  7. ArgNone = -2;
  8. ArgImm = 1;
  9. ArgReg = 2;
  10. ArgShift = 3;
  11. ArgRegImm = 11;
  12. ArgRegReg = 12;
  13. ArgRegShift = 13;
  14. ArgRegMem = 14;
  15. ArgRegRList = 15;
  16. ArgRegRegImm = 21;
  17. ArgRegRegReg = 22;
  18. ArgRegRegShift = 23;
  19. ArgRegRegMem = 24;
  20. ArgRegRegRegReg = 31;
  21. ArgRegRegRegImm = 32;
  22. ArgRegRegRegShift = 33;
  23. ArgCProcRegMem = 41;
  24. ArgCProcImmRegRegRegImm = 42;
  25. (* registers *)
  26. FP = 12; SP = 13; LR = 14; PC = 15; CPSR = 16; SPSR = 17;
  27. (* status register bits *)
  28. SRegC = 0; SRegX = 1; SRegS = 2; SRegF = 3;
  29. (* instructions *)
  30. opUNDEFINED = -2;
  31. opADC = 1;
  32. opADD = 2;
  33. opAND = 3;
  34. opASR = 4;
  35. opB = 5;
  36. opBIC = 6;
  37. opBKPT = 7;
  38. opBL = 8;
  39. opBLX = 9;
  40. opBX = 10;
  41. opCDP = 11;
  42. opCDP2 = 12;
  43. opCLZ = 13;
  44. opCMN = 14;
  45. opCMP = 15;
  46. opEOR = 16;
  47. opLDC = 17;
  48. opLDC2 = 18;
  49. opLDM = 19;
  50. opLDR = 20;
  51. opLDRB = 21;
  52. opLDRBT = 22;
  53. opLDRH = 23;
  54. opLDRSB = 24;
  55. opLDRSH = 25;
  56. opLDRT = 26;
  57. opLSL = 27;
  58. opLSR = 28;
  59. opMCR = 29;
  60. opMCR2 = 30;
  61. opMLA = 31;
  62. opMOV = 32;
  63. opMRC = 33;
  64. opMRC2 = 34;
  65. opMRS = 61;
  66. opMSR = 35;
  67. opMUL = 36;
  68. opMVN = 37;
  69. opORR = 38;
  70. opROR = 39;
  71. opRRX = 40;
  72. opRSB = 41;
  73. opRSC = 42;
  74. opSBC = 43;
  75. opSMLAL = 44;
  76. opSMULL = 45;
  77. opSTC = 46;
  78. opSTC2 = 47;
  79. opSTM = 48;
  80. opSTR = 49;
  81. opSTRB = 50;
  82. opSTRBT = 51;
  83. opSTRH = 52;
  84. opSTRT = 53;
  85. opSUB = 54;
  86. opSWI = 55;
  87. opSWP = 56;
  88. opSWPB = 62;
  89. opTEQ = 57;
  90. opTST = 58;
  91. opUMLAL = 59;
  92. opUMULL = 60;
  93. (* conditions *)
  94. EQ = 0;
  95. NE = 1;
  96. CSHS = 2;
  97. CCLO = 3;
  98. MI = 4;
  99. PL = 5;
  100. VS = 6;
  101. VC = 7;
  102. HI = 8;
  103. LS = 9;
  104. GE = 10;
  105. LT = 11;
  106. GT = 12;
  107. LE = 13;
  108. AL = 14;
  109. NV = 15;
  110. (* argument representations *)
  111. RepInt = 1;
  112. RepHex = 2;
  113. RepRelJmp = 10;
  114. (* immediate reg operations *)
  115. Lsl = 0;
  116. LSR = 1;
  117. Asr = 2;
  118. Ror = 3;
  119. RRX = 4;
  120. (* memory access addressing modes *)
  121. AddrModeReg = 1;
  122. AddrModeRegImm = 2;
  123. AddrModeRegReg = 3;
  124. AddrModeRegRegScale = 4;
  125. AddrModeDA = 5;
  126. AddrModeIA = 6;
  127. AddrModeDB = 7;
  128. AddrModeIB = 8;
  129. RegUpdateNone = 0;
  130. RegUpdatePre = 1;
  131. RegUpdatePost = 2;
  132. TYPE
  133. ARMArg = OBJECT
  134. END ARMArg;
  135. ARMArgImm = OBJECT (ARMArg)
  136. VAR
  137. imm, rep : LONGINT;
  138. PROCEDURE &New *(imm, rep : LONGINT);
  139. BEGIN
  140. SELF.imm := imm;
  141. SELF.rep := rep
  142. END New;
  143. END ARMArgImm;
  144. ARMArgReg = OBJECT (ARMArg)
  145. VAR
  146. reg : LONGINT;
  147. isCReg : BOOLEAN; (* coprocessor register? *)
  148. sregMask : SET; (* for CPSR, SPSR registers *)
  149. PROCEDURE &New *(reg : LONGINT);
  150. BEGIN
  151. SELF.reg := reg;
  152. isCReg := FALSE
  153. END New;
  154. END ARMArgReg;
  155. ARMArgRList = OBJECT (ARMArg)
  156. VAR
  157. regs : SET;
  158. addrMode : LONGINT;
  159. PROCEDURE &New *(regs : SET);
  160. BEGIN
  161. SELF.regs := regs;
  162. END New;
  163. END ARMArgRList;
  164. ARMArgMem = OBJECT (ARMArg)
  165. VAR
  166. addrMode, reg, regOffs, regScale, shift, immOffs : LONGINT;
  167. width : LONGINT;
  168. signed, translation : BOOLEAN;
  169. regUpdate : LONGINT;
  170. PROCEDURE &New *(adrMode, reg : LONGINT);
  171. BEGIN
  172. SELF.addrMode := adrMode;
  173. SELF.reg := reg;
  174. width := 4;
  175. regUpdate := RegUpdateNone;
  176. signed := FALSE;
  177. translation := FALSE
  178. END New;
  179. END ARMArgMem;
  180. ARMArgShift = OBJECT (ARMArg)
  181. VAR
  182. shiftImmOrReg, operation : LONGINT;
  183. reg : BOOLEAN;
  184. PROCEDURE &New *(operation, shiftImmOrReg : LONGINT; reg : BOOLEAN);
  185. BEGIN
  186. SELF.operation := operation;
  187. SELF.shiftImmOrReg := shiftImmOrReg;
  188. SELF.reg := reg
  189. END New;
  190. END ARMArgShift;
  191. ARMArgCProc = OBJECT (ARMArg)
  192. VAR
  193. cproc : LONGINT;
  194. PROCEDURE &New *(cproc : LONGINT);
  195. BEGIN
  196. SELF.cproc := cproc
  197. END New;
  198. END ARMArgCProc;
  199. ARMOpcode = OBJECT (Decoder.Opcode)
  200. VAR
  201. argStructure : LONGINT;
  202. op, cond : LONGINT;
  203. ccUpdate : BOOLEAN;
  204. arg1, arg2, arg3, arg4, arg5, arg6 : ARMArg;
  205. PROCEDURE &New*(proc : Decoder.ProcedureInfo; stream : Streams.Writer);
  206. BEGIN
  207. New^(proc, stream);
  208. instr := -1;
  209. ccUpdate := FALSE;
  210. argStructure := none
  211. END New;
  212. PROCEDURE PrintOpcodeBytes (w : Streams.Writer);
  213. BEGIN
  214. w.Hex(op, 0)
  215. END PrintOpcodeBytes;
  216. PROCEDURE PrintInstruction (w : Streams.Writer);
  217. VAR str : ARRAY 20 OF CHAR; writeCondition, writeLSMAddrMode : BOOLEAN;
  218. BEGIN
  219. writeCondition := TRUE; writeLSMAddrMode := FALSE;
  220. CASE instr OF
  221. opADC : str := "ADC"
  222. | opADD : str := "ADD"
  223. | opAND : str := "AND"
  224. | opASR : str := "ASR"
  225. | opB : str := "B"
  226. | opBIC : str := "BIC"
  227. | opBKPT : str := "BKPT"
  228. | opBL : str := "BL"
  229. | opBLX : str := "BLX"; writeCondition := FALSE
  230. | opBX : str := "BX"
  231. | opCDP : str := "CDP"
  232. | opCDP2 : str := "CDP2"; writeCondition := FALSE
  233. | opCLZ : str := "CLZ"
  234. | opCMN : str := "CMN"
  235. | opCMP : str := "CMP"
  236. | opEOR : str := "EOR"
  237. | opLDC : str := "LDC"
  238. | opLDC2 : str := "LDC2"; writeCondition := FALSE
  239. | opLDM : str := "LDM"; writeLSMAddrMode := TRUE
  240. | opLDR : str := "LDR"
  241. | opLDRB : str := "LDRB"
  242. | opLDRBT : str := "LDRBT"
  243. | opLDRH : str := "LDRH"
  244. | opLDRSB : str := "LDRSB"
  245. | opLDRSH : str := "LDRSH"
  246. | opLDRT : str := "LDRT"
  247. | opLSL : str := "LSL"
  248. | opLSR : str := "LSR"
  249. | opMCR : str := "MCR"
  250. | opMCR2 : str := "MCR2"; writeCondition := FALSE
  251. | opMLA : str := "MLA"
  252. | opMOV : str := "MOV"
  253. | opMRC : str := "MRC"
  254. | opMRC2 : str := "MRC2"; writeCondition := FALSE
  255. | opMRS : str := "MRS"
  256. | opMSR : str := "MSR"
  257. | opMUL : str := "MUL"
  258. | opMVN : str := "MVN"
  259. | opORR : str := "ORR"
  260. | opROR : str := "ROR"
  261. | opRRX : str := "RRX"
  262. | opRSB : str := "RSB"
  263. | opRSC : str := "RSC"
  264. | opSBC : str := "SBC"
  265. | opSMLAL : str := "SMLAL"
  266. | opSMULL : str := "SMULL"
  267. | opSTC : str := "STC"
  268. | opSTC2 : str := "STC2"; writeCondition := FALSE
  269. | opSTM : str := "STM"; writeLSMAddrMode := TRUE
  270. | opSTR : str := "STR"
  271. | opSTRB : str := "STRB"
  272. | opSTRBT : str := "STRBT"
  273. | opSTRH : str := "STRH"
  274. | opSTRT : str := "STRT"
  275. | opSUB : str := "SUB"
  276. | opSWI : str := "SWI"
  277. | opSWP : str := "SWP"
  278. | opSWPB : str := "SWPB"
  279. | opTEQ : str := "TEQ"
  280. | opTST : str := "TST"
  281. | opUMLAL : str := "UMLAL"
  282. | opUMULL : str := "UMULL"
  283. | opUNDEFINED : str := "{UNDEFINED}"
  284. ELSE
  285. KernelLog.String("Unknown instr = "); KernelLog.Int(instr, 0); KernelLog.String(", op = "); KernelLog.Hex(op, -1); KernelLog.Ln;
  286. str := "[unknown]"
  287. END;
  288. w.String(str);
  289. IF writeCondition THEN PrintCondition(w) END;
  290. IF writeLSMAddrMode THEN PrintLSMAddrMode(w) END;
  291. IF ccUpdate THEN w.String(" S")
  292. ELSIF argStructure = ArgRegMem THEN
  293. w.String(" ");
  294. IF arg2(ARMArgMem).signed THEN w.Char('S') END;
  295. IF arg2(ARMArgMem).width = 1 THEN w.Char('B')
  296. ELSIF arg2(ARMArgMem).width = 2 THEN w.Char('H')
  297. END;
  298. IF arg2(ARMArgMem).translation THEN w.Char('T') END;
  299. END
  300. END PrintInstruction;
  301. PROCEDURE PrintCondition (w : Streams.Writer);
  302. VAR str : ARRAY 6 OF CHAR;
  303. BEGIN
  304. w.Char(' ');
  305. CASE cond OF
  306. EQ : str := "EQ"
  307. | NE : str := "NE"
  308. | CSHS : str := "CS/HS"
  309. | CCLO : str := "CC/LO"
  310. | MI : str := "MI"
  311. | PL : str := "PL"
  312. | VS : str := "VS"
  313. | VC : str := "VC"
  314. | HI : str := "HI"
  315. | LS : str := "LS"
  316. | GE : str := "GE"
  317. | LT : str := "LT"
  318. | GT : str := "GT"
  319. | LE : str := "LE"
  320. | AL : str := ""
  321. | NV : str := "NV"
  322. END;
  323. w.String(str)
  324. END PrintCondition;
  325. PROCEDURE PrintLSMAddrMode (w : Streams.Writer);
  326. VAR str : ARRAY 6 OF CHAR;
  327. BEGIN
  328. ASSERT(argStructure = ArgRegRList);
  329. w.Char(' ');
  330. CASE arg2(ARMArgRList).addrMode OF
  331. AddrModeIA : str := "IA"
  332. | AddrModeIB : str := "IB"
  333. | AddrModeDA : str := "DA"
  334. | AddrModeDB : str := "DB"
  335. ELSE str := ""
  336. END;
  337. w.String(str)
  338. END PrintLSMAddrMode;
  339. PROCEDURE PrintArguments (w : Streams.Writer);
  340. BEGIN
  341. (* KernelLog.String("*argStructure = "); KernelLog.Int(argStructure, 0); KernelLog.String(", instr = "); KernelLog.Int(instr, 0); KernelLog.Ln; *)
  342. CASE argStructure OF
  343. ArgNone :
  344. | ArgImm : WriteImm(arg1(ARMArgImm), w)
  345. | ArgReg : WriteReg(arg1(ARMArgReg), w)
  346. | ArgRegReg : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w)
  347. | ArgRegRList : WriteRegRList(arg1(ARMArgReg), arg2(ARMArgRList), w)
  348. | ArgRegImm : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteImm(arg2(ARMArgImm), w)
  349. | ArgRegShift : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteShift(arg2(ARMArgShift), w)
  350. | ArgRegMem : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteMem(arg2(ARMArgMem), w)
  351. | ArgRegRegReg : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w)
  352. | ArgRegRegImm : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteImm(arg3(ARMArgImm), w)
  353. | ArgRegRegShift : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteShift(arg3(ARMArgShift), w)
  354. | ArgRegRegMem : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteMem(arg3(ARMArgMem), w)
  355. | ArgRegRegRegReg : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteReg(arg4(ARMArgReg), w)
  356. | ArgRegRegRegImm : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteImm(arg4(ARMArgImm), w)
  357. | ArgRegRegRegShift : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteShift(arg4(ARMArgShift), w)
  358. | ArgCProcRegMem : WriteCProc(arg1(ARMArgCProc), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteMem(arg3(ARMArgMem), w)
  359. | ArgCProcImmRegRegRegImm : WriteCProc(arg1(ARMArgCProc), w); w.String(", "); WriteImm(arg2(ARMArgImm), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteReg(arg4(ARMArgReg), w); w.String(", "); WriteReg(arg5(ARMArgReg), w); w.String(", "); WriteImm(arg2(ARMArgImm), w)
  360. ELSE
  361. KernelLog.String("argStructure = "); KernelLog.Int(argStructure, 0); KernelLog.Ln;
  362. w.String("{argStructure not specified!}")
  363. END
  364. END PrintArguments;
  365. PROCEDURE WriteImm (immArg : ARMArgImm; w : Streams.Writer);
  366. PROCEDURE WriteHex;
  367. VAR absImm : LONGINT;
  368. BEGIN
  369. absImm := immArg.imm;
  370. IF immArg.rep = RepRelJmp THEN
  371. (* add opcode position and length of full opcode to immediate argument value *)
  372. INC(absImm, LONGINT(offset + 4))
  373. END;
  374. Hex(absImm, w)
  375. END WriteHex;
  376. BEGIN
  377. IF immArg.rep = RepInt THEN
  378. w.Int(immArg.imm, 0)
  379. ELSIF immArg.rep = RepHex THEN
  380. WriteHex
  381. ELSE
  382. w.Int(immArg.imm, 0);
  383. w.String(" (");
  384. WriteHex;
  385. w.Char(')')
  386. END
  387. END WriteImm;
  388. PROCEDURE WriteReg (regArg : ARMArgReg; w : Streams.Writer);
  389. BEGIN
  390. IF regArg.isCReg THEN
  391. w.String("CR"); w.Int(regArg.reg, 0)
  392. ELSE
  393. WriteRegSymbol(regArg.reg, w);
  394. IF regArg.reg >= CPSR THEN
  395. IF regArg.sregMask * {SRegC} # {} THEN w.String("c") END;
  396. IF regArg.sregMask * {SRegX} # {} THEN w.String("x") END;
  397. IF regArg.sregMask * {SRegS} # {} THEN w.String("s") END;
  398. IF regArg.sregMask * {SRegF} # {} THEN w.String("f") END
  399. END
  400. END
  401. END WriteReg;
  402. PROCEDURE WriteRegSymbol (reg : LONGINT; w : Streams.Writer);
  403. BEGIN
  404. CASE reg OF
  405. FP : w.String("FP")
  406. | SP : w.String("SP")
  407. | LR : w.String("LR")
  408. | PC : w.String("PC")
  409. | CPSR : w.String("CPSR")
  410. | SPSR : w.String("SPSR")
  411. ELSE
  412. w.Char('R'); w.Int(reg, 0)
  413. END
  414. END WriteRegSymbol;
  415. PROCEDURE WriteShiftSymbol (op : LONGINT; w : Streams.Writer);
  416. BEGIN
  417. CASE op OF
  418. Lsl : w.String("LSL ")
  419. | LSR : w.String("LSR ")
  420. | Asr : w.String("ASR ")
  421. | Ror : w.String("ROR ")
  422. | RRX : w.String("RRX ")
  423. END;
  424. END WriteShiftSymbol;
  425. PROCEDURE WriteShift (shiftArg : ARMArgShift; w : Streams.Writer);
  426. BEGIN
  427. WriteShiftSymbol(shiftArg.operation, w);
  428. IF shiftArg.operation # RRX THEN
  429. IF shiftArg.reg THEN
  430. ASSERT(shiftArg.shiftImmOrReg < CPSR);
  431. WriteRegSymbol(shiftArg.shiftImmOrReg, w)
  432. ELSE
  433. w.Char('#');
  434. Hex(shiftArg.shiftImmOrReg, w)
  435. END
  436. END
  437. END WriteShift;
  438. PROCEDURE WriteMem (memArg : ARMArgMem; w : Streams.Writer);
  439. PROCEDURE WriteEnd;
  440. BEGIN
  441. IF memArg.regUpdate # RegUpdatePost THEN
  442. w.Char("]");
  443. IF memArg.regUpdate = RegUpdatePre THEN w.Char('!') END
  444. END
  445. END WriteEnd;
  446. BEGIN
  447. w.Char('[');
  448. WriteRegSymbol(memArg.reg, w);
  449. IF memArg.regUpdate = RegUpdatePost THEN w.Char(']') END;
  450. CASE memArg.addrMode OF
  451. AddrModeReg : w.Char(']')
  452. | AddrModeRegImm :
  453. w.String(", #");
  454. IF memArg.immOffs < 0 THEN w.Char('-'); Hex(-memArg.immOffs, w) ELSE Hex(memArg.immOffs, w) END;
  455. WriteEnd
  456. | AddrModeRegReg :
  457. w.String(", "); WriteRegSymbol(memArg.regOffs, w); WriteEnd
  458. | AddrModeRegRegScale : w.String(", "); WriteRegSymbol(memArg.regOffs, w); w.String(", "); WriteShiftSymbol(memArg.shift, w); w.String(" #"); w.Int(memArg.regScale, 0); WriteEnd
  459. END
  460. END WriteMem;
  461. PROCEDURE WriteRegRList (regArg : ARMArgReg; rListArg : ARMArgRList; w : Streams.Writer);
  462. VAR i, lastStart : LONGINT; notFirst : BOOLEAN;
  463. PROCEDURE PrintRegs (start, end : LONGINT);
  464. BEGIN
  465. IF start >= 0 THEN
  466. IF notFirst THEN w.String(", ") END;
  467. IF start < end THEN (* print range *)
  468. WriteRegSymbol(start, w); w.String(" - "); WriteRegSymbol(end, w)
  469. ELSE (* print single reg *)
  470. WriteRegSymbol(start, w)
  471. END;
  472. notFirst := TRUE
  473. END
  474. END PrintRegs;
  475. BEGIN
  476. WriteRegSymbol(regArg.reg, w);
  477. IF rListArg.addrMode # none THEN w.Char('!') END;
  478. w.String(", {");
  479. lastStart := -1;
  480. notFirst := FALSE;
  481. FOR i := 0 TO PC DO
  482. IF rListArg.regs * {i} # {} THEN IF lastStart < 0 THEN lastStart := i END
  483. ELSE
  484. PrintRegs(lastStart, i-1); lastStart := -1
  485. END;
  486. END;
  487. PrintRegs(lastStart, PC);
  488. w.Char('}')
  489. END WriteRegRList;
  490. PROCEDURE WriteCProc (cProcArg : ARMArgCProc; w : Streams.Writer);
  491. BEGIN
  492. w.Char('p'); w.Int(cProcArg.cproc, 0)
  493. END WriteCProc;
  494. END ARMOpcode;
  495. ARMDecoder = OBJECT (Decoder.Decoder)
  496. VAR
  497. bit24To27, bit20To23, bit16To19, bit12To15, bit8To11, bit4To7, bit0To3 : LONGINT;
  498. PROCEDURE NewOpcode() : Decoder.Opcode;
  499. VAR
  500. opcode : ARMOpcode;
  501. BEGIN
  502. NEW(opcode, currentProc, outputStreamWriter);
  503. RETURN opcode
  504. END NewOpcode;
  505. PROCEDURE DecodeThis(opcode : Decoder.Opcode);
  506. VAR
  507. armOpcode : ARMOpcode;
  508. opSet : SET;
  509. code, category : LONGINT;
  510. BEGIN
  511. armOpcode := opcode(ARMOpcode);
  512. armOpcode.op := ReadLInt();
  513. IF bigEndian THEN SwapBytes(armOpcode.op) END;
  514. opSet := SYSTEM.VAL(SET, armOpcode.op);
  515. (* KernelLog.String("op = "); KernelLog.Hex(armOpcode.op, 0); KernelLog.String(" -> "); *)
  516. code := armOpcode.op;
  517. bit0To3 := code MOD 10H; code := code DIV 10H; (* split instruction *)
  518. bit4To7 := code MOD 10H; code := code DIV 10H;
  519. bit8To11 := code MOD 10H; code := code DIV 10H;
  520. bit12To15 := code MOD 10H; code := code DIV 10H;
  521. bit16To19 := code MOD 10H; code := code DIV 10H;
  522. bit20To23 := code MOD 10H; code := code DIV 10H;
  523. bit24To27 := code MOD 10H; code := code DIV 10H;
  524. armOpcode.cond := code MOD 10H;
  525. category := bit24To27 DIV 2;
  526. IF armOpcode.cond = 15 THEN
  527. IF category = 5 THEN
  528. BranchToThumb(armOpcode, armOpcode.op);
  529. RETURN
  530. ELSIF ((category = 7) & (bit24To27 = 0EH)) OR (category = 6) THEN (* not undefined *)
  531. ELSE
  532. armOpcode.instr := opUNDEFINED;
  533. armOpcode.argStructure := ArgNone;
  534. RETURN
  535. END
  536. END;
  537. CASE category OF
  538. 0 :
  539. IF (opSet * {4, 7}) = {4, 7} THEN
  540. MultipliesExtraLS(armOpcode)
  541. ELSIF (opSet * {20, 23, 24}) = {24} THEN Miscellaneous(armOpcode)
  542. ELSE DataProcessing(armOpcode)
  543. END
  544. | 1 :
  545. IF (opSet * {20, 21, 23, 24}) = {21, 24} THEN
  546. SRegTransfer(armOpcode)
  547. ELSIF (opSet * {20, 21, 23, 24}) = {24} THEN
  548. armOpcode.instr := opUNDEFINED;
  549. armOpcode.argStructure := ArgNone
  550. ELSE DataProcessing(armOpcode)
  551. END
  552. | 2 : LoadStore(armOpcode)
  553. | 3 :
  554. IF (opSet * {4}) = {4} THEN
  555. armOpcode.instr := opUNDEFINED;
  556. armOpcode.argStructure := ArgNone
  557. ELSE LoadStore(armOpcode)
  558. END
  559. | 4 : LoadStoreMultiple(armOpcode)
  560. | 5 : Branch(armOpcode)
  561. | 6 : CoprocLoadStoreDRegTransfer(armOpcode)
  562. | 7 : KernelLog.String("check2"); KernelLog.Ln;
  563. IF (opSet * {24}) = {24} THEN SoftwareInterrupt(armOpcode)
  564. ELSIF (opSet * {4}) = {4} THEN CoprocRegTransfer(armOpcode)
  565. ELSE CoprocDataProcessing(armOpcode)
  566. END
  567. END
  568. END DecodeThis;
  569. PROCEDURE DecodeShifterOperand(op : LONGINT; VAR argStructure : LONGINT; VAR arg1, arg2 : ARMArg);
  570. VAR
  571. Rm, shiftImmOrReg, operation, mode : LONGINT;
  572. regOp : BOOLEAN;
  573. regArg : ARMArgReg;
  574. immArg : ARMArgImm;
  575. shiftArg : ARMArgShift;
  576. BEGIN
  577. IF (SYSTEM.VAL(SET, op) * {25}) = {25} THEN (* I Bit *)
  578. argStructure := ArgImm;
  579. NEW(immArg, ROT(op MOD 100H, -2*bit8To11), RepHex); arg1 := immArg;
  580. ELSE
  581. Rm := op MOD 10H;
  582. NEW(regArg, Rm); arg1 := regArg;
  583. argStructure := ArgRegShift;
  584. mode := bit4To7 MOD 8; (* type of register addressing mode *)
  585. IF mode = 0 THEN (* Register / Logical shift left by immediate *)
  586. shiftImmOrReg := (op MOD 1000H) DIV 80H;
  587. IF shiftImmOrReg = 0 THEN argStructure := ArgReg
  588. ELSE
  589. NEW(shiftArg, Lsl, shiftImmOrReg, FALSE); arg2 := shiftArg
  590. END
  591. ELSIF ((op MOD 1000H) DIV 10H) = 6 THEN (* rotate right with extend *)
  592. NEW(shiftArg, RRX, 0, FALSE); arg2 := shiftArg
  593. ELSE
  594. CASE mode OF
  595. 1 : operation := Lsl
  596. | 2,3 : operation := LSR
  597. | 4,5 : operation := Asr
  598. | 6,7 : operation := Ror
  599. END;
  600. IF ODD(mode) THEN
  601. regOp := TRUE;
  602. shiftImmOrReg := bit8To11
  603. ELSE
  604. regOp := FALSE;
  605. shiftImmOrReg := (op MOD 1000H) DIV 80H
  606. END;
  607. NEW(shiftArg, operation, shiftImmOrReg, regOp); arg2 := shiftArg
  608. END
  609. END
  610. END DecodeShifterOperand;
  611. PROCEDURE DataProcessing (opcode : ARMOpcode);
  612. VAR SBit : BOOLEAN; Rn, Rd, type : LONGINT;
  613. regArg : ARMArgReg; argSh1, argSh2 : ARMArg;
  614. shStruct : LONGINT;
  615. BEGIN
  616. CASE (opcode.op MOD 2000000H) DIV 200000H OF (* opcode *)
  617. 0 : opcode.instr := opAND; type := 3
  618. | 1 : opcode.instr := opEOR; type := 3
  619. | 2 : opcode.instr := opSUB; type := 3
  620. | 3 : opcode.instr := opRSB; type := 3
  621. | 4 : opcode.instr := opADD; type := 3
  622. | 5 : opcode.instr := opADC; type := 3
  623. | 6 : opcode.instr := opSBC; type := 3
  624. | 7 : opcode.instr := opRSC; type := 3
  625. | 8 : opcode.instr := opTST; type := 2
  626. | 9 : opcode.instr := opTEQ; type := 2
  627. | 10 : opcode.instr := opCMP; type := 2
  628. | 11 : opcode.instr := opCMN; type := 2
  629. | 12 : opcode.instr := opORR; type := 3
  630. | 13 : opcode.instr := opMOV; type := 1
  631. | 14 : opcode.instr := opBIC; type := 3
  632. | 15 : opcode.instr := opMVN; type := 1
  633. END;
  634. DecodeShifterOperand(opcode.op, shStruct, argSh1, argSh2);
  635. IF (SYSTEM.VAL(SET, opcode.op) * {20}) = {20} THEN SBit := TRUE ELSE SBit := FALSE END;
  636. opcode.ccUpdate := SBit & (type # 2);
  637. Rn := bit16To19;
  638. Rd := bit12To15;
  639. IF (type = 1) OR (type = 2) THEN
  640. opcode.argStructure := shStruct + 10;
  641. IF type = 1 THEN NEW(regArg, Rd) ELSE NEW(regArg, Rn) END;
  642. opcode.arg1 := regArg; opcode.arg2 := argSh1; opcode.arg3 := argSh2
  643. ELSIF type = 3 THEN
  644. opcode.argStructure := shStruct + 20;
  645. NEW(regArg, Rd); opcode.arg1 := regArg;
  646. NEW(regArg, Rn); opcode.arg2 := regArg;
  647. opcode.arg3 := argSh1; opcode.arg4 := argSh2
  648. END
  649. END DataProcessing;
  650. PROCEDURE Miscellaneous (opcode : ARMOpcode);
  651. VAR regArg : ARMArgReg; immArg : ARMArgImm;
  652. BEGIN
  653. CASE bit4To7 MOD 2 OF
  654. 0 : SRegTransfer(opcode)
  655. | 1 :
  656. IF bit20To23 = 6 THEN
  657. opcode.instr := opCLZ;
  658. opcode.argStructure := ArgRegReg;
  659. NEW(regArg, bit12To15); opcode.arg1 := regArg;
  660. NEW(regArg, bit0To3); opcode.arg2 := regArg
  661. ELSIF LSH(opcode.op, -20) = 0E12H THEN
  662. IF bit4To7 = 7 THEN
  663. opcode.instr := opBKPT;
  664. NEW(immArg, (((opcode.op MOD 100000) DIV 100H) * 10H) + (opcode.op MOD 10H), RepHex);
  665. opcode.argStructure := ArgImm;
  666. opcode.arg1 := immArg
  667. ELSIF bit4To7 = 1 THEN
  668. opcode.instr := opBX;
  669. NEW(regArg, bit0To3); opcode.arg1 := regArg;
  670. opcode.argStructure := ArgReg
  671. END
  672. END
  673. END
  674. END Miscellaneous;
  675. PROCEDURE MultipliesExtraLS (opcode : ARMOpcode);
  676. VAR op1: LONGINT;
  677. regA, regB, regC, regD : ARMArgReg; memArg : ARMArgMem;
  678. argSh1, argSh2 : ARMArg;
  679. shStruct : LONGINT;
  680. BEGIN
  681. op1 := bit20To23 DIV 2;
  682. opcode.ccUpdate := (bit20To23 MOD 2) = 1; (* S bit set? *)
  683. NEW(regA, bit16To19);
  684. NEW(regB, bit12To15);
  685. NEW(regC, bit8To11);
  686. NEW(regD, bit0To3);
  687. IF bit24To27 = 1 THEN (* SWP/SWPB *)
  688. NEW(memArg, AddrModeReg, regA.reg);
  689. opcode.argStructure := ArgRegRegMem;
  690. opcode.arg1 := regB; opcode.arg2 := regD; opcode.arg3 := memArg;
  691. IF bit20To23 = 0 THEN opcode.instr := opSWP ELSE opcode.instr := opSWPB END
  692. ELSE
  693. opcode.argStructure := ArgRegRegRegReg;
  694. opcode.arg1 := regB; opcode.arg2 := regA; opcode.arg3 := regD; opcode.arg4 := regC;
  695. CASE op1 OF
  696. 0 : opcode.instr := opMUL; opcode.argStructure := ArgRegRegReg; opcode.arg1 := regA; opcode.arg2 := regD; opcode.arg3 := regC
  697. | 1 : opcode.instr := opMLA; opcode.arg1 := regA; opcode.arg2 := regD; opcode.arg3 := regC; opcode.arg4 := regB
  698. | 3 : opcode.instr := opRSB; opcode.arg1 := regB; opcode.arg2 := regA; DecodeShifterOperand(opcode.op, shStruct, argSh1, argSh2); opcode.argStructure := shStruct + 20; opcode.arg3 := argSh1; opcode.arg4 := argSh2
  699. | 4 : opcode.instr := opUMULL
  700. | 5 : opcode.instr := opUMLAL
  701. | 6 : opcode.instr := opSMULL
  702. | 7 : opcode.instr := opSMLAL
  703. END
  704. END
  705. END MultipliesExtraLS;
  706. PROCEDURE SRegTransfer (opcode : ARMOpcode);
  707. VAR regArg : ARMArgReg; immArg : ARMArgImm;
  708. BEGIN
  709. opcode.argStructure := ArgRegReg;
  710. IF (bit20To23 DIV 4) = 1 THEN NEW(regArg, SPSR) ELSE NEW(regArg, CPSR) END;
  711. IF (bit20To23 MOD 4) # 2 THEN
  712. opcode.instr := opMRS;
  713. opcode.arg2 := regArg;
  714. NEW(regArg, bit12To15); opcode.arg1 := regArg
  715. ELSE
  716. opcode.instr := opMSR;
  717. regArg.sregMask := SYSTEM.VAL(SET, bit16To19);
  718. opcode.arg1 := regArg;
  719. IF (bit24To27 DIV 2) = 1 THEN (* immediate operand *)
  720. NEW(immArg, ROT(opcode.op MOD 100H, -2*bit8To11), RepHex); (* 8 bit imm rotated by rotate imm *)
  721. opcode.arg2 := immArg
  722. ELSE NEW(regArg, bit0To3); opcode.arg2 := regArg
  723. END
  724. END
  725. END SRegTransfer;
  726. PROCEDURE LoadStore (opcode : ARMOpcode);
  727. VAR regArg : ARMArgReg; memArg : ARMArgMem;
  728. P, L, W, B, U : BOOLEAN;
  729. offset12 : LONGINT;
  730. BEGIN
  731. opcode.argStructure := ArgRegMem;
  732. NEW(regArg, bit12To15); opcode.arg1 := regArg;
  733. P := bit24To27 MOD 2 = 1;
  734. L := bit20To23 MOD 2 = 1;
  735. W := (bit20To23 MOD 4) DIV 2 = 1;
  736. B := (bit20To23 MOD 8) DIV 4 = 1;
  737. U := bit20To23 DIV 8 = 1;
  738. offset12 := opcode.op MOD 1000H;
  739. (* determine memory location and addressing mode *)
  740. IF (bit24To27 DIV 2) = 2 THEN (* immediate offset/index *)
  741. IF offset12 = 0 THEN NEW(memArg, AddrModeReg, bit16To19)
  742. ELSE
  743. NEW(memArg, AddrModeRegImm, bit16To19);
  744. IF U THEN memArg.immOffs := offset12 ELSE memArg.immOffs := -offset12 END
  745. END
  746. ELSE (* register offset/index *)
  747. IF (bit4To7 = 0) & (bit8To11 = 0) THEN
  748. NEW(memArg, AddrModeRegReg, bit16To19); memArg.regOffs := bit0To3
  749. ELSE
  750. NEW(memArg, AddrModeRegRegScale, bit16To19); memArg.regOffs := bit0To3;
  751. memArg.shift := (bit4To7 MOD 8) DIV 2;
  752. memArg.regScale := (opcode.op MOD 1000H) DIV 80H
  753. END
  754. END;
  755. IF L THEN opcode.instr := opLDR ELSE opcode.instr := opSTR END;
  756. IF ~P THEN (* P = 0, post index addressing *)
  757. IF memArg.addrMode # AddrModeReg THEN memArg.regUpdate := RegUpdatePost END;
  758. memArg.immOffs := opcode.op MOD 1000H;
  759. ELSE (* P = 1, offset or pre-indexed addressing *)
  760. IF W THEN (* base register update *)
  761. memArg.regUpdate := RegUpdatePre;
  762. END
  763. END;
  764. IF W THEN memArg.translation := TRUE END;
  765. IF B THEN memArg.width := 1 END;
  766. opcode.arg2 := memArg
  767. END LoadStore;
  768. PROCEDURE LoadStoreMultiple (opcode : ARMOpcode);
  769. VAR regArg : ARMArgReg; regListArg : ARMArgRList;
  770. P, U, S, W, L : BOOLEAN;
  771. BEGIN
  772. P := bit24To27 MOD 2 = 1;
  773. U := bit20To23 DIV 8 = 1;
  774. S := (bit20To23 MOD 8) DIV 4 = 1;
  775. W := (bit20To23 MOD 4) DIV 2 = 1;
  776. L := bit20To23 MOD 2 = 1;
  777. IF L THEN opcode.instr := opLDM ELSE opcode.instr := opSTM END;
  778. NEW(regArg, bit16To19);
  779. NEW(regListArg, SYSTEM.VAL(SET, opcode.op MOD 10000H));
  780. IF W THEN
  781. IF P THEN IF U THEN regListArg.addrMode := AddrModeIB ELSE regListArg.addrMode := AddrModeDB END
  782. ELSE IF U THEN regListArg.addrMode := AddrModeIA ELSE regListArg.addrMode := AddrModeDA END
  783. END
  784. ELSE regListArg.addrMode := none END;
  785. opcode.argStructure := ArgRegRList;
  786. opcode.arg1 := regArg;
  787. opcode.arg2 := regListArg
  788. END LoadStoreMultiple;
  789. PROCEDURE Branch (opcode : ARMOpcode);
  790. VAR immArg : ARMArgImm;
  791. BEGIN
  792. IF (SYSTEM.VAL(SET, opcode.op) * {24}) = {24} THEN opcode.instr := opBL
  793. ELSE opcode.instr := opB
  794. END;
  795. opcode.argStructure := ArgImm;
  796. NEW(immArg, (opcode.op MOD 1000000H), RepRelJmp);
  797. SignExtension(immArg.imm, 24);
  798. immArg.imm := (immArg.imm + 1) *4;
  799. opcode.arg1 := immArg
  800. END Branch;
  801. PROCEDURE BranchToThumb (opcode : ARMOpcode; op : LONGINT);
  802. VAR sImmed24, targetAddr : LONGINT; immArg : ARMArgImm; regArg : ARMArgReg;
  803. BEGIN
  804. opcode.instr := opBLX;
  805. IF opcode.cond = 15 THEN
  806. sImmed24 := opcode.op MOD 1000000H;
  807. targetAddr := (bit24To27 MOD 2)*2 + ASH(LSH(sImmed24, 8), -6); (* sign extend *)
  808. NEW(immArg, targetAddr, RepRelJmp); opcode.arg1 := immArg;
  809. opcode.argStructure := ArgImm
  810. ELSE
  811. NEW(regArg, bit0To3); opcode.arg1 := regArg;
  812. opcode.argStructure := ArgReg
  813. END
  814. END BranchToThumb;
  815. PROCEDURE CoprocLoadStoreDRegTransfer (opcode : ARMOpcode);
  816. VAR cProcArg : ARMArgCProc; memArg : ARMArgMem; regArg : ARMArgReg;
  817. P, U, W, mul4 : BOOLEAN;
  818. BEGIN
  819. IF (bit20To23 MOD 2) = 1 THEN opcode.instr := opLDC ELSE opcode.instr := opSTC END;
  820. P := (bit24To27 MOD 2) = 1; (* P bit *)
  821. U := (bit20To23 DIV 8) = 1; (* U bit *)
  822. W := ((bit20To23 MOD 4) DIV 2) = 1; (* W bit *)
  823. mul4 := TRUE;
  824. opcode.argStructure := ArgCProcRegMem;
  825. NEW(memArg, AddrModeRegImm, bit16To19);
  826. IF P THEN
  827. memArg.regUpdate := RegUpdatePost;
  828. IF ~W THEN mul4 := FALSE END (* this is the option argument, therefore it is not multiplied by 4, but represented the same way like a post update offset *)
  829. ELSE
  830. IF W THEN memArg.regUpdate := RegUpdatePre
  831. ELSE memArg.regUpdate := RegUpdateNone
  832. END
  833. END;
  834. IF U THEN memArg.immOffs := (opcode.op MOD 100H) ELSE memArg.immOffs := - (opcode.op MOD 100H) END;
  835. IF mul4 THEN memArg.immOffs := memArg.immOffs * 4 END;
  836. NEW(cProcArg, bit8To11); opcode.arg1 := cProcArg;
  837. NEW(regArg, bit12To15); regArg.isCReg := TRUE;
  838. opcode.arg1 := cProcArg; opcode.arg2 := regArg; opcode.arg3 := memArg
  839. END CoprocLoadStoreDRegTransfer;
  840. PROCEDURE CoprocDataProcessing (opcode : ARMOpcode);
  841. BEGIN
  842. CoprocRegTransfer(opcode);
  843. IF opcode.cond = 15 THEN opcode.instr := opCDP2 ELSE opcode.instr := opCDP END;
  844. opcode.arg2(ARMArgImm).imm := bit20To23
  845. END CoprocDataProcessing;
  846. PROCEDURE CoprocRegTransfer (opcode : ARMOpcode);
  847. VAR immArg : ARMArgImm; regArg : ARMArgReg; cProcArg : ARMArgCProc;
  848. BEGIN
  849. IF (bit20To23 MOD 2) = 1 THEN
  850. IF opcode.cond = 15 THEN opcode.instr := opMRC2 ELSE opcode.instr := opMRC END
  851. ELSE
  852. IF opcode.cond = 15 THEN opcode.instr := opMCR2 ELSE opcode.instr := opMCR END
  853. END;
  854. opcode.argStructure := ArgCProcImmRegRegRegImm;
  855. NEW(cProcArg, bit8To11); opcode.arg1 := cProcArg;
  856. NEW(immArg, bit20To23 DIV 2, RepInt); opcode.arg2 := immArg; (* opcode-1 *)
  857. NEW(regArg, bit12To15); opcode.arg3 := regArg;
  858. NEW(regArg, bit16To19); regArg.isCReg := TRUE; opcode.arg4 := regArg;
  859. NEW(regArg, bit0To3); regArg.isCReg := TRUE; opcode.arg5 := regArg;
  860. NEW(immArg, bit4To7 DIV 2, RepInt); opcode.arg6 := immArg
  861. END CoprocRegTransfer;
  862. PROCEDURE SoftwareInterrupt (opcode : ARMOpcode);
  863. VAR immArg : ARMArgImm;
  864. BEGIN
  865. NEW(immArg, opcode.op MOD 1000000H, RepHex);
  866. opcode.instr := opSWI;
  867. opcode.argStructure := ArgImm;
  868. opcode.arg1 := immArg
  869. END SoftwareInterrupt;
  870. PROCEDURE SignExtension (VAR x : LONGINT; length : LONGINT);
  871. BEGIN
  872. ASSERT((length > 0) & (length <= 32));
  873. x := LSH(x, 32-length);
  874. x := ASH(x, length-32)
  875. END SignExtension;
  876. END ARMDecoder;
  877. VAR
  878. bigEndian : BOOLEAN;
  879. PROCEDURE SetBigEndian*;
  880. BEGIN
  881. bigEndian := TRUE;
  882. END SetBigEndian;
  883. PROCEDURE SetLittleEndian*;
  884. BEGIN
  885. bigEndian := FALSE;
  886. END SetLittleEndian;
  887. PROCEDURE Hex(n: LONGINT; w : Streams.Writer); (* procedure from PCARMDecoder.Mod *)
  888. VAR i, j: INTEGER; s, t : ARRAY 10 OF CHAR;
  889. BEGIN
  890. i := 0;
  891. REPEAT
  892. IF n MOD 10H < 10 THEN s[i] := CHR(n MOD 10H +ORD("0")) ELSE s[i] := CHR(n MOD 10H - 10 + ORD("A")) END;
  893. n := n DIV 10H MOD 10000000H; INC(i);
  894. UNTIL n = 0;
  895. j := 0;
  896. WHILE i>0 DO DEC(i); t[j] := s[i]; INC(j) END; t[j]:="H"; t[j+1] := 0X;
  897. w.String(t)
  898. END Hex;
  899. PROCEDURE SwapBytes(VAR code: LONGINT);
  900. TYPE Opcode = ARRAY 4 OF CHAR;
  901. VAR opcode: Opcode;
  902. tmp: CHAR;
  903. BEGIN
  904. opcode := SYSTEM.VAL(Opcode, code);
  905. tmp := opcode[0]; opcode[0] := opcode[3]; opcode[3] := tmp;
  906. tmp := opcode[1]; opcode[1] := opcode[2]; opcode[2] := tmp;
  907. code := SYSTEM.VAL(LONGINT, opcode);
  908. END SwapBytes;
  909. PROCEDURE ARMDecoderFactory (reader : Streams.Reader) : Decoder.Decoder;
  910. VAR
  911. armDecoder : ARMDecoder;
  912. BEGIN
  913. NEW(armDecoder, reader);
  914. RETURN armDecoder
  915. END ARMDecoderFactory;
  916. PROCEDURE CodeScaleCallback(VAR codeSize: LONGINT);
  917. BEGIN
  918. codeSize := codeSize * 4
  919. END CodeScaleCallback;
  920. PROCEDURE Init*;
  921. BEGIN
  922. Decoder.RegisterDecoder("Oba", ARMDecoderFactory, CodeScaleCallback);
  923. KernelLog.String("ARMDecoder installed."); KernelLog.Ln;
  924. END Init;
  925. BEGIN
  926. bigEndian := FALSE;
  927. END ARMDecoder.