PCOARM.Mod 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. (* Paco, Copyright 2000, Patrik Reali, ETH Zurich *)
  2. MODULE PCOARM; (** be **)
  3. (** Code Generator for ARM. Not concurrent ! *)
  4. IMPORT SYSTEM, Files, PCLIR, PCM(*Trace, PCARMDecoder *), Diagnostics;
  5. CONST
  6. (*Trace = FALSE; *)
  7. INTERNALERROR* = 100;
  8. UNIMPLEMENTED* = 101;
  9. NONORTHOGONALITYEXCEPTION* = 102;
  10. ErrBranchOffsetTooBig* = 110;
  11. ErrImmediateTooSmall* = 111;
  12. ErrImmediateTooBig* = 112;
  13. ErrRotateImmTooBig* = 113;
  14. ErrRotateImmOdd* = 114;
  15. ErrInvalidRegister* = 115;
  16. ErrInvalidRegisterSet* = 116;
  17. ErrInvalidMode* = 117;
  18. ErrCaseOffsetTooBig* = 118;
  19. MaxCodeLength* = 256*1024;
  20. InstructionSize* = 4; (* size of one instruction, in bytes *)
  21. (** Conditions - instruction is executed if CPSR satisfies the condition *)
  22. EQ* = { }; (** equal *)
  23. NE* = { 28 }; (** not equal *)
  24. CS* = { 29 }; (** carry set *)
  25. HS* = CS; (** unsigned higher or same *)
  26. CC* = { 29, 28 }; (** carry clear *)
  27. LO* = CC; (** unsigned lower *)
  28. MI* = { 30 }; (** minus/negative *)
  29. PL* = { 30, 28 }; (** plus/positive or zero *)
  30. VS* = { 30, 29 }; (** overflow *)
  31. VC* = { 30, 29, 28 }; (** no overflow *)
  32. HI* = { 31 }; (** unsigned higher *)
  33. LS* = { 31, 28 }; (** unsigned lower or same *)
  34. GE* = { 31, 29 }; (** signed greater or equal *)
  35. LT* = { 31, 29, 28 }; (** signed less than *)
  36. GT* = { 31, 30 }; (** signed greater than *)
  37. LE* = { 31, 30, 28 }; (** signed less than or equal *)
  38. AL* = { 31, 30, 29 }; (** always *)
  39. CondMask* = { 31, 30, 29, 28 };
  40. (** Registers *)
  41. R0* = 0; R1* = 1; R2* = 2; R3* = 3; R4* = 4; R5* = 5; R6* = 6; R7* = 7; R8* = 8; R9* = 9; R10* = 10; R11* = 11;
  42. FP* = 12; (** frame pointer *)
  43. SP* = 13; (** stack pointer *)
  44. LR* = 14; (** return address *)
  45. PC* = 15; (** program counter *)
  46. Registers* = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; (** valid registers *)
  47. CPSR* = {}; (** current program status register *)
  48. SPSR* = { 22 }; (** saved program status register *)
  49. CR0* = 0; CR1* = 1; CR2* = 2; CR3* = 3; CR4* = 4; CR5* = 5; CR6* = 6; CR7* = 7; CR8* = 8; CR9* = 9; CR10* = 10;
  50. CR11* = 11; CR12* = 12; CR13* = 13; CR14* = 14; CR15* = 15; (** coprocessor registers *)
  51. (** PSR flags *)
  52. PSRc* = { 16 }; (** control fields *)
  53. PSRx* = { 17 }; (** extension fields *)
  54. PSRs* = { 18 }; (** status fields *)
  55. PSRf* = { 19 }; (** flags fields *)
  56. (** useful Bit-Masks *)
  57. Mask24* = { 0..23 };
  58. MaskRd* = { 15, 14, 13, 12 };
  59. (** Common modifiers *)
  60. Sflag* = { 20 }; (** if set, the condition codes are updated *)
  61. Bflag* = { 22 }; (** distinguishes between a SWP and a SWPB instruction *)
  62. Lflag* = { 22 }; (** LDC/STC: specifies long load/store *)
  63. Lsl* = { }; (** logical shift left *)
  64. LSR* = { 5 }; (** logical shift right *)
  65. Asr* = { 6 }; (** arithmetic shift right *)
  66. Ror* = { 6, 5 }; (** rotate right *)
  67. RRX* = Ror; (** rotate right with extend *)
  68. ShiftMask = { 6, 5 };
  69. Load* = { 20 }; (** load *)
  70. Store* = { }; (** store *)
  71. IdxAdd* = { 23 }; (** load/store: the index is added to the base register *)
  72. IdxSub* = { }; (** load/store: the index is subtracted from the base register *)
  73. Offset* = { 24 }; (** load/store: offset addressing *)
  74. PreIdxd* = { 24, 21 }; (** load/store: pre-indexed addressing *)
  75. PostIdxd* = { }; (** laod/store: post-indexed addressing *)
  76. (** Addressing Mode 1 - Data-processing operands *)
  77. A1Imm* = { 25 }; (** shifterOperand contains an 8-bit immediate value plus a 4-bit rotate immediate value *)
  78. A1Reg* = { }; (** shifterOperand contains a register *)
  79. A1ShiftImm* = { }; (** shifterOperand contains a register and is shifted by an immeditae *)
  80. A1ShiftReg* = { 4 }; (** shifterOperand contains a register and is shifted by a register *)
  81. A1Immediate0* = {}; (** prepared immediate values: 0, 1, 2, 4 and 8 *)
  82. A1Immediate1* = { 0 };
  83. A1Immediate2* = { 1 };
  84. A1Immediate4* = { 2 };
  85. A1Immediate8* = { 3 };
  86. A1Immediate31* = { 4, 3, 2, 1, 0 };
  87. (** Addressing Mode 2 - Load and Store Words or Unsigned Byte *)
  88. A2Mode* = { 26 }; (** load/store word/unsigned byte *)
  89. A2Word* = { }; (** load/store word *)
  90. A2Byte* = { 22 }; (** load/store byte *)
  91. A2Imm* = { }; (** address contains an immediate value *)
  92. A2Reg* = { 25 }; (** address contains a register *)
  93. A2WImmOffset* = A2Word + A2Imm + Offset;
  94. A2WRegOffset* = A2Word + A2Reg + Offset;
  95. A2BImmOffset* = A2Byte + A2Imm + Offset;
  96. A2BRegOffset* = A2Byte + A2Reg + Offset;
  97. A2WImmPreIdxd* = A2Word + A2Imm + PreIdxd;
  98. A2WRegPreIdxd* = A2Word + A2Reg + PreIdxd;
  99. A2WImmPostIdxd* = A2Word + A2Imm + PostIdxd;
  100. A2WRegPostIdxd* = A2Word + A2Reg + PostIdxd;
  101. A2BImmPostIdxd* = A2Byte + A2Imm + PostIdxd;
  102. A2BRegPostIdxd* = A2Byte + A2Reg + PostIdxd;
  103. A2AddrModeMask = { 25, 24, 23, 22, 21 };
  104. (** Addressing Mode 3 - Miscellaneous Loads and Stores *)
  105. A3Mode* = { 7, 4 }; (** micellaneous load/store *)
  106. A3Halfword* = { 5 }; (** load/store halfword *)
  107. A3Byte* = { }; (** load/store byte *)
  108. A3Imm* = { 22 }; (** address contains an immediate value *)
  109. A3Reg* = { }; (** address contains a register *)
  110. A3Signed* = { 6 }; (** signed halfword/byte *)
  111. A3Unsigned* = { }; (** unsigned halfword/byte *)
  112. A3SHImmOffset* = A3Halfword + A3Imm + A3Signed + Offset;
  113. A3UHImmOffset* = A3Halfword + A3Imm + A3Unsigned + Offset;
  114. A3SHRegOffset* = A3Halfword + A3Reg + A3Signed + Offset;
  115. A3UHRegOffset* = A3Halfword + A3Reg + A3Unsigned + Offset;
  116. A3SBImmOffset* = A3Byte + A3Imm + A3Signed + Offset;
  117. A3UBImmOffset* = A3Byte + A3Imm + A3Unsigned + Offset;
  118. A3SBRegOffset* = A3Byte + A3Reg + A3Signed + Offset;
  119. A3UBRegOffset* = A3Byte + A3Reg + A3Unsigned + Offset;
  120. A3AddrModeMask = { 24, 23, 22, 21, 7, 6, 5, 4 };
  121. (** Addressing Mode 4 - Load and Store Multiple *)
  122. A4IA* = { 23 }; (** increment after *)
  123. A4IB* = { 24, 23 }; (** increment before *)
  124. A4DA* = { }; (** decrement after *)
  125. A4DB* = { 24 }; (** decrement before *)
  126. A4W* = { 21 }; (** update address register *)
  127. A4User* = { 22 }; (** load/store user mode registers *)
  128. A4LDMMask* = { 20 }; (** if this bit is set, it's a LDM (ifffff it's a addressing mode 4 instruction, Hobbes, idiot) *)
  129. (** Addressing Mode 5 - Load and Store Coprocessor *)
  130. A5W* = { 21 }; (** update base register *)
  131. A5Offset* = { }; (** offset addressing *)
  132. A5PreIdxd* = { 21 }; (** pre-indexed addressing *)
  133. A5PostIdxd* = { 24, 21 }; (** post-indexed addressing *)
  134. A5UnIdxd* = { 24 }; (** unindexed addressing *)
  135. (** Miscellaneous *)
  136. MSRImmediate* = { 25 }; (** the operand is a 8bit immediate *)
  137. MSRRegister* = { }; (** the operand is a register *)
  138. (** Instruction Opcodes *)
  139. (* data-processing instructions *)
  140. opADC* = { 23, 21 };
  141. opADD* = { 23 };
  142. opAND* = { };
  143. opBIC* = { 24, 23, 22 };
  144. opCMN* = { 24, 22, 21, 20 };
  145. opCMP* = { 24, 22, 20 };
  146. opEOR* = { 21 };
  147. opMOV* = { 24, 23, 21 };
  148. opMVN* = { 24, 23, 22, 21 };
  149. opORR* = { 24, 23 };
  150. opRSB* = { 22, 21 };
  151. opRSC* = { 23, 22, 21 };
  152. opSBC* = { 23, 22 };
  153. opSUB* = { 22 };
  154. opTEQ* = { 24, 21, 20 };
  155. opTST* = { 24, 20 };
  156. opMRS* = { 24, 19, 18, 17, 16 };
  157. opMSR* = { 24, 21, 15, 14, 13, 12 };
  158. (* multiply instructions *)
  159. opMLA* = { 21, 7, 4 };
  160. opMUL* = { 7, 4 };
  161. opSMLAL* = { 23, 22, 21, 7, 4 };
  162. opSMULL* = { 23, 22, 7, 4 };
  163. opUMLAL* = { 23, 21, 7, 4 };
  164. opUMULL* = { 23, 7, 4 };
  165. (* branch instructions *)
  166. opB* = { 27, 25 };
  167. LinkBit* = { 24 };
  168. opBL* = opB + LinkBit;
  169. BMask* = { 27, 25, 24 };
  170. (* load/store instructions *)
  171. opLDM* = { 27, 20 };
  172. opLDR* = { 26, 20 };
  173. opLDRH* = { 20, 7, 4 };
  174. opSTM* = { 27 };
  175. opSTR* = { 26 };
  176. opSTRH* = { 7, 5, 4 };
  177. (* semaphore instructions *)
  178. opSWP* = { 24, 7, 4 };
  179. (* exception-generating instructions *)
  180. opSWI* = {27, 26, 25, 24 }; (* software interrupt *)
  181. opBKPT* = { 31, 30, 29, 24, 21, 6, 5, 4 };
  182. (* coprocessor instructions *)
  183. opCDP* = { 27, 26, 25 };
  184. opLDC* = { 27, 26, 20 };
  185. opMCR* = { 27, 26, 25, 4 };
  186. opMRC* = { 27, 26, 25, 20, 4 };
  187. opSTC* = { 27, 26 };
  188. TYPE
  189. DCDList = POINTER TO RECORD
  190. pc: LONGINT;
  191. next: DCDList;
  192. END;
  193. Callback* = PROCEDURE {DELEGATE} (pc: LONGINT);
  194. VAR
  195. (*Trace W: Texts.Writer;
  196. t: Texts.Text; *)
  197. AddrMode: ARRAY 5 OF SET; (* contains bitmasks for validity checks *)
  198. f: Files.File;
  199. r: Files.Rider;
  200. start: LONGINT;
  201. code: PCLIR.CodeArray;
  202. codelen: LONGINT;
  203. codeTooLong: BOOLEAN;
  204. sourcepos*: LONGINT;
  205. dcd: BOOLEAN;
  206. codeBarrier: LONGINT;
  207. codeBarrierCallback: Callback;
  208. callbackLocked: BOOLEAN;
  209. PROCEDURE GetCodePos*(): LONGINT;
  210. BEGIN RETURN codelen
  211. END GetCodePos;
  212. PROCEDURE GetInstruction*(pos: LONGINT): SET;
  213. VAR factor, i, l: LONGINT;
  214. BEGIN ASSERT(pos < codelen);
  215. factor := 1;
  216. FOR i := 0 TO 3 DO
  217. l := l + ORD(code[pos+i])*factor;
  218. factor := factor*100H
  219. END;
  220. IF PCM.bigEndian THEN PCM.SwapBytes(l, 0, 4) END;
  221. RETURN SYSTEM.VAL(SET, l)
  222. END GetInstruction;
  223. PROCEDURE GetCode*(VAR codeArr: PCLIR.CodeArray; VAR length, hdrLength, addressFactor: LONGINT);
  224. BEGIN
  225. codeArr := code; length := codelen; hdrLength := codelen DIV 4; addressFactor := 4
  226. END GetCode;
  227. PROCEDURE Lsh(v, s: LONGINT): SET;
  228. BEGIN RETURN SYSTEM.VAL(SET, LSH(v,s))
  229. END Lsh;
  230. (*
  231. PROCEDURE CheckCondition(c: SET);
  232. BEGIN ASSERT(c - {31, 30, 29, 28} = {})
  233. END CheckCondition;
  234. PROCEDURE CheckAddressingMode(mode: LONGINT; am: SET);
  235. BEGIN ASSERT(am - AddrMode[mode-1] = {})
  236. END CheckAddressingMode;
  237. *)
  238. PROCEDURE CheckReg(register: LONGINT);
  239. BEGIN ASSERT((0 <= register) & (register < 16), ErrInvalidRegister)
  240. END CheckReg;
  241. (*
  242. PROCEDURE CheckRegisterSet(registers: SET);
  243. BEGIN ASSERT (registers - Registers = {}, ErrInvalidRegisterSet)
  244. END CheckRegisterSet;
  245. *)
  246. PROCEDURE CheckImm(imm, max: LONGINT);
  247. BEGIN ASSERT((0 <= imm) & (imm < max), ErrImmediateTooBig)
  248. END CheckImm;
  249. (*
  250. PROCEDURE CheckSignedImm(imm, min, max: LONGINT);
  251. BEGIN ASSERT((min < imm), ErrImmediateTooSmall);
  252. ASSERT((imm < max), ErrImmediateTooBig)
  253. END CheckSignedImm;
  254. *)
  255. PROCEDURE CheckSet(set, mask: SET);
  256. BEGIN ASSERT(set * (-mask) = {}, ErrInvalidMode)
  257. END CheckSet;
  258. (** Addressing Mode 3 Helpers *)
  259. PROCEDURE MakeA3Immediate*(VAR addrMode: SET; offset: LONGINT): SET;
  260. VAR neg: BOOLEAN; address: SET;
  261. BEGIN
  262. neg := offset < 0; offset := ABS(offset);
  263. ASSERT(offset < 100H);
  264. (* address[11:8] = offset[7:4], address[3:0] = offset[3:0] *)
  265. address := SYSTEM.VAL(SET, 100H*(offset DIV 10H) + (offset MOD 10H));
  266. addrMode := addrMode - (A3Imm + IdxAdd + IdxSub);
  267. addrMode := addrMode + A3Imm;
  268. IF ~neg THEN addrMode := addrMode + IdxAdd
  269. ELSE addrMode := addrMode + IdxSub
  270. END;
  271. RETURN address
  272. END MakeA3Immediate;
  273. PROCEDURE MakeA3Register*(register: LONGINT): SET;
  274. BEGIN RETURN SYSTEM.VAL(SET, register)
  275. END MakeA3Register;
  276. (**----- Data Processing Instructions (Addressing Mode 1) -------*)
  277. PROCEDURE MakeA1Immediate*(immediate: LONGINT; VAR imm: SET): BOOLEAN;
  278. VAR rot: LONGINT;
  279. BEGIN
  280. rot := 0; imm := SYSTEM.VAL(SET, immediate);
  281. WHILE (rot < 32) & (ODD(rot) OR (imm * { 8..31} # {})) DO
  282. imm := ROT(imm, 1); INC(rot)
  283. END;
  284. IF (rot < 32) THEN
  285. imm := imm + SYSTEM.VAL(SET, Lsh(rot DIV 2, 8));
  286. RETURN TRUE
  287. ELSE
  288. imm := {};
  289. RETURN FALSE
  290. END
  291. END MakeA1Immediate;
  292. PROCEDURE MakeA1Register*(reg: LONGINT): SET;
  293. BEGIN CheckReg(reg);
  294. RETURN SYSTEM.VAL(SET, reg)
  295. END MakeA1Register;
  296. PROCEDURE MakeA1RegSHIFTReg*(reg, shiftreg: LONGINT; mode: SET): SET;
  297. BEGIN CheckReg(reg); CheckReg(shiftreg); CheckSet(mode, ShiftMask);
  298. RETURN Lsh(shiftreg, 8) + mode + A1ShiftReg + SYSTEM.VAL(SET, reg)
  299. END MakeA1RegSHIFTReg;
  300. PROCEDURE MakeA1RegSHIFTImm*(reg, imm: LONGINT; mode: SET): SET;
  301. BEGIN CheckReg(reg); CheckImm(imm, 20H); CheckSet(mode, ShiftMask);
  302. RETURN Lsh(imm, 7) + mode + A1ShiftImm + SYSTEM.VAL(SET, reg)
  303. END MakeA1RegSHIFTImm;
  304. (** ADC - add with carry (rD <- rN + shifterOperand + carry) *)
  305. PROCEDURE ADC*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  306. BEGIN Code(cond + opADC + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  307. END ADC;
  308. (** ADD - add (rD <- rN + shifterOperand) *)
  309. PROCEDURE ADD*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  310. BEGIN Code(cond + opADD + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  311. END ADD;
  312. (** AND - bitwise and (rD <- rN AND shifterOperand) *)
  313. PROCEDURE AND*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  314. BEGIN CheckSet(shifterOperand, {0..11});
  315. Code(cond + opAND + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  316. END AND;
  317. (** BIC - clears bits (rD <- rN AND NOT shifterOperand) *)
  318. PROCEDURE BIC*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  319. BEGIN Code(cond + opBIC + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  320. END BIC;
  321. (** CMN - compare negative (CC updated based on rN + shifterOperand) *)
  322. PROCEDURE CMN*(cond, addrMode: SET; rN: LONGINT; shifterOperand: SET);
  323. BEGIN Code(cond + opCMN + addrMode + Lsh(rN, 16) + shifterOperand)
  324. END CMN;
  325. (** CMP - compare (CC updateed based on rN - shifterOperand) *)
  326. PROCEDURE CMP*(cond, addrMode: SET; rN: LONGINT; shifterOperand: SET);
  327. BEGIN Code(cond + opCMP + addrMode + Lsh(rN, 16) + shifterOperand)
  328. END CMP;
  329. (** EOR - XOr (rD <- rN XOR shifterOperand) *)
  330. PROCEDURE EOR*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  331. BEGIN Code(cond + opEOR + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  332. END EOR;
  333. (** MOV - move (rD <- shifterOperand) *)
  334. PROCEDURE MOV*(cond, addrMode: SET; rD: LONGINT; shifterOperand, S: SET);
  335. BEGIN Code(cond + opMOV + addrMode + Lsh(rD, 12) + shifterOperand + S)
  336. END MOV;
  337. (** MVN - move negative (rD <- NOT shifterOperand) *)
  338. PROCEDURE MVN*(cond, addrMode: SET; rD: LONGINT; shifterOperand, S: SET);
  339. BEGIN Code(cond + opMVN + addrMode + Lsh(rD, 12) + shifterOperand + S)
  340. END MVN;
  341. (** ORR - bitwise OR (rD <- rN OR shifterOperand) *)
  342. PROCEDURE ORR*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  343. BEGIN Code(cond + opORR + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  344. END ORR;
  345. (** RSB - reverse subtract (rD <- shifterOperand - rN) *)
  346. PROCEDURE RSB*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  347. BEGIN Code(cond + opRSB + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  348. END RSB;
  349. (** RSC - reverse subtract with carry (rD <- shifterOperand - rN - NOT(carry)) *)
  350. PROCEDURE RSC*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  351. BEGIN Code(cond + opRSC + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  352. END RSC;
  353. (** SBC - subtract with carry (rD <- rN - shifterOperand - NOT(carry))*)
  354. PROCEDURE SBC*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  355. BEGIN Code(cond + opSBC + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  356. END SBC;
  357. (** SUB - subtract (rD <- rN - shifterOperand) *)
  358. PROCEDURE SUB*(cond, addrMode: SET; rD, rN: LONGINT; shifterOperand, S: SET);
  359. BEGIN Code(cond + opSUB + addrMode + Lsh(rN, 16) + Lsh(rD, 12) + shifterOperand + S)
  360. END SUB;
  361. (** TEQ - test equivalence (CC updated based on rN XOR shifterOperand) *)
  362. PROCEDURE TEQ*(cond, addrMode: SET; rN: LONGINT; shifterOperand: SET);
  363. BEGIN Code(cond + opTEQ + addrMode + Lsh(rN, 16) + shifterOperand)
  364. END TEQ;
  365. (** TST - test (CC updated based on rN AND shifterOperand) *)
  366. PROCEDURE TST*(cond, addrMode: SET; rN: LONGINT; shifterOperand: SET);
  367. BEGIN Code(cond + opTST + addrMode + Lsh(rN, 16) + shifterOperand)
  368. END TST;
  369. (**----------------------- Multiply Instructions -----------------------*)
  370. (** MLA - multiply accumulate (rD <- (rM * rS) + rN) *)
  371. PROCEDURE MLA*(cond: SET; rD, rM, rS, rN: LONGINT; S: SET);
  372. BEGIN ASSERT(rD # rM, NONORTHOGONALITYEXCEPTION);
  373. Code(cond + opMLA + Lsh(rD, 16) + Lsh(rN, 12) + Lsh(rS, 8) + Lsh(rM, 0) + S)
  374. END MLA;
  375. (** MUL - multiply (rD <- rM * rS) *)
  376. PROCEDURE MUL*(cond: SET; rD, rM, rS: LONGINT; S: SET);
  377. BEGIN ASSERT(rD # rM, NONORTHOGONALITYEXCEPTION);
  378. Code(cond + opMUL + Lsh(rD, 16) + Lsh(rS, 8) + Lsh(rM, 0) + S)
  379. END MUL;
  380. (** SMLAL - signed multiply accumulate long (rDLo <- (rA * rB)[31:0] + rDLo, rDHi <- (rA * rB)[63:32] + rDHi + carry) *)
  381. PROCEDURE SMLAL*(cond: SET; rDHi, rDLo, rM, rS: LONGINT; S: SET);
  382. BEGIN ASSERT((rDHi # rDLo) & (rDHi # rM) & (rDLo # rM), NONORTHOGONALITYEXCEPTION);
  383. Code(cond + opSMLAL + Lsh(rDHi, 16) + Lsh(rDLo, 12) + Lsh(rS, 8) + Lsh(rM, 0) + S)
  384. END SMLAL;
  385. (** SMULL - signed multiply long (rDLo <- (rM * rS)[31:0], rDHi <- (rM * rS)[63:32]) *)
  386. PROCEDURE SMULL*(cond: SET; rDHi, rDLo, rM, rS: LONGINT; S: SET);
  387. BEGIN ASSERT((rDHi # rDLo) & (rDHi # rM) & (rDLo # rM), NONORTHOGONALITYEXCEPTION);
  388. Code(cond + opSMULL + Lsh(rDHi, 16) + Lsh(rDLo, 12) + Lsh(rS, 8) + Lsh(rM, 0) + S)
  389. END SMULL;
  390. (** UMLAL - unsigned multiply accumulate long (rDLo <- (rM*rS)[31:0] + rDLo, rDHi <- (rM*rS)[63:32] + rDHi + carry) *)
  391. PROCEDURE UMLAL*(cond: SET; rDLo, rDHi, rM, rS: LONGINT; S: SET);
  392. BEGIN ASSERT((rDHi # rDLo) & (rDHi # rM) & (rDLo # rM), NONORTHOGONALITYEXCEPTION);
  393. Code(cond + opUMLAL + Lsh(rDHi, 16) + Lsh(rDLo, 12) + Lsh(rS, 8) + Lsh(rM, 0) + S)
  394. END UMLAL;
  395. (** UMULL - unsigned multply long (rDLo <- (rM*rS)[31:0], rDHi <- (rM*rS)[63:32]) *)
  396. PROCEDURE UMULL*(cond: SET; rDLo, rDHi, rM, rS: LONGINT; S: SET);
  397. BEGIN ASSERT((rDHi # rDLo) & (rDHi # rM) & (rDLo # rM), NONORTHOGONALITYEXCEPTION);
  398. Code(cond + opUMULL + Lsh(rDHi, 16) + Lsh(rDLo, 12) + Lsh(rS, 8) + Lsh(rM, 0) + S)
  399. END UMULL;
  400. (**------------------------- Branch Instructions -------------------------*)
  401. (** B - branch to address. (PC <- PC + extS(address << 2)). Hint: PC is 2 instructions ahead *)
  402. PROCEDURE B*(cond: SET; address: LONGINT);
  403. BEGIN ASSERT((ABS(address) < 1000000H), ErrBranchOffsetTooBig);
  404. ASSERT(cond # {31, 30, 29, 28});
  405. Code(cond + opB + Mask24*SYSTEM.VAL(SET, address))
  406. END B;
  407. (** BL - branch to address. (LR <- address of instr. after branch instruction, PC <- PC + extS(address << 2))
  408. Hint: - PC is 2 instructions ahead *)
  409. PROCEDURE BL*(cond: SET; address: LONGINT);
  410. BEGIN Code(cond + opBL + Mask24*SYSTEM.VAL(SET, address))
  411. END BL;
  412. (**------------ Load/Store Instructions (Addressing Modes 2, 3 & 4) --------------*)
  413. PROCEDURE MakeA2Immediate*(VAR addrMode: SET; offset: LONGINT): SET;
  414. VAR neg: BOOLEAN; address: SET;
  415. BEGIN
  416. neg := offset < 0; offset := ABS(offset);
  417. ASSERT(offset < 1000H);
  418. address := SYSTEM.VAL(SET, offset);
  419. addrMode := addrMode - (A2Imm + IdxAdd + IdxSub);
  420. addrMode := addrMode + A2Imm;
  421. IF ~neg THEN addrMode := addrMode + IdxAdd
  422. ELSE addrMode := addrMode + IdxSub
  423. END;
  424. RETURN address
  425. END MakeA2Immediate;
  426. PROCEDURE MakeA2Register*(register: LONGINT): SET;
  427. BEGIN RETURN SYSTEM.VAL(SET, register)
  428. END MakeA2Register;
  429. PROCEDURE MakeA2ScaledRegister*(reg: LONGINT; mode: SET; shift: LONGINT): SET;
  430. BEGIN CheckReg(reg); CheckImm(shift, 20H); CheckSet(mode, ShiftMask);
  431. RETURN Lsh(shift, 7) + mode + Lsh(reg, 0)
  432. END MakeA2ScaledRegister;
  433. (** LDM - uses Addressing Mode 4 *)
  434. PROCEDURE LDM*(cond, addrMode: SET; rD: LONGINT; registers, W: SET);
  435. BEGIN Code(cond + opLDM + addrMode + Lsh(rD, 16) + registers + W)
  436. END LDM;
  437. (** LDR - uses Addressing Mode 2 *)
  438. PROCEDURE LDR*(cond, addrMode: SET; rD, rAdr: LONGINT; address: SET);
  439. BEGIN Code(cond + opLDR + addrMode + Lsh(rAdr, 16) + Lsh(rD, 12) + address)
  440. END LDR;
  441. (** LDRH - uses Addressing Mode 3 *)
  442. PROCEDURE LDRH*(cond, addrMode: SET; rD, rAdr: LONGINT; address: SET);
  443. BEGIN Code(cond + opLDRH + addrMode + Lsh(rAdr, 16) + Lsh(rD, 12) + address)
  444. END LDRH;
  445. (** STM - uses Addressing Mode 4 *)
  446. PROCEDURE STM*(cond, addrMode: SET; rD: LONGINT; registers, W: SET);
  447. BEGIN Code(cond + opSTM + addrMode + Lsh(rD, 16) + registers + W)
  448. END STM;
  449. (** STR - uses Addressing Mode 2 *)
  450. PROCEDURE STR*(cond, addrMode: SET; rAdr, rS: LONGINT; address: SET);
  451. BEGIN Code(cond + opSTR + addrMode + Lsh(rAdr, 16) + Lsh(rS, 12) + address)
  452. END STR;
  453. (** STRH - uses Addressing Mode 3 *)
  454. PROCEDURE STRH*(cond, addrMode: SET; rAdr, rS: LONGINT; address: SET);
  455. BEGIN ASSERT(address*{6,5}={}, NONORTHOGONALITYEXCEPTION);
  456. Code(cond + opSTRH + addrMode + Lsh(rAdr, 16) + Lsh(rS, 12) + address)
  457. END STRH;
  458. (**--------------------------- Miscellaneous -----------------------------*)
  459. (** SWI - software interrupt *)
  460. PROCEDURE SWI*(cond: SET; code: LONGINT);
  461. BEGIN CheckImm(code, 1000000H);
  462. Code(cond + opSWI + Mask24*Lsh(code, 0))
  463. END SWI;
  464. (** DCD - puts a 32bit value into the code *)
  465. PROCEDURE DCD*(value: LONGINT);
  466. BEGIN dcd := TRUE; Code(SYSTEM.VAL(SET, value))
  467. END DCD;
  468. (**--------------------------- Fixup Handling -------------------------------*)
  469. (* Lock - does not allow automatic flushing of the constant pool. Not reentrant. *)
  470. PROCEDURE Lock*;
  471. BEGIN callbackLocked := TRUE
  472. END Lock;
  473. (* Unlock - allows automatic flushing of the constant pool. Not reentrant *)
  474. PROCEDURE Unlock*;
  475. BEGIN callbackLocked := FALSE; CheckCallback
  476. END Unlock;
  477. (* SetConstantPoolBarrier - *)
  478. PROCEDURE SetConstantPoolBarrier*(pc: LONGINT);
  479. BEGIN
  480. ASSERT((codelen < pc) & (pc < codelen + 1000H) OR (pc = -1), INTERNALERROR);
  481. codeBarrier := pc
  482. END SetConstantPoolBarrier;
  483. (* SetConstantPoolBarrierCallback - *)
  484. PROCEDURE SetConstantPoolBarrierCallback*(callback: Callback);
  485. BEGIN
  486. codeBarrierCallback := callback
  487. END SetConstantPoolBarrierCallback;
  488. (* CheckCallback - calls the callback handler if necessary *)
  489. PROCEDURE CheckCallback;
  490. BEGIN
  491. IF ~callbackLocked & (codeBarrier # -1) & (codeBarrierCallback # NIL) & (codelen >= codeBarrier) THEN
  492. Lock; (* lock or we'll get a stack overflow due to endless recursion *)
  493. codeBarrierCallback(codelen);
  494. Unlock
  495. END
  496. END CheckCallback;
  497. PROCEDURE ExtractRegister(code: SET; pos: LONGINT): LONGINT;
  498. BEGIN RETURN LSH(SYSTEM.VAL(LONGINT, code), -pos) MOD 10H
  499. END ExtractRegister;
  500. PROCEDURE FixLoad*(pc: LONGINT; address: LONGINT);
  501. VAR b, addrMode, addr: SET; currPos: LONGINT;
  502. BEGIN
  503. b := GetInstruction(pc);
  504. currPos := codelen;
  505. codelen := pc;
  506. IF (b * opLDR = opLDR) THEN
  507. addrMode := b * A2AddrModeMask;
  508. addr := MakeA2Immediate(addrMode, address);
  509. LDR(b*CondMask, addrMode, ExtractRegister(b, 12), ExtractRegister(b, 16), addr)
  510. ELSIF (b * opLDRH = opLDRH) THEN
  511. addrMode := b * A3AddrModeMask;
  512. addr := MakeA3Immediate(addrMode, address);
  513. LDRH(b*CondMask, addrMode, ExtractRegister(b, 12), ExtractRegister(b, 16), addr)
  514. ELSE HALT(INTERNALERROR)
  515. END;
  516. codelen := currPos;
  517. END FixLoad;
  518. PROCEDURE FixJump*(pc: LONGINT; address: LONGINT);
  519. VAR b: SET; currPos: LONGINT;
  520. BEGIN
  521. b := GetInstruction(pc);
  522. ASSERT(b * opB = opB);
  523. currPos := codelen;
  524. codelen := pc;
  525. B(b*CondMask, address);
  526. codelen := currPos
  527. END FixJump;
  528. PROCEDURE FixCall*(pc: LONGINT; address: LONGINT): LONGINT;
  529. VAR b: SET; currPos: LONGINT;
  530. BEGIN
  531. b := GetInstruction(pc);
  532. ASSERT(b * opBL = opBL);
  533. currPos := codelen;
  534. codelen := pc;
  535. BL(b*CondMask, address);
  536. codelen := currPos;
  537. RETURN SYSTEM.VAL(LONGINT, b*Mask24)
  538. END FixCall;
  539. PROCEDURE FixCaseTable*(pc: LONGINT; address: LONGINT);
  540. VAR fixup, currPos: LONGINT;
  541. BEGIN
  542. ASSERT((address >= 0) & (address < 10000H), ErrCaseOffsetTooBig);
  543. fixup := SYSTEM.VAL(LONGINT, GetInstruction(pc) * { 16..31 });
  544. currPos := codelen;
  545. codelen := pc;
  546. DCD(fixup + address);
  547. codelen := currPos
  548. END FixCaseTable;
  549. (**--------------------------- Miscellaneous -------------------------------*)
  550. PROCEDURE Init*(codeFN: ARRAY OF CHAR);
  551. BEGIN
  552. f := Files.New(codeFN);
  553. Files.Register(f);
  554. f.Set(r, 0);
  555. start := 0;
  556. IF (code = NIL) THEN NEW(code, MaxCodeLength) END;
  557. codelen := 0; codeTooLong := FALSE;
  558. (*Trace IF Trace THEN NEW(t); Texts.Open(t, ""); PCARMDecoder.Init END *)
  559. END Init;
  560. PROCEDURE Code(opcode: SET);
  561. TYPE Bytes= ARRAY 4 OF CHAR;
  562. VAR b: Bytes; i: INTEGER;
  563. BEGIN
  564. ASSERT(codelen MOD 4 = 0); (* in case PutChar did not write 4x characters *)
  565. (*Trace IF Trace & dcd THEN
  566. dcd := FALSE;
  567. NEW(d); d.pc := codelen;
  568. IF (dcdLast = NIL) THEN dcdList := d; dcdLast := d
  569. ELSE dcdLast.next := d; dcdLast := d
  570. END
  571. END; *)
  572. IF (codelen <= MaxCodeLength-4) THEN
  573. b := SYSTEM.VAL(Bytes, opcode);
  574. IF PCM.bigEndian THEN PCM.SwapBytes(b, 0, 4) END;
  575. FOR i := 0 TO 3 DO
  576. code[codelen] := b[i]; INC(codelen) (* little endian *)
  577. END;
  578. CheckCallback
  579. ELSE
  580. IF ~codeTooLong THEN (* report only once *)
  581. codeTooLong := TRUE;
  582. PCM.Error(244, sourcepos, "Code too long.")
  583. END
  584. END
  585. END Code;
  586. PROCEDURE PutChar*(c: CHAR);
  587. BEGIN
  588. code[codelen] := c; INC(codelen)
  589. END PutChar;
  590. PROCEDURE Close*;
  591. VAR b: POINTER TO ARRAY OF CHAR;
  592. BEGIN
  593. IF (codelen > MaxCodeLength) THEN (* code too long *)
  594. PCM.Error(244, Diagnostics.Invalid, "Code too long.");
  595. ELSIF (codelen-start > 0) THEN
  596. NEW(b, codelen-start);
  597. SYSTEM.MOVE(ADDRESSOF(code[start]), ADDRESSOF(b[0]), codelen-start);
  598. f.WriteBytes(r, b^, 0, codelen-start);
  599. Files.Register(f);
  600. ELSIF (codelen - start < 0) THEN HALT(MAX(INTEGER)) (* show stack*)
  601. END;
  602. f := NIL;
  603. END Close;
  604. PROCEDURE BoP*(name: ARRAY OF CHAR);
  605. (* VAR dcd: DCDList; i: LONGINT; b: ARRAY InstructionSize OF CHAR;
  606. BEGIN
  607. Trace IF Trace THEN
  608. IF (start # codelen) THEN
  609. dcd := dcdList;
  610. WHILE (start < codelen) DO
  611. FOR i := 0 TO InstructionSize-1 DO b[i] := code[start+i] END;
  612. PCARMDecoder.Decode(start, SYSTEM.VAL(LONGINT, b), (dcd # NIL) & (dcd.pc = start));
  613. IF (dcd # NIL) & (dcd.pc = start) THEN dcd := dcd.next END;
  614. INC(start, InstructionSize)
  615. END;
  616. ASSERT(start = codelen);
  617. dcdList := NIL; dcdLast := NIL
  618. END;
  619. IF (name = "") THEN COPY("Module Body", name) END;
  620. Texts.WriteLn(PCARMDecoder.W);
  621. Texts.WriteString(PCARMDecoder.W, name); Texts.WriteLn(PCARMDecoder.W);
  622. Texts.Append(t, PCARMDecoder.W.buf)
  623. END; *)
  624. END BoP;
  625. PROCEDURE EoP*;
  626. END EoP;
  627. PROCEDURE Dump*;
  628. (* VAR dcd: DCDList; i: LONGINT; b: ARRAY InstructionSize OF CHAR;
  629. BEGIN
  630. Trace IF Trace THEN
  631. IF (start # codelen) THEN
  632. dcd := dcdList;
  633. WHILE (start < codelen) DO
  634. FOR i := 0 TO InstructionSize-1 DO b[i] := code[start+i] END;
  635. PCARMDecoder.Decode(start, SYSTEM.VAL(LONGINT, b), (dcd # NIL) & (dcd.pc = start));
  636. IF (dcd # NIL) & (dcd.pc = start) THEN dcd := dcd.next END;
  637. INC(start, InstructionSize)
  638. END;
  639. ASSERT(start = codelen);
  640. dcdList := NIL; dcdLast := NIL;
  641. Texts.WriteLn(PCARMDecoder.W);
  642. Texts.WriteString(PCARMDecoder.W, "TRAP"); Texts.WriteLn(PCARMDecoder.W);
  643. Texts.Append(t, PCARMDecoder.W.buf)
  644. END;
  645. Oberon.OpenText("ARM Code", t, 600, 400)
  646. END *)
  647. END Dump;
  648. BEGIN
  649. AddrMode[0] := { 0 .. 31 };
  650. AddrMode[1] := { 0 .. 31 };
  651. AddrMode[2] := { 0 .. 31 };
  652. AddrMode[3] := { 24, 23 };
  653. AddrMode[4] := { 0 .. 31 };
  654. SetConstantPoolBarrier(-1)
  655. END PCOARM.