raavr.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. {
  2. Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
  3. Handles the common arm assembler reader routines
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit raavr;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cpubase,
  22. aasmtai,aasmdata,
  23. rautils,
  24. globtype;
  25. type
  26. TAVROperand=class(TOperand)
  27. end;
  28. TAVRInstruction=class(TInstruction)
  29. function ConcatInstruction(p:TAsmList) : tai;override;
  30. end;
  31. TRegType = (rt_all, rt_even, rt_16_31, rt_even_24_30, rt_16_23, rt_XYZ, rt_YZ, rt_X, rt_Y, rt_Z);
  32. TAVROpConstraint = record
  33. case typ : toptype of
  34. top_none : ();
  35. top_reg : (rt: TRegType; am: set of taddressmode; minconst, maxconst: tcgint);
  36. top_ref,
  37. top_const : (max, min: tcgint);
  38. end;
  39. // Constraints of operands per opcode
  40. // Encode variable number of operands by bit position, e.g.
  41. // 2 operands = 1 shl 2 = 4
  42. // 1 or 2 operands = 1 shl 1 + 1 shl 2 = 6
  43. TAVRInstrConstraint = record
  44. numOperands: byte;
  45. Operands: array[0..max_operands-1] of TAVROpConstraint;
  46. end;
  47. {$PUSH}
  48. {$WARN 3177 off : Some fields coming after "$1" were not initialized}
  49. const
  50. AVRInstrConstraint: array[TAsmOp] of TAVRInstrConstraint =
  51. // A_NONE
  52. ((numOperands: 0; Operands: ((typ: top_none), (typ: top_none))),
  53. // A_ADD
  54. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  55. // A_ADC
  56. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  57. // A_ADIW
  58. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even_24_30), (typ: top_const; max: 63; min: 0))),
  59. // A_SUB
  60. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  61. // A_SUBI
  62. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  63. // A_SBC
  64. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  65. // A_SBCI
  66. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  67. // A_SBRC
  68. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
  69. // A_SBRS
  70. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
  71. // A_SBIW
  72. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even_24_30), (typ: top_const; max: 63; min: 0))),
  73. // A_AND
  74. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  75. // A_ANDI
  76. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  77. // A_OR
  78. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  79. // A_ORI
  80. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  81. // A_EOR
  82. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  83. // A_COM
  84. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  85. // A_NEG
  86. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  87. // A_SBR
  88. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  89. // A_CBR
  90. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  91. // A_INC
  92. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  93. // A_DEC
  94. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  95. // A_TST
  96. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  97. // A_MUL
  98. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  99. // A_MULS
  100. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_reg; rt: rt_16_31))),
  101. // A_MULSU
  102. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
  103. // A_FMUL
  104. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
  105. // A_FMULS
  106. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
  107. // A_FMULSU
  108. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_23), (typ: top_reg; rt: rt_16_23))),
  109. // A_RJMP
  110. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 2047; min: -2048), (typ: top_reg; rt: rt_all))),
  111. // A_IJMP
  112. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  113. // A_EIJMP
  114. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  115. // A_JMP, max size depends on size op PC
  116. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: (1 shl 22 - 1); min: 0), (typ: top_none))),
  117. // A_RCALL
  118. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 2047; min: -2048), (typ: top_none))),
  119. // A_ICALL
  120. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  121. // A_EICALL
  122. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  123. // A_CALL, max size depends on size op PC
  124. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: (1 shl 22 - 1); min: 0), (typ: top_none))),
  125. // A_RET
  126. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  127. // A_IRET
  128. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  129. // A_CPSE
  130. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  131. // A_CP
  132. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  133. // A_CPC
  134. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  135. // A_CPI
  136. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  137. // A_SBIC
  138. (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 31; min: 0), (typ: top_const; max: 7; min: 0))),
  139. // A_SBIS
  140. (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 31; min: 0), (typ: top_const; max: 7; min: 0))),
  141. // A_BRxx
  142. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 63; min: -64), (typ: top_none))),
  143. // A_MOV
  144. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_all))),
  145. // A_MOVW
  146. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_even), (typ: top_reg; rt: rt_even))),
  147. // A_LDI
  148. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_const; max: 255; min: -128))),
  149. // A_LDS TODO: There are 2 versions with different machine codes and constant ranges. Could possibly distinguish based on size of PC?
  150. // Perhaps handle separately with a check on sub-architecture? Range check only important if smaller instruction code selected on larger arch
  151. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 65535; min: 0))),
  152. // A_LD
  153. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_XYZ; am: [AM_UNCHANGED, AM_POSTINCREMENT, AM_PREDECREMENT]))),
  154. // A_LDD
  155. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_YZ; am: [AM_UNCHANGED]; minconst: 0; maxconst: 63))),
  156. // A_STS TODO: See LDS above
  157. (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 65535; min: 0), (typ: top_reg; rt: rt_all))),
  158. // A_ST
  159. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_XYZ; am: [AM_UNCHANGED, AM_POSTINCREMENT, AM_PREDECREMENT]), (typ: top_reg; rt: rt_all))),
  160. // A_STD
  161. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_YZ; am: [AM_UNCHANGED]; minconst: 0; maxconst: 63), (typ: top_reg; rt: rt_all))),
  162. // A_LPM
  163. (numOperands: (1 shl 0 + 1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]))),
  164. // A_ELPM
  165. (numOperands: (1 shl 0 + 1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]))),
  166. // A_SPM
  167. (numOperands: (1 shl 0 + 1 shl 1); Operands: ((typ: top_reg; rt: rt_Z; am: [AM_UNCHANGED, AM_POSTINCREMENT]), (typ: top_none))),
  168. // A_IN
  169. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 63; min: 0))),
  170. // A_OUT
  171. (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 63; min: 0), (typ: top_reg; rt: rt_all))),
  172. // A_PUSH
  173. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  174. // A_POP
  175. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  176. // A_LSL
  177. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  178. // A_LSR
  179. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  180. // A_ROL
  181. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  182. // A_ROR
  183. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  184. // A_ASR
  185. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  186. // A_SWAP
  187. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  188. // A_BSET
  189. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 7; min: 0), (typ: top_none))),
  190. // A_BCLR
  191. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 7; min: 0), (typ: top_none))),
  192. // A_SBI
  193. (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 32; min: 0), (typ: top_const; max: 7; min: 0))),
  194. // A_CBI
  195. (numOperands: (1 shl 2); Operands: ((typ: top_const; max: 32; min: 0), (typ: top_const; max: 7; min: 0))),
  196. // A_SEC
  197. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  198. // A_SEH
  199. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  200. // A_SEI
  201. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  202. // A_SEN
  203. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  204. // A_SER
  205. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_16_31), (typ: top_none))),
  206. // A_SES
  207. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  208. // A_SET
  209. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  210. // A_SEV
  211. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  212. // A_SEZ
  213. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  214. // A_CLC
  215. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  216. // A_CLH
  217. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  218. // A_CLI
  219. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  220. // A_CLN
  221. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  222. // A_CLR
  223. (numOperands: (1 shl 1); Operands: ((typ: top_reg; rt: rt_all), (typ: top_none))),
  224. // A_CLS
  225. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  226. // A_CLT
  227. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  228. // A_CLV
  229. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  230. // A_CLZ
  231. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  232. // A_BST
  233. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
  234. // A_BLD
  235. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_all), (typ: top_const; max: 7; min: 0))),
  236. // A_BREAK
  237. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  238. // A_NOP
  239. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  240. // A_SLEEP
  241. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  242. // A_WDR
  243. (numOperands: (1 shl 0); Operands: ((typ: top_none), (typ: top_none))),
  244. // A_XCH
  245. (numOperands: (1 shl 2); Operands: ((typ: top_reg; rt: rt_Z), (typ: top_reg; rt: rt_all))),
  246. // A_DES
  247. (numOperands: (1 shl 1); Operands: ((typ: top_const; max: 15; min: 0), (typ: top_none)))
  248. );
  249. {$POP}
  250. implementation
  251. uses
  252. aasmcpu, verbose, cgbase, itcpugas;
  253. function TAVRInstruction.ConcatInstruction(p:TAsmList) : tai;
  254. var
  255. i: integer;
  256. err, opregasref: boolean;
  257. s1, s2: string;
  258. reg: tregister;
  259. begin
  260. result:=inherited ConcatInstruction(p);
  261. if Result.typ = ait_instruction then
  262. begin
  263. // check if number of operands fall inside the allowed set
  264. if ((1 shl taicpu(Result).ops) and AVRInstrConstraint[opcode].numOperands = 0) then
  265. Message(asmr_e_invalid_opcode_and_operand)
  266. else
  267. begin
  268. for i := 0 to taicpu(Result).ops-1 do
  269. begin
  270. err := true;
  271. opregasref := false;
  272. // Type check
  273. if (taicpu(Result).oper[i]^.typ = AVRInstrConstraint[opcode].Operands[i].typ) then
  274. err := false
  275. // if label was specified check if const is expected
  276. else if (AVRInstrConstraint[opcode].Operands[i].typ = top_const) and (taicpu(Result).oper[i]^.typ = top_ref) then
  277. err := false
  278. // Also expressions such as X+, -Z and X+8 are classified as TOP_REF
  279. else if (AVRInstrConstraint[opcode].Operands[i].typ = top_reg) and (taicpu(Result).oper[i]^.typ = top_ref) and
  280. (int64(taicpu(Result).oper[i]^.ref^.base) and $01030000 > 0) then
  281. begin
  282. err := false;
  283. opregasref := true;
  284. reg := taicpu(Result).oper[i]^.ref^.base;
  285. end
  286. // LDD r1, a or STD a, r1 where a is local variable => type is set to top_local
  287. // also mov r10, TypeCastToByte(procParam) returns top_local for typecasted param
  288. // but no further information is available at this point to check
  289. else if (AVRInstrConstraint[opcode].Operands[i].typ = top_reg) and (taicpu(Result).oper[i]^.typ = top_local) and
  290. (opcode in [A_LDD, A_STD, A_MOV]) then
  291. begin
  292. err := false;
  293. end;
  294. if err then
  295. begin
  296. WriteStr(s1, taicpu(Result).oper[i]^.typ);
  297. WriteStr(s2, AVRInstrConstraint[opcode].Operands[i].typ);
  298. Message2(type_e_incompatible_types, s1, s2);
  299. end
  300. else if (taicpu(Result).oper[i]^.typ = top_reg) or opregasref then
  301. begin
  302. err := false;
  303. if not opregasref then
  304. reg := taicpu(Result).oper[i]^.reg;
  305. case AVRInstrConstraint[opcode].Operands[i].rt of
  306. rt_all: err := int64(reg) > $1030000; // excluding pointer registers X, Y, Z
  307. rt_even: err := int64(reg) mod 2 = 1;
  308. rt_even_24_30: err := not(word(reg) in [24, 26, 28, 30]);
  309. rt_16_31: err := not(word(reg) in [16..31]);
  310. rt_16_23: err := not(word(reg) in [16..23]);
  311. rt_Z: err := (int64(reg) <> $0103001e);
  312. rt_YZ: err := not((int64(reg) = $0103001c) or
  313. (int64(reg) =$0103001e));
  314. rt_XYZ: err := not((int64(reg) = $0103001a) or
  315. (int64(reg) = $0103001c) or
  316. (int64(reg) = $0103001e));
  317. end;
  318. // Catch erroneous z if it should be z+k or something similar
  319. // By checking if .am is not empty (implying a reference is expected)
  320. // ldd R20, z should not pass => opregasref = true
  321. // but ldd R20, z+1 should pass => opregasref = false
  322. if not (err) and (AVRInstrConstraint[opcode].Operands[i].am = [AM_UNCHANGED]) then
  323. err := not opregasref;
  324. if not (err) and not(AM_UNCHANGED in AVRInstrConstraint[opcode].Operands[i].am) and
  325. ((AM_POSTINCREMENT in AVRInstrConstraint[opcode].Operands[i].am) or
  326. (AM_PREDECREMENT in AVRInstrConstraint[opcode].Operands[i].am)) then
  327. err := not opregasref;
  328. if not(err) and opregasref then
  329. begin
  330. if (taicpu(Result).oper[i]^.ref^.addressmode = AM_UNCHANGED) and
  331. (AM_UNCHANGED in AVRInstrConstraint[opcode].Operands[i].am) then
  332. err := ((taicpu(Result).oper[i]^.ref^.offset > AVRInstrConstraint[opcode].Operands[i].maxconst) or
  333. (taicpu(Result).oper[i]^.ref^.offset < AVRInstrConstraint[opcode].Operands[i].minconst))
  334. else if (taicpu(Result).oper[i]^.ref^.addressmode in AVRInstrConstraint[opcode].Operands[i].am) then
  335. err := false
  336. else
  337. err := true;
  338. end;
  339. if err then
  340. Message1(asmr_e_invalid_ref_register, gas_regname(reg));
  341. end
  342. else if taicpu(Result).oper[i]^.typ = top_const then
  343. begin
  344. // Need to check if original value was signed or simply sign overflowed in 16 bit?
  345. if ((taicpu(Result).oper[i]^.val > AVRInstrConstraint[opcode].Operands[i].max) or
  346. (taicpu(Result).oper[i]^.val < AVRInstrConstraint[opcode].Operands[i].min)) then
  347. Message(asmr_e_constant_out_of_bounds);
  348. end;
  349. end;
  350. end;
  351. end;
  352. end;
  353. end.