ra68k.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. {
  2. Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
  3. Handles the common 68k 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 ra68k;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. aasmbase,aasmtai,aasmcpu,
  22. cpubase,rautils,cclasses;
  23. type
  24. Tm68kOperand=class(TOperand)
  25. end;
  26. Tm68kInstruction=class(TInstruction)
  27. opsize : topsize;
  28. function ConcatInstruction(p : taasmoutput):tai;override;
  29. function ConcatLabeledInstr(p : taasmoutput):tai;
  30. end;
  31. implementation
  32. uses
  33. verbose,cgbase;
  34. {*****************************************************************************
  35. TM68kInstruction
  36. *****************************************************************************}
  37. function TM68kInstruction.ConcatInstruction(p : taasmoutput):tai;
  38. var
  39. fits : boolean;
  40. begin
  41. result:=nil;
  42. fits := FALSE;
  43. { setup specific opcodetions for first pass }
  44. { Setup special operands }
  45. { Convert to general form as to conform to the m68k opcode table }
  46. if (opcode = A_ADDA) or (opcode = A_ADDI)
  47. then opcode := A_ADD
  48. else
  49. { CMPM excluded because of GAS v1.34 BUG }
  50. if (opcode = A_CMPA) or
  51. (opcode = A_CMPI) then
  52. opcode := A_CMP
  53. else
  54. if opcode = A_EORI then
  55. opcode := A_EOR
  56. else
  57. if opcode = A_MOVEA then
  58. opcode := A_MOVE
  59. else
  60. if opcode = A_ORI then
  61. opcode := A_OR
  62. else
  63. if (opcode = A_SUBA) or (opcode = A_SUBI) then
  64. opcode := A_SUB;
  65. { Setup operand types }
  66. (*
  67. in opcode <> A_MOVEM then
  68. begin
  69. while not(fits) do
  70. begin
  71. { set the opcodetion cache, if the opcodetion }
  72. { occurs the first time }
  73. if (it[i].i=opcode) and (ins_cache[opcode]=-1) then
  74. ins_cache[opcode]:=i;
  75. if (it[i].i=opcode) and (instr.ops=it[i].ops) then
  76. begin
  77. { first fit }
  78. case instr.ops of
  79. 0 : begin
  80. fits:=true;
  81. break;
  82. end;
  83. 1 :
  84. begin
  85. if (optyp1 and it[i].o1)<>0 then
  86. begin
  87. fits:=true;
  88. break;
  89. end;
  90. end;
  91. 2 : if ((optyp1 and it[i].o1)<>0) and
  92. ((optyp2 and it[i].o2)<>0) then
  93. begin
  94. fits:=true;
  95. break;
  96. end
  97. 3 : if ((optyp1 and it[i].o1)<>0) and
  98. ((optyp2 and it[i].o2)<>0) and
  99. ((optyp3 and it[i].o3)<>0) then
  100. begin
  101. fits:=true;
  102. break;
  103. end;
  104. end; { end case }
  105. end; { endif }
  106. if it[i].i=A_NONE then
  107. begin
  108. { NO MATCH! }
  109. Message(asmr_e_invalid_combination_opcode_and_operand);
  110. exit;
  111. end;
  112. inc(i);
  113. end; { end while }
  114. *)
  115. fits:=TRUE;
  116. { We add the opcode to the opcode linked list }
  117. if fits then
  118. begin
  119. case ops of
  120. 0:
  121. if opsize <> S_NO then
  122. result:=(taicpu.op_none(opcode,opsize))
  123. else
  124. result:=(taicpu.op_none(opcode,S_NO));
  125. 1: begin
  126. case operands[1].opr.typ of
  127. OPR_SYMBOL:
  128. begin
  129. result:=(taicpu.op_sym_ofs(opcode,
  130. opsize, operands[1].opr.symbol,operands[1].opr.symofs));
  131. end;
  132. OPR_CONSTANT:
  133. begin
  134. result:=(taicpu.op_const(opcode,
  135. opsize, operands[1].opr.val));
  136. end;
  137. OPR_REGISTER:
  138. result:=(taicpu.op_reg(opcode,opsize,operands[1].opr.reg));
  139. OPR_REFERENCE:
  140. if opsize <> S_NO then
  141. begin
  142. result:=(taicpu.op_ref(opcode,
  143. opsize,operands[1].opr.ref));
  144. end
  145. else
  146. begin
  147. { special jmp and call case with }
  148. { symbolic references. }
  149. if opcode in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then
  150. begin
  151. result:=(taicpu.op_ref(opcode,
  152. S_NO,operands[1].opr.ref));
  153. end
  154. else
  155. Message(asmr_e_invalid_opcode_and_operand);
  156. end;
  157. OPR_NONE:
  158. Message(asmr_e_invalid_opcode_and_operand);
  159. else
  160. begin
  161. Message(asmr_e_invalid_opcode_and_operand);
  162. end;
  163. end;
  164. end;
  165. 2: begin
  166. { source }
  167. case operands[1].opr.typ of
  168. { reg,reg }
  169. { reg,ref }
  170. OPR_REGISTER:
  171. begin
  172. case operands[2].opr.typ of
  173. OPR_REGISTER:
  174. begin
  175. result:=(taicpu.op_reg_reg(opcode,
  176. opsize,operands[1].opr.reg,operands[2].opr.reg));
  177. end;
  178. OPR_REFERENCE:
  179. result:=(taicpu.op_reg_ref(opcode,
  180. opsize,operands[1].opr.reg,operands[2].opr.ref));
  181. else { else case }
  182. begin
  183. Message(asmr_e_invalid_opcode_and_operand);
  184. end;
  185. end; { end second operand case for OPR_REGISTER }
  186. end;
  187. { regset, ref }
  188. OPR_regset:
  189. begin
  190. case operands[2].opr.typ of
  191. OPR_REFERENCE :
  192. result:=(taicpu.op_regset_ref(opcode,
  193. opsize,operands[1].opr.regset,operands[2].opr.ref));
  194. else
  195. begin
  196. Message(asmr_e_invalid_opcode_and_operand);
  197. end;
  198. end; { end second operand case for OPR_regset }
  199. end;
  200. { const,reg }
  201. { const,const }
  202. { const,ref }
  203. OPR_CONSTANT:
  204. case operands[2].opr.typ of
  205. { constant, constant does not have a specific size. }
  206. OPR_CONSTANT:
  207. result:=(taicpu.op_const_const(opcode,
  208. S_NO,operands[1].opr.val,operands[2].opr.val));
  209. OPR_REFERENCE:
  210. begin
  211. result:=(taicpu.op_const_ref(opcode,
  212. opsize,operands[1].opr.val,
  213. operands[2].opr.ref))
  214. end;
  215. OPR_REGISTER:
  216. begin
  217. result:=(taicpu.op_const_reg(opcode,
  218. opsize,operands[1].opr.val,
  219. operands[2].opr.reg))
  220. end;
  221. else
  222. begin
  223. Message(asmr_e_invalid_opcode_and_operand);
  224. end;
  225. end; { end second operand case for OPR_CONSTANT }
  226. { ref,reg }
  227. { ref,ref }
  228. OPR_REFERENCE:
  229. case operands[2].opr.typ of
  230. OPR_REGISTER:
  231. begin
  232. result:=(taicpu.op_ref_reg(opcode,
  233. opsize,operands[1].opr.ref,
  234. operands[2].opr.reg));
  235. end;
  236. OPR_regset:
  237. begin
  238. result:=(taicpu.op_ref_regset(opcode,
  239. opsize,operands[1].opr.ref,
  240. operands[2].opr.regset));
  241. end;
  242. OPR_REFERENCE: { special opcodes }
  243. result:=(taicpu.op_ref_ref(opcode,
  244. opsize,operands[1].opr.ref,
  245. operands[2].opr.ref));
  246. else
  247. begin
  248. Message(asmr_e_invalid_opcode_and_operand);
  249. end;
  250. end; { end second operand case for OPR_REFERENCE }
  251. OPR_SYMBOL: case operands[2].opr.typ of
  252. OPR_REFERENCE:
  253. begin
  254. result:=(taicpu.op_sym_ofs_ref(opcode,
  255. opsize,operands[1].opr.symbol,operands[1].opr.symofs,
  256. operands[2].opr.ref))
  257. end;
  258. OPR_REGISTER:
  259. begin
  260. result:=(taicpu.op_sym_ofs_reg(opcode,
  261. opsize,operands[1].opr.symbol,operands[1].opr.symofs,
  262. operands[2].opr.reg))
  263. end;
  264. else
  265. begin
  266. Message(asmr_e_invalid_opcode_and_operand);
  267. end;
  268. end; { end second operand case for OPR_SYMBOL }
  269. else
  270. begin
  271. Message(asmr_e_invalid_opcode_and_operand);
  272. end;
  273. end; { end first operand case }
  274. end;
  275. 3: begin
  276. if (opcode = A_DIVSL) or (opcode = A_DIVUL) or (opcode = A_MULU)
  277. or (opcode = A_MULS) or (opcode = A_DIVS) or (opcode = A_DIVU) then
  278. begin
  279. if (operands[1].opr.typ <> OPR_REGISTER)
  280. or (operands[2].opr.typ <> OPR_REGISTER)
  281. or (operands[3].opr.typ <> OPR_REGISTER) then
  282. begin
  283. Message(asmr_e_invalid_opcode_and_operand);
  284. end
  285. else
  286. begin
  287. result:=(taicpu. op_reg_reg_reg(opcode,opsize,
  288. operands[1].opr.reg,operands[2].opr.reg,operands[3].opr.reg));
  289. end;
  290. end
  291. else
  292. Message(asmr_e_invalid_opcode_and_operand);
  293. end;
  294. end; { end case }
  295. end;
  296. if assigned(result) then
  297. p.concat(result);
  298. end;
  299. function TM68kInstruction.ConcatLabeledInstr(p : taasmoutput):tai;
  300. begin
  301. if ((opcode >= A_BCC) and (opcode <= A_BVS)) or
  302. (opcode = A_BRA) or (opcode = A_BSR) or
  303. (opcode = A_JMP) or (opcode = A_JSR) or
  304. ((opcode >= A_FBEQ) and (opcode <= A_FBNGLE)) then
  305. begin
  306. if ops > 2 then
  307. Message(asmr_e_invalid_opcode_and_operand)
  308. else if operands[1].opr.typ <> OPR_SYMBOL then
  309. Message(asmr_e_invalid_opcode_and_operand)
  310. else if (operands[1].opr.typ = OPR_SYMBOL) and
  311. (ops = 1) then
  312. if assigned(operands[1].opr.symbol) and
  313. (operands[1].opr.symofs=0) then
  314. result:=taicpu.op_sym(opcode,S_NO,
  315. operands[1].opr.symbol)
  316. else
  317. Message(asmr_e_invalid_opcode_and_operand);
  318. end
  319. else if ((opcode >= A_DBCC) and (opcode <= A_DBF))
  320. or ((opcode >= A_FDBEQ) and (opcode <= A_FDBNGLE)) then
  321. begin
  322. if (ops<>2) or
  323. (operands[1].opr.typ <> OPR_REGISTER) or
  324. (operands[2].opr.typ <> OPR_SYMBOL) or
  325. (operands[2].opr.symofs <> 0) then
  326. Message(asmr_e_invalid_opcode_and_operand)
  327. else
  328. result:=taicpu.op_reg_sym(opcode,opsize,operands[1].opr.reg,
  329. operands[2].opr.symbol);
  330. end
  331. else
  332. Message(asmr_e_invalid_opcode_and_operand);
  333. if assigned(result) then
  334. p.concat(result);
  335. end;
  336. end.