rasm.pas 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Carl Eric Codere
  4. This unit does the parsing process for the motorola inline assembler
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit Rasm;
  19. {**********************************************************************}
  20. { WARNING }
  21. {**********************************************************************}
  22. { Any modification in the order or removal of terms in the tables }
  23. { in m68k.pas and asmo68k.pas will BREAK the code in this unit, }
  24. { unless the appropriate changes are made to this unit. Addition }
  25. { of terms though, will not change the code herein. }
  26. {**********************************************************************}
  27. {---------------------------------------------------------------------------}
  28. { LEFT TO DO }
  29. {---------------------------------------------------------------------------}
  30. { o Add support for sized indexing such as in d0.l }
  31. { presently only (an,dn) is supported for indexing -- }
  32. { size defaults to LONG. }
  33. { o Add support for MC68020 opcodes. }
  34. { o Add support for MC68020 adressing modes. }
  35. { o Add operand checking with m68k opcode table in ConcatOpCode }
  36. { o Add Floating point support }
  37. {---------------------------------------------------------------------------}
  38. Interface
  39. {$i fpcdefs.inc}
  40. Uses
  41. node;
  42. function assemble: tnode;
  43. Implementation
  44. uses
  45. { common }
  46. cutils,cclasses,
  47. { global }
  48. globtype,globals,verbose,
  49. systems,
  50. { aasm }
  51. cpubase,cpuinfo,aasmbase,aasmtai,aasmcpu,
  52. { symtable }
  53. symconst,symbase,symtype,symsym,symtable,
  54. { pass 1 }
  55. nbas,
  56. { parser }
  57. scanner,agcpugas,
  58. rautils
  59. ;
  60. const
  61. { this variable is TRUE if the lookup tables have already been setup }
  62. { for fast access. On the first call to assemble the tables are setup }
  63. { and stay set up. }
  64. _asmsorted: boolean = FALSE;
  65. firstasmreg = R_D0;
  66. lastasmreg = R_FPSR;
  67. type
  68. tiasmops = array[firstop..lastop] of string[7];
  69. piasmops = ^tiasmops;
  70. tasmkeyword = string[6];
  71. var
  72. { sorted tables of opcodes }
  73. iasmops: piasmops;
  74. { uppercased tables of registers }
  75. iasmregs: array[firstasmreg..lastasmreg] of string[6];
  76. type
  77. tasmtoken = (
  78. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
  79. AS_BINNUM,AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
  80. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
  81. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_APPT,AS_REALNUM,
  82. AS_ALIGN,
  83. {------------------ Assembler directives --------------------}
  84. AS_DB,AS_DW,AS_DD,AS_XDEF,AS_END,
  85. {------------------ Assembler Operators --------------------}
  86. AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR);
  87. const
  88. firstdirective = AS_DB;
  89. lastdirective = AS_END;
  90. firstoperator = AS_MOD;
  91. lastoperator = AS_XOR;
  92. _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  93. _count_asmoperators = longint(lastoperator)-longint(firstoperator);
  94. _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  95. ('DC.B','DC.W','DC.L','XDEF','END');
  96. { problems with shl,shr,not,and,or and xor, they are }
  97. { context sensitive. }
  98. _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
  99. 'MOD','SHL','SHR','NOT','AND','OR','XOR');
  100. const
  101. newline = #10;
  102. firsttoken : boolean = TRUE;
  103. operandnum : byte = 0;
  104. var
  105. actasmtoken: tasmtoken;
  106. actasmpattern: string;
  107. c: char;
  108. old_exit : pointer;
  109. curlist : taasmoutput;
  110. Procedure SetupTables;
  111. { creates uppercased symbol tables for speed access }
  112. var
  113. i: tasmop;
  114. j: tregister;
  115. Begin
  116. {Message(asmr_d_creating_lookup_tables);}
  117. { opcodes }
  118. new(iasmops);
  119. for i:=firstop to lastop do
  120. iasmops^[i] := upper(gas_op2str[i]);
  121. { opcodes }
  122. for j:=firstasmreg to lastasmreg do
  123. iasmregs[j] := upper(std_reg2str[j]);
  124. end;
  125. {---------------------------------------------------------------------}
  126. { Routines for the tokenizing }
  127. {---------------------------------------------------------------------}
  128. function is_asmopcode(s: string):Boolean;
  129. {*********************************************************************}
  130. { FUNCTION is_asmopcode(s: string):Boolean }
  131. { Description: Determines if the s string is a valid opcode }
  132. { if so returns TRUE otherwise returns FALSE. }
  133. { Remark: Suffixes are also checked, as long as they are valid. }
  134. {*********************************************************************}
  135. var
  136. i: tasmop;
  137. j: byte;
  138. Begin
  139. is_asmopcode := FALSE;
  140. { first of all we remove the suffix }
  141. j:=pos('.',s);
  142. if j<>0 then
  143. delete(s,j,2);
  144. for i:=firstop to lastop do
  145. begin
  146. if s = iasmops^[i] then
  147. begin
  148. is_asmopcode:=TRUE;
  149. exit;
  150. end;
  151. end;
  152. end;
  153. Procedure is_asmdirective(const s: string; var token: tasmtoken);
  154. {*********************************************************************}
  155. { FUNCTION is_asmdirective(s: string; var token: tinteltoken):Boolean }
  156. { Description: Determines if the s string is a valid directive }
  157. { (an operator can occur in operand fields, while a directive cannot) }
  158. { if so returns the directive token, otherwise does not change token.}
  159. {*********************************************************************}
  160. var
  161. i:byte;
  162. Begin
  163. for i:=0 to _count_asmdirectives do
  164. begin
  165. if s=_asmdirectives[i] then
  166. begin
  167. token := tasmtoken(longint(firstdirective)+i);
  168. exit;
  169. end;
  170. end;
  171. end;
  172. Procedure is_register(const s: string; var token: tasmtoken);
  173. {*********************************************************************}
  174. { PROCEDURE is_register(s: string; var token: tinteltoken); }
  175. { Description: Determines if the s string is a valid register, if }
  176. { so return token equal to A_REGISTER, otherwise does not change token}
  177. {*********************************************************************}
  178. Var
  179. i: tregister;
  180. Begin
  181. for i:=firstasmreg to lastasmreg do
  182. begin
  183. if s=iasmregs[i] then
  184. begin
  185. token := AS_REGISTER;
  186. exit;
  187. end;
  188. end;
  189. { take care of other name for sp }
  190. if s = 'A7' then
  191. begin
  192. token:=AS_REGISTER;
  193. exit;
  194. end;
  195. end;
  196. Function GetToken: tasmtoken;
  197. {*********************************************************************}
  198. { FUNCTION GetToken: tinteltoken; }
  199. { Description: This routine returns intel assembler tokens and }
  200. { does some minor syntax error checking. }
  201. {*********************************************************************}
  202. var
  203. token: tasmtoken;
  204. forcelabel: boolean;
  205. begin
  206. forcelabel := FALSE;
  207. actasmpattern :='';
  208. {* INIT TOKEN TO NOTHING *}
  209. token := AS_NONE;
  210. { while space and tab , continue scan... }
  211. while c in [' ',#9] do
  212. c:=current_scanner.asmgetchar;
  213. if not (c in [newline,#13,'{',';']) then
  214. current_scanner.gettokenpos;
  215. { Possiblities for first token in a statement: }
  216. { Local Label, Label, Directive, Prefix or Opcode.... }
  217. if firsttoken and not (c in [newline,#13,'{',';']) then
  218. begin
  219. firsttoken := FALSE;
  220. if c = '@' then
  221. begin
  222. token := AS_LLABEL; { this is a local label }
  223. { Let us point to the next character }
  224. c := current_scanner.asmgetchar;
  225. end;
  226. while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
  227. begin
  228. { if there is an at_sign, then this must absolutely be a label }
  229. if c = '@' then forcelabel:=TRUE;
  230. actasmpattern := actasmpattern + c;
  231. c := current_scanner.asmgetchar;
  232. end;
  233. uppervar(actasmpattern);
  234. if c = ':' then
  235. begin
  236. case token of
  237. AS_NONE: token := AS_LABEL;
  238. AS_LLABEL: ; { do nothing }
  239. end; { end case }
  240. { let us point to the next character }
  241. c := current_scanner.asmgetchar;
  242. gettoken := token;
  243. exit;
  244. end;
  245. { Are we trying to create an identifier with }
  246. { an at-sign...? }
  247. if forcelabel then
  248. Message(asmr_e_none_label_contain_at);
  249. If is_asmopcode(actasmpattern) then
  250. Begin
  251. gettoken := AS_OPCODE;
  252. exit;
  253. end;
  254. is_asmdirective(actasmpattern, token);
  255. if (token <> AS_NONE) then
  256. Begin
  257. gettoken := token;
  258. exit
  259. end
  260. else
  261. begin
  262. gettoken := AS_NONE;
  263. Message1(asmr_e_invalid_or_missing_opcode,actasmpattern);
  264. end;
  265. end
  266. else { else firsttoken }
  267. { Here we must handle all possible cases }
  268. begin
  269. case c of
  270. '@': { possiblities : - local label reference , such as in jmp @local1 }
  271. { - @Result, @Code or @Data special variables. }
  272. begin
  273. actasmpattern := c;
  274. c:= current_scanner.asmgetchar;
  275. while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
  276. begin
  277. actasmpattern := actasmpattern + c;
  278. c := current_scanner.asmgetchar;
  279. end;
  280. uppervar(actasmpattern);
  281. gettoken := AS_ID;
  282. exit;
  283. end;
  284. { identifier, register, opcode, prefix or directive }
  285. 'A'..'Z','a'..'z','_': begin
  286. actasmpattern := c;
  287. c:= current_scanner.asmgetchar;
  288. while c in ['A'..'Z','a'..'z','0'..'9','_','.'] do
  289. begin
  290. actasmpattern := actasmpattern + c;
  291. c := current_scanner.asmgetchar;
  292. end;
  293. uppervar(actasmpattern);
  294. If is_asmopcode(actasmpattern) then
  295. Begin
  296. gettoken := AS_OPCODE;
  297. exit;
  298. end;
  299. is_register(actasmpattern, token);
  300. {is_asmoperator(actasmpattern,token);}
  301. is_asmdirective(actasmpattern,token);
  302. { if found }
  303. if (token <> AS_NONE) then
  304. begin
  305. gettoken := token;
  306. exit;
  307. end
  308. { this is surely an identifier }
  309. else
  310. token := AS_ID;
  311. gettoken := token;
  312. exit;
  313. end;
  314. { override operator... not supported }
  315. '&': begin
  316. c:=current_scanner.asmgetchar;
  317. gettoken := AS_AND;
  318. end;
  319. { string or character }
  320. '''' :
  321. begin
  322. actasmpattern:='';
  323. while true do
  324. begin
  325. if c = '''' then
  326. begin
  327. c:=current_scanner.asmgetchar;
  328. if c=newline then
  329. begin
  330. Message(scan_f_string_exceeds_line);
  331. break;
  332. end;
  333. repeat
  334. if c=''''then
  335. begin
  336. c:=current_scanner.asmgetchar;
  337. if c='''' then
  338. begin
  339. actasmpattern:=actasmpattern+'''';
  340. c:=current_scanner.asmgetchar;
  341. if c=newline then
  342. begin
  343. Message(scan_f_string_exceeds_line);
  344. break;
  345. end;
  346. end
  347. else break;
  348. end
  349. else
  350. begin
  351. actasmpattern:=actasmpattern+c;
  352. c:=current_scanner.asmgetchar;
  353. if c=newline then
  354. begin
  355. Message(scan_f_string_exceeds_line);
  356. break
  357. end;
  358. end;
  359. until false; { end repeat }
  360. end
  361. else break; { end if }
  362. end; { end while }
  363. token:=AS_STRING;
  364. gettoken := token;
  365. exit;
  366. end;
  367. '$' : begin
  368. c:=current_scanner.asmgetchar;
  369. while c in ['0'..'9','A'..'F','a'..'f'] do
  370. begin
  371. actasmpattern := actasmpattern + c;
  372. c := current_scanner.asmgetchar;
  373. end;
  374. gettoken := AS_HEXNUM;
  375. exit;
  376. end;
  377. ',' : begin
  378. gettoken := AS_COMMA;
  379. c:=current_scanner.asmgetchar;
  380. exit;
  381. end;
  382. '(' : begin
  383. gettoken := AS_LPAREN;
  384. c:=current_scanner.asmgetchar;
  385. exit;
  386. end;
  387. ')' : begin
  388. gettoken := AS_RPAREN;
  389. c:=current_scanner.asmgetchar;
  390. exit;
  391. end;
  392. ':' : begin
  393. gettoken := AS_COLON;
  394. c:=current_scanner.asmgetchar;
  395. exit;
  396. end;
  397. { '.' : begin
  398. gettoken := AS_DOT;
  399. c:=current_scanner.asmgetchar;
  400. exit;
  401. end; }
  402. '+' : begin
  403. gettoken := AS_PLUS;
  404. c:=current_scanner.asmgetchar;
  405. exit;
  406. end;
  407. '-' : begin
  408. gettoken := AS_MINUS;
  409. c:=current_scanner.asmgetchar;
  410. exit;
  411. end;
  412. '*' : begin
  413. gettoken := AS_STAR;
  414. c:=current_scanner.asmgetchar;
  415. exit;
  416. end;
  417. '/' : begin
  418. gettoken := AS_SLASH;
  419. c:=current_scanner.asmgetchar;
  420. exit;
  421. end;
  422. '<' : begin
  423. c := current_scanner.asmgetchar;
  424. { invalid characters }
  425. if c <> '<' then
  426. Message(asmr_e_invalid_char_smaller);
  427. { still assume << }
  428. gettoken := AS_SHL;
  429. c := current_scanner.asmgetchar;
  430. exit;
  431. end;
  432. '>' : begin
  433. c := current_scanner.asmgetchar;
  434. { invalid characters }
  435. if c <> '>' then
  436. Message(asmr_e_invalid_char_greater);
  437. { still assume << }
  438. gettoken := AS_SHR;
  439. c := current_scanner.asmgetchar;
  440. exit;
  441. end;
  442. '|' : begin
  443. gettoken := AS_OR;
  444. c := current_scanner.asmgetchar;
  445. exit;
  446. end;
  447. '^' : begin
  448. gettoken := AS_XOR;
  449. c := current_scanner.asmgetchar;
  450. exit;
  451. end;
  452. '#' : begin
  453. gettoken:=AS_APPT;
  454. c:=current_scanner.asmgetchar;
  455. exit;
  456. end;
  457. '%' : begin
  458. c:=current_scanner.asmgetchar;
  459. while c in ['0','1'] do
  460. Begin
  461. actasmpattern := actasmpattern + c;
  462. c := current_scanner.asmgetchar;
  463. end;
  464. gettoken := AS_BINNUM;
  465. exit;
  466. end;
  467. { integer number }
  468. '0'..'9': begin
  469. actasmpattern := c;
  470. c := current_scanner.asmgetchar;
  471. while c in ['0'..'9'] do
  472. Begin
  473. actasmpattern := actasmpattern + c;
  474. c:= current_scanner.asmgetchar;
  475. end;
  476. gettoken := AS_INTNUM;
  477. exit;
  478. end;
  479. ';' : begin
  480. repeat
  481. c:=current_scanner.asmgetchar;
  482. until c=newline;
  483. firsttoken := TRUE;
  484. gettoken:=AS_SEPARATOR;
  485. end;
  486. '{',#13,newline : begin
  487. c:=current_scanner.asmgetchar;
  488. firsttoken := TRUE;
  489. gettoken:=AS_SEPARATOR;
  490. end;
  491. else
  492. Begin
  493. Message(scan_f_illegal_char);
  494. end;
  495. end; { end case }
  496. end; { end else if }
  497. end;
  498. {---------------------------------------------------------------------}
  499. { Routines for the parsing }
  500. {---------------------------------------------------------------------}
  501. procedure consume(t : tasmtoken);
  502. begin
  503. if t<>actasmtoken then
  504. Message(asmr_e_syntax_error);
  505. actasmtoken:=gettoken;
  506. { if the token must be ignored, then }
  507. { get another token to parse. }
  508. if actasmtoken = AS_NONE then
  509. actasmtoken := gettoken;
  510. end;
  511. function findregister(const s : string): tregister;
  512. {*********************************************************************}
  513. { FUNCTION findregister(s: string):tasmop; }
  514. { Description: Determines if the s string is a valid register, }
  515. { if so returns correct tregister token, or R_NO if not found. }
  516. {*********************************************************************}
  517. var
  518. i: tregister;
  519. begin
  520. findregister := R_NO;
  521. for i:=firstasmreg to lastasmreg do
  522. if s = iasmregs[i] then
  523. Begin
  524. findregister := i;
  525. exit;
  526. end;
  527. if s = 'A7' then
  528. Begin
  529. findregister := R_SP;
  530. exit;
  531. end;
  532. end;
  533. function findopcode(s: string; var opsize: topsize): tasmop;
  534. {*********************************************************************}
  535. { FUNCTION findopcode(s: string): tasmop; }
  536. { Description: Determines if the s string is a valid opcode }
  537. { if so returns correct tasmop token. }
  538. {*********************************************************************}
  539. var
  540. i: tasmop;
  541. j: byte;
  542. op_size: string;
  543. Begin
  544. findopcode := A_NONE;
  545. j:=pos('.',s);
  546. if j<>0 then
  547. begin
  548. op_size:=copy(s,j+1,1);
  549. case op_size[1] of
  550. { For the motorola only opsize size is used to }
  551. { determine the size of the operands. }
  552. 'B': opsize := S_B;
  553. 'W': opsize := S_W;
  554. 'L': opsize := S_L;
  555. 'S': opsize := S_FS;
  556. 'D': opsize := S_FD;
  557. 'X': opsize := S_FX;
  558. else
  559. Message1(asmr_e_unknown_opcode,s);
  560. end;
  561. { delete everything starting from dot }
  562. delete(s,j,length(s));
  563. end;
  564. for i:=firstop to lastop do
  565. if s = iasmops^[i] then
  566. begin
  567. findopcode:=i;
  568. exit;
  569. end;
  570. end;
  571. Function BuildExpression(allow_symbol : boolean; asmsym : pstring) : longint;
  572. {*********************************************************************}
  573. { FUNCTION BuildExpression: longint }
  574. { Description: This routine calculates a constant expression to }
  575. { a given value. The return value is the value calculated from }
  576. { the expression. }
  577. { The following tokens (not strings) are recognized: }
  578. { (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
  579. {*********************************************************************}
  580. { ENTRY: On entry the token should be any valid expression token. }
  581. { EXIT: On Exit the token points to either COMMA or SEPARATOR }
  582. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  583. { invalid tokens. }
  584. {*********************************************************************}
  585. var expr: string;
  586. hs, tempstr: string;
  587. sym : tsym;
  588. srsymtable : tsymtable;
  589. hl : tasmlabel;
  590. l : longint;
  591. errorflag: boolean;
  592. Begin
  593. errorflag := FALSE;
  594. expr := '';
  595. tempstr := '';
  596. if allow_symbol then
  597. asmsym^:='';
  598. Repeat
  599. Case actasmtoken of
  600. AS_LPAREN: Begin
  601. Consume(AS_LPAREN);
  602. expr := expr + '(';
  603. end;
  604. AS_RPAREN: Begin
  605. Consume(AS_RPAREN);
  606. expr := expr + ')';
  607. end;
  608. AS_SHL: Begin
  609. Consume(AS_SHL);
  610. expr := expr + '<';
  611. end;
  612. AS_SHR: Begin
  613. Consume(AS_SHR);
  614. expr := expr + '>';
  615. end;
  616. AS_SLASH: Begin
  617. Consume(AS_SLASH);
  618. expr := expr + '/';
  619. end;
  620. AS_MOD: Begin
  621. Consume(AS_MOD);
  622. expr := expr + '%';
  623. end;
  624. AS_STAR: Begin
  625. Consume(AS_STAR);
  626. expr := expr + '*';
  627. end;
  628. AS_PLUS: Begin
  629. Consume(AS_PLUS);
  630. expr := expr + '+';
  631. end;
  632. AS_MINUS: Begin
  633. Consume(AS_MINUS);
  634. expr := expr + '-';
  635. end;
  636. AS_AND: Begin
  637. Consume(AS_AND);
  638. expr := expr + '&';
  639. end;
  640. AS_NOT: Begin
  641. Consume(AS_NOT);
  642. expr := expr + '~';
  643. end;
  644. AS_XOR: Begin
  645. Consume(AS_XOR);
  646. expr := expr + '^';
  647. end;
  648. AS_OR: Begin
  649. Consume(AS_OR);
  650. expr := expr + '|';
  651. end;
  652. AS_ID: Begin
  653. if SearchIConstant(actasmpattern,l) then
  654. Begin
  655. str(l, tempstr);
  656. expr := expr + tempstr;
  657. Consume(AS_ID);
  658. End else
  659. if not allow_symbol then
  660. Begin
  661. Message(asmr_e_syn_constant);
  662. l := 0;
  663. End else
  664. Begin
  665. hs:='';
  666. if (expr[Length(expr)]='+') then
  667. Delete(expr,Length(expr),1)
  668. else if expr<>'' then
  669. Begin
  670. Message(asmr_e_invalid_constant_expression);
  671. break;
  672. End;
  673. tempstr:=actasmpattern;
  674. consume(AS_ID);
  675. if (length(tempstr)>1) and (tempstr[1]='@') then
  676. begin
  677. CreateLocalLabel(tempstr,hl,false);
  678. hs:=hl.name
  679. end
  680. else if SearchLabel(tempstr,hl,false) then
  681. hs:=hl.name
  682. else
  683. begin
  684. searchsym(tempstr,sym,srsymtable);
  685. if assigned(sym) then
  686. begin
  687. case sym.typ of
  688. varsym :
  689. begin
  690. if sym.owner.symtabletype in [localsymtable,parasymtable] then
  691. Message(asmr_e_no_local_or_para_allowed);
  692. hs:=tvarsym(sym).mangledname;
  693. end;
  694. typedconstsym :
  695. hs:=ttypedconstsym(sym).mangledname;
  696. procsym :
  697. begin
  698. if assigned(tprocsym(sym).defs^.next) then
  699. Message(asmr_w_calling_overload_func);
  700. hs:=tprocsym(sym).defs^.def.mangledname;
  701. end;
  702. typesym :
  703. begin
  704. if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
  705. Message(asmr_e_wrong_sym_type);
  706. end;
  707. else
  708. Message(asmr_e_wrong_sym_type);
  709. end;
  710. end
  711. else
  712. Message1(sym_e_unknown_id,tempstr);
  713. end;
  714. { symbol found? }
  715. if hs<>'' then
  716. begin
  717. if asmsym^='' then
  718. asmsym^:=hs
  719. else
  720. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  721. end;
  722. end;
  723. end;
  724. AS_INTNUM: Begin
  725. expr := expr + actasmpattern;
  726. Consume(AS_INTNUM);
  727. end;
  728. AS_BINNUM: Begin
  729. tempstr := tostr(ValBinary(actasmpattern));
  730. if tempstr = '' then
  731. Message(asmr_e_error_converting_binary);
  732. expr:=expr+tempstr;
  733. Consume(AS_BINNUM);
  734. end;
  735. AS_HEXNUM: Begin
  736. tempstr := tostr(ValHexadecimal(actasmpattern));
  737. if tempstr = '' then
  738. Message(asmr_e_error_converting_hexadecimal);
  739. expr:=expr+tempstr;
  740. Consume(AS_HEXNUM);
  741. end;
  742. AS_OCTALNUM: Begin
  743. tempstr := tostr(ValOctal(actasmpattern));
  744. if tempstr = '' then
  745. Message(asmr_e_error_converting_octal);
  746. expr:=expr+tempstr;
  747. Consume(AS_OCTALNUM);
  748. end;
  749. { go to next term }
  750. AS_COMMA: Begin
  751. if not ErrorFlag then
  752. BuildExpression := CalculateExpression(expr)
  753. else
  754. BuildExpression := 0;
  755. Exit;
  756. end;
  757. { go to next symbol }
  758. AS_SEPARATOR: Begin
  759. if not ErrorFlag then
  760. BuildExpression := CalculateExpression(expr)
  761. else
  762. BuildExpression := 0;
  763. Exit;
  764. end;
  765. else
  766. Begin
  767. { only write error once. }
  768. if not errorflag then
  769. Message(asmr_e_invalid_constant_expression);
  770. { consume tokens until we find COMMA or SEPARATOR }
  771. Consume(actasmtoken);
  772. errorflag := TRUE;
  773. End;
  774. end;
  775. Until false;
  776. end;
  777. Procedure BuildRealConstant(typ : tfloattype);
  778. {*********************************************************************}
  779. { PROCEDURE BuilRealConst }
  780. { Description: This routine calculates a constant expression to }
  781. { a given value. The return value is the value calculated from }
  782. { the expression. }
  783. { The following tokens (not strings) are recognized: }
  784. { +/-,numbers and real numbers }
  785. {*********************************************************************}
  786. { ENTRY: On entry the token should be any valid expression token. }
  787. { EXIT: On Exit the token points to either COMMA or SEPARATOR }
  788. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  789. { invalid tokens. }
  790. {*********************************************************************}
  791. var expr: string;
  792. r : extended;
  793. code : word;
  794. negativ : boolean;
  795. errorflag: boolean;
  796. Begin
  797. errorflag := FALSE;
  798. Repeat
  799. negativ:=false;
  800. expr := '';
  801. if actasmtoken=AS_PLUS then Consume(AS_PLUS)
  802. else if actasmtoken=AS_MINUS then
  803. begin
  804. negativ:=true;
  805. consume(AS_MINUS);
  806. end;
  807. Case actasmtoken of
  808. AS_INTNUM: Begin
  809. expr := actasmpattern;
  810. Consume(AS_INTNUM);
  811. end;
  812. AS_REALNUM: Begin
  813. expr := actasmpattern;
  814. { in ATT syntax you have 0d in front of the real }
  815. { should this be forced ? yes i think so, as to }
  816. { conform to gas as much as possible. }
  817. if (expr[1]='0') and (upper(expr[2])='D') then
  818. expr:=copy(expr,3,255);
  819. Consume(AS_REALNUM);
  820. end;
  821. AS_BINNUM: Begin
  822. { checking for real constants with this should use }
  823. { real DECODING otherwise the compiler will crash! }
  824. Message(asmr_e_invalid_float_expr);
  825. expr:='0.0';
  826. Consume(AS_BINNUM);
  827. end;
  828. AS_HEXNUM: Begin
  829. { checking for real constants with this should use }
  830. { real DECODING otherwise the compiler will crash! }
  831. Message(asmr_e_invalid_float_expr);
  832. expr:='0.0';
  833. Consume(AS_HEXNUM);
  834. end;
  835. AS_OCTALNUM: Begin
  836. { checking for real constants with this should use }
  837. { real DECODING otherwise the compiler will crash! }
  838. { xxxToDec using reals could be a solution, but the }
  839. { problem is that these will crash the m68k compiler }
  840. { when compiling -- because of lack of good fpu }
  841. { support. }
  842. Message(asmr_e_invalid_float_expr);
  843. expr:='0.0';
  844. Consume(AS_OCTALNUM);
  845. end;
  846. else
  847. Begin
  848. { only write error once. }
  849. if not errorflag then
  850. Message(asmr_e_invalid_float_expr);
  851. { consume tokens until we find COMMA or SEPARATOR }
  852. Consume(actasmtoken);
  853. errorflag := TRUE;
  854. End;
  855. end;
  856. { go to next term }
  857. if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
  858. Begin
  859. if negativ then expr:='-'+expr;
  860. val(expr,r,code);
  861. if code<>0 then
  862. Begin
  863. r:=0;
  864. Message(asmr_e_invalid_float_expr);
  865. ConcatRealConstant(curlist,r,typ);
  866. End
  867. else
  868. Begin
  869. ConcatRealConstant(curlist,r,typ);
  870. End;
  871. end
  872. else
  873. Message(asmr_e_invalid_float_expr);
  874. Until actasmtoken=AS_SEPARATOR;
  875. end;
  876. Procedure BuildConstant(maxvalue: longint);
  877. {*********************************************************************}
  878. { PROCEDURE BuildConstant }
  879. { Description: This routine takes care of parsing a DB,DD,or DW }
  880. { line and adding those to the assembler node. Expressions, range- }
  881. { checking are fullly taken care of. }
  882. { maxvalue: $ff -> indicates that this is a DB node. }
  883. { $ffff -> indicates that this is a DW node. }
  884. { $ffffffff -> indicates that this is a DD node. }
  885. {*********************************************************************}
  886. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  887. {*********************************************************************}
  888. var
  889. strlength: byte;
  890. expr: string;
  891. tempstr: string;
  892. value : longint;
  893. Begin
  894. Repeat
  895. Case actasmtoken of
  896. AS_STRING: Begin
  897. if maxvalue = $ff then
  898. strlength := 1
  899. else
  900. Message(asmr_e_string_not_allowed_as_const);
  901. expr := actasmpattern;
  902. if length(expr) > 1 then
  903. Message(asmr_e_string_not_allowed_as_const);
  904. Consume(AS_STRING);
  905. Case actasmtoken of
  906. AS_COMMA: Consume(AS_COMMA);
  907. AS_SEPARATOR: ;
  908. else
  909. Message(asmr_e_invalid_string_expression);
  910. end; { end case }
  911. ConcatString(curlist,expr);
  912. end;
  913. AS_INTNUM,AS_BINNUM,
  914. AS_OCTALNUM,AS_HEXNUM:
  915. Begin
  916. value:=BuildExpression(false,nil);
  917. ConcatConstant(curlist,value,maxvalue);
  918. end;
  919. AS_ID:
  920. Begin
  921. value:=BuildExpression(false,nil);
  922. if value > maxvalue then
  923. Begin
  924. Message(asmr_e_constant_out_of_bounds);
  925. { assuming a value of maxvalue }
  926. value := maxvalue;
  927. end;
  928. ConcatConstant(curlist,value,maxvalue);
  929. end;
  930. { These terms can start an assembler expression }
  931. AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: Begin
  932. value := BuildExpression(false,nil);
  933. ConcatConstant(curlist,value,maxvalue);
  934. end;
  935. AS_COMMA: BEGIN
  936. Consume(AS_COMMA);
  937. END;
  938. AS_SEPARATOR: ;
  939. else
  940. Begin
  941. Message(asmr_e_syntax_error);
  942. end;
  943. end; { end case }
  944. Until actasmtoken = AS_SEPARATOR;
  945. end;
  946. {****************************************************************************
  947. Tm68kOperand
  948. ****************************************************************************}
  949. type
  950. TM68kOperand=class(TOperand)
  951. Procedure BuildOperand;override;
  952. private
  953. labeled : boolean;
  954. Procedure BuildReference;
  955. Function BuildRefExpression: longint;
  956. Procedure BuildScaling;
  957. end;
  958. Procedure TM68kOperand.BuildScaling;
  959. {*********************************************************************}
  960. { Takes care of parsing expression starting from the scaling value }
  961. { up to and including possible field specifiers. }
  962. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR }
  963. { or AS_COMMA. On entry should point to the AS_STAR token. }
  964. {*********************************************************************}
  965. var str:string;
  966. l: longint;
  967. code: integer;
  968. Begin
  969. Consume(AS_STAR);
  970. if (opr.ref.scalefactor <> 0)
  971. and (opr.ref.scalefactor <> 1) then
  972. Message(asmr_e_wrong_base_index);
  973. case actasmtoken of
  974. AS_INTNUM: str := actasmpattern;
  975. AS_HEXNUM: str := Tostr(ValHexadecimal(actasmpattern));
  976. AS_BINNUM: str := Tostr(ValBinary(actasmpattern));
  977. AS_OCTALNUM: str := Tostr(ValOctal(actasmpattern));
  978. else
  979. Message(asmr_e_syntax_error);
  980. end;
  981. val(str, l, code);
  982. if code <> 0 then
  983. Message(asmr_e_wrong_scale_factor);
  984. if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
  985. begin
  986. opr.ref.scalefactor := l;
  987. end
  988. else
  989. Begin
  990. Message(asmr_e_wrong_scale_factor);
  991. opr.ref.scalefactor := 0;
  992. end;
  993. if opr.ref.index = R_NO then
  994. Begin
  995. Message(asmr_e_wrong_base_index);
  996. opr.ref.scalefactor := 0;
  997. end;
  998. { Consume the scaling number }
  999. Consume(actasmtoken);
  1000. if actasmtoken = AS_RPAREN then
  1001. Consume(AS_RPAREN)
  1002. else
  1003. Message(asmr_e_wrong_scale_factor);
  1004. { // .Field.Field ... or separator/comma // }
  1005. if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
  1006. Begin
  1007. end
  1008. else
  1009. Message(asmr_e_syntax_error);
  1010. end;
  1011. Function TM68kOperand.BuildRefExpression: longint;
  1012. {*********************************************************************}
  1013. { FUNCTION BuildRefExpression: longint }
  1014. { Description: This routine calculates a constant expression to }
  1015. { a given value. The return value is the value calculated from }
  1016. { the expression. }
  1017. { The following tokens (not strings) are recognized: }
  1018. { SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
  1019. {*********************************************************************}
  1020. { ENTRY: On entry the token should be any valid expression token. }
  1021. { EXIT: On Exit the token points to the LPAREN token. }
  1022. { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  1023. { invalid tokens. }
  1024. {*********************************************************************}
  1025. var tempstr: string;
  1026. expr: string;
  1027. l : longint;
  1028. errorflag : boolean;
  1029. Begin
  1030. errorflag := FALSE;
  1031. tempstr := '';
  1032. expr := '';
  1033. Repeat
  1034. Case actasmtoken of
  1035. AS_RPAREN: Begin
  1036. Message(asmr_e_syntax_error);
  1037. Consume(AS_RPAREN);
  1038. end;
  1039. AS_SHL: Begin
  1040. Consume(AS_SHL);
  1041. expr := expr + '<';
  1042. end;
  1043. AS_SHR: Begin
  1044. Consume(AS_SHR);
  1045. expr := expr + '>';
  1046. end;
  1047. AS_SLASH: Begin
  1048. Consume(AS_SLASH);
  1049. expr := expr + '/';
  1050. end;
  1051. AS_MOD: Begin
  1052. Consume(AS_MOD);
  1053. expr := expr + '%';
  1054. end;
  1055. AS_STAR: Begin
  1056. Consume(AS_STAR);
  1057. expr := expr + '*';
  1058. end;
  1059. AS_PLUS: Begin
  1060. Consume(AS_PLUS);
  1061. expr := expr + '+';
  1062. end;
  1063. AS_MINUS: Begin
  1064. Consume(AS_MINUS);
  1065. expr := expr + '-';
  1066. end;
  1067. AS_AND: Begin
  1068. Consume(AS_AND);
  1069. expr := expr + '&';
  1070. end;
  1071. AS_NOT: Begin
  1072. Consume(AS_NOT);
  1073. expr := expr + '~';
  1074. end;
  1075. AS_XOR: Begin
  1076. Consume(AS_XOR);
  1077. expr := expr + '^';
  1078. end;
  1079. AS_OR: Begin
  1080. Consume(AS_OR);
  1081. expr := expr + '|';
  1082. end;
  1083. { End of reference }
  1084. AS_LPAREN: Begin
  1085. if not ErrorFlag then
  1086. BuildRefExpression := CalculateExpression(expr)
  1087. else
  1088. BuildRefExpression := 0;
  1089. { no longer in an expression }
  1090. exit;
  1091. end;
  1092. AS_ID:
  1093. Begin
  1094. if NOT SearchIConstant(actasmpattern,l) then
  1095. Begin
  1096. Message(asmr_e_syn_constant);
  1097. l := 0;
  1098. end;
  1099. str(l, tempstr);
  1100. expr := expr + tempstr;
  1101. Consume(AS_ID);
  1102. end;
  1103. AS_INTNUM: Begin
  1104. expr := expr + actasmpattern;
  1105. Consume(AS_INTNUM);
  1106. end;
  1107. AS_BINNUM: Begin
  1108. tempstr := Tostr(ValBinary(actasmpattern));
  1109. if tempstr = '' then
  1110. Message(asmr_e_error_converting_binary);
  1111. expr:=expr+tempstr;
  1112. Consume(AS_BINNUM);
  1113. end;
  1114. AS_HEXNUM: Begin
  1115. tempstr := Tostr(ValHexadecimal(actasmpattern));
  1116. if tempstr = '' then
  1117. Message(asmr_e_error_converting_hexadecimal);
  1118. expr:=expr+tempstr;
  1119. Consume(AS_HEXNUM);
  1120. end;
  1121. AS_OCTALNUM: Begin
  1122. tempstr := Tostr(ValOctal(actasmpattern));
  1123. if tempstr = '' then
  1124. Message(asmr_e_error_converting_octal);
  1125. expr:=expr+tempstr;
  1126. Consume(AS_OCTALNUM);
  1127. end;
  1128. else
  1129. Begin
  1130. { write error only once. }
  1131. if not errorflag then
  1132. Message(asmr_e_invalid_constant_expression);
  1133. BuildRefExpression := 0;
  1134. if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
  1135. { consume tokens until we find COMMA or SEPARATOR }
  1136. Consume(actasmtoken);
  1137. errorflag := TRUE;
  1138. end;
  1139. end;
  1140. Until false;
  1141. end;
  1142. Procedure TM68kOperand.BuildReference;
  1143. {*********************************************************************}
  1144. { PROCEDURE BuildBracketExpression }
  1145. { Description: This routine builds up an expression after a LPAREN }
  1146. { token is encountered. }
  1147. { On entry actasmtoken should be equal to AS_LPAREN }
  1148. {*********************************************************************}
  1149. { EXIT CONDITION: On exit the routine should point to either the }
  1150. { AS_COMMA or AS_SEPARATOR token. }
  1151. {*********************************************************************}
  1152. var
  1153. l:longint;
  1154. code: integer;
  1155. str: string;
  1156. Begin
  1157. Consume(AS_LPAREN);
  1158. Case actasmtoken of
  1159. { // (reg ... // }
  1160. AS_REGISTER: Begin
  1161. opr.ref.base := findregister(actasmpattern);
  1162. Consume(AS_REGISTER);
  1163. { can either be a register or a right parenthesis }
  1164. { // (reg) // }
  1165. { // (reg)+ // }
  1166. if actasmtoken=AS_RPAREN then
  1167. Begin
  1168. Consume(AS_RPAREN);
  1169. if actasmtoken = AS_PLUS then
  1170. Begin
  1171. if (opr.ref.direction <> dir_none) then
  1172. Message(asmr_e_no_inc_and_dec_together)
  1173. else
  1174. opr.ref.direction := dir_inc;
  1175. Consume(AS_PLUS);
  1176. end;
  1177. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1178. Begin
  1179. Message(asmr_e_invalid_reference_syntax);
  1180. { error recovery ... }
  1181. while actasmtoken <> AS_SEPARATOR do
  1182. Consume(actasmtoken);
  1183. end;
  1184. exit;
  1185. end;
  1186. { // (reg,reg .. // }
  1187. Consume(AS_COMMA);
  1188. if actasmtoken = AS_REGISTER then
  1189. Begin
  1190. opr.ref.index :=
  1191. findregister(actasmpattern);
  1192. Consume(AS_REGISTER);
  1193. { check for scaling ... }
  1194. case actasmtoken of
  1195. AS_RPAREN:
  1196. Begin
  1197. Consume(AS_RPAREN);
  1198. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1199. Begin
  1200. { error recovery ... }
  1201. Message(asmr_e_invalid_reference_syntax);
  1202. while actasmtoken <> AS_SEPARATOR do
  1203. Consume(actasmtoken);
  1204. end;
  1205. exit;
  1206. end;
  1207. AS_STAR:
  1208. Begin
  1209. BuildScaling;
  1210. end;
  1211. else
  1212. Begin
  1213. Message(asmr_e_invalid_reference_syntax);
  1214. while (actasmtoken <> AS_SEPARATOR) do
  1215. Consume(actasmtoken);
  1216. end;
  1217. end; { end case }
  1218. end
  1219. else
  1220. Begin
  1221. Message(asmr_e_invalid_reference_syntax);
  1222. while (actasmtoken <> AS_SEPARATOR) do
  1223. Consume(actasmtoken);
  1224. end;
  1225. end;
  1226. AS_HEXNUM,AS_OCTALNUM, { direct address }
  1227. AS_BINNUM,AS_INTNUM: Begin
  1228. case actasmtoken of
  1229. AS_INTNUM: str := actasmpattern;
  1230. AS_HEXNUM: str := Tostr(ValHexadecimal(actasmpattern));
  1231. AS_BINNUM: str := Tostr(ValBinary(actasmpattern));
  1232. AS_OCTALNUM: str := Tostr(ValOctal(actasmpattern));
  1233. else
  1234. Message(asmr_e_syntax_error);
  1235. end;
  1236. Consume(actasmtoken);
  1237. val(str, l, code);
  1238. if code <> 0 then
  1239. Message(asmr_e_invalid_reference_syntax)
  1240. else
  1241. opr.ref.offset := l;
  1242. Consume(AS_RPAREN);
  1243. if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1244. Begin
  1245. { error recovery ... }
  1246. Message(asmr_e_invalid_reference_syntax);
  1247. while actasmtoken <> AS_SEPARATOR do
  1248. Consume(actasmtoken);
  1249. end;
  1250. exit;
  1251. end;
  1252. else
  1253. Begin
  1254. Message(asmr_e_invalid_reference_syntax);
  1255. while (actasmtoken <> AS_SEPARATOR) do
  1256. Consume(actasmtoken);
  1257. end;
  1258. end; { end case }
  1259. end;
  1260. Procedure TM68kOperand.BuildOperand;
  1261. {*********************************************************************}
  1262. { EXIT CONDITION: On exit the routine should point to either the }
  1263. { AS_COMMA or AS_SEPARATOR token. }
  1264. {*********************************************************************}
  1265. var
  1266. tempstr: string;
  1267. expr: string;
  1268. lab: tasmlabel;
  1269. l : longint;
  1270. i: tregister;
  1271. hl: tasmlabel;
  1272. reg_one, reg_two: tregister;
  1273. reglist: set of tregister;
  1274. Begin
  1275. reglist := [];
  1276. tempstr := '';
  1277. expr := '';
  1278. case actasmtoken of
  1279. { // Memory reference // }
  1280. AS_LPAREN:
  1281. Begin
  1282. InitRef;
  1283. BuildReference;
  1284. end;
  1285. { // Constant expression // }
  1286. AS_APPT: Begin
  1287. Consume(AS_APPT);
  1288. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1289. Message(asmr_e_invalid_operand_type);
  1290. { identifiers are handled by BuildExpression }
  1291. opr.typ := OPR_CONSTANT;
  1292. opr.val :=BuildExpression(true,@tempstr);
  1293. if tempstr<>'' then
  1294. begin
  1295. l:=opr.val;
  1296. opr.typ := OPR_SYMBOL;
  1297. opr.symofs := l;
  1298. opr.symbol := objectlibrary.newasmsymbol(tempstr);
  1299. end;
  1300. end;
  1301. { // Constant memory offset . // }
  1302. { // This must absolutely be followed by ( // }
  1303. AS_HEXNUM,AS_INTNUM,
  1304. AS_BINNUM,AS_OCTALNUM,AS_PLUS:
  1305. Begin
  1306. InitRef;
  1307. opr.ref.offset:=BuildRefExpression;
  1308. BuildReference;
  1309. end;
  1310. { // A constant expression, or a Variable ref. // }
  1311. AS_ID: Begin
  1312. InitRef;
  1313. if actasmpattern[1] = '@' then
  1314. { // Label or Special symbol reference // }
  1315. Begin
  1316. if actasmpattern = '@RESULT' then
  1317. SetUpResult
  1318. else
  1319. if actasmpattern = 'SELF' then
  1320. SetUpSelf
  1321. else
  1322. if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
  1323. Message(asmr_w_CODE_and_DATA_not_supported)
  1324. else
  1325. Begin
  1326. delete(actasmpattern,1,1);
  1327. if actasmpattern = '' then
  1328. Message(asmr_e_null_label_ref_not_allowed);
  1329. CreateLocalLabel(actasmpattern,lab,false);
  1330. opr.typ := OPR_SYMBOL;
  1331. opr.symbol := lab;
  1332. opr.symofs := 0;
  1333. labeled := TRUE;
  1334. end;
  1335. Consume(AS_ID);
  1336. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1337. Message(asmr_e_syntax_error);
  1338. end
  1339. { probably a variable or normal expression }
  1340. { or a procedure (such as in CALL ID) }
  1341. else
  1342. Begin
  1343. { is it a constant ? }
  1344. if SearchIConstant(actasmpattern,l) then
  1345. Begin
  1346. InitRef;
  1347. opr.ref.offset:=BuildRefExpression;
  1348. BuildReference;
  1349. end
  1350. else { is it a label variable ? }
  1351. Begin
  1352. { // ID[ , ID.Field.Field or simple ID // }
  1353. { check if this is a label, if so then }
  1354. { emit it as a label. }
  1355. if SearchLabel(actasmpattern,hl,false) then
  1356. Begin
  1357. opr.typ := OPR_SYMBOL;
  1358. opr.symbol := hl;
  1359. opr.symofs := 0;
  1360. labeled := TRUE;
  1361. Consume(AS_ID);
  1362. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1363. Message(asmr_e_syntax_error);
  1364. end
  1365. else
  1366. { is it a normal variable ? }
  1367. if (cs_compilesystem in aktmoduleswitches) then
  1368. begin
  1369. if not SetupDirectVar(expr) then
  1370. Begin
  1371. { not found, finally ... add it anyways ... }
  1372. Message1(asmr_w_id_supposed_external,expr);
  1373. opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
  1374. end;
  1375. end
  1376. else
  1377. Message1(sym_e_unknown_id,actasmpattern);
  1378. end;
  1379. expr := actasmpattern;
  1380. Consume(AS_ID);
  1381. case actasmtoken of
  1382. AS_LPAREN: { indexing }
  1383. BuildReference;
  1384. AS_SEPARATOR,AS_COMMA: ;
  1385. else
  1386. Message(asmr_e_syntax_error);
  1387. end;
  1388. end;
  1389. end;
  1390. { // Pre-decrement mode reference or constant mem offset. // }
  1391. AS_MINUS: Begin
  1392. Consume(AS_MINUS);
  1393. if actasmtoken = AS_LPAREN then
  1394. Begin
  1395. InitRef;
  1396. { indicate pre-decrement mode }
  1397. opr.ref.direction := dir_dec;
  1398. BuildReference;
  1399. end
  1400. else
  1401. if actasmtoken in [AS_OCTALNUM,AS_HEXNUM,AS_BINNUM,AS_INTNUM] then
  1402. Begin
  1403. InitRef;
  1404. opr.ref.offset:=BuildRefExpression;
  1405. { negate because was preceded by a negative sign! }
  1406. opr.ref.offset:=-opr.ref.offset;
  1407. BuildReference;
  1408. end
  1409. else
  1410. Begin
  1411. Message(asmr_e_syntax_error);
  1412. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1413. Consume(actasmtoken);
  1414. end;
  1415. end;
  1416. { // Register, a variable reference or a constant reference // }
  1417. AS_REGISTER: Begin
  1418. { save the type of register used. }
  1419. tempstr := actasmpattern;
  1420. Consume(AS_REGISTER);
  1421. { // Simple register // }
  1422. if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
  1423. Begin
  1424. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1425. Message(asmr_e_invalid_operand_type);
  1426. opr.typ := OPR_REGISTER;
  1427. opr.reg := findregister(tempstr);
  1428. end
  1429. else
  1430. { HERE WE MUST HANDLE THE SPECIAL CASE OF MOVEM AND FMOVEM }
  1431. { // Individual register listing // }
  1432. if (actasmtoken = AS_SLASH) then
  1433. Begin
  1434. reglist := [findregister(tempstr)];
  1435. Consume(AS_SLASH);
  1436. if actasmtoken = AS_REGISTER then
  1437. Begin
  1438. While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1439. Begin
  1440. case actasmtoken of
  1441. AS_REGISTER: Begin
  1442. reglist := reglist + [findregister(actasmpattern)];
  1443. Consume(AS_REGISTER);
  1444. end;
  1445. AS_SLASH: Consume(AS_SLASH);
  1446. AS_SEPARATOR,AS_COMMA: break;
  1447. else
  1448. Begin
  1449. Message(asmr_e_invalid_reg_list_in_movem);
  1450. Consume(actasmtoken);
  1451. end;
  1452. end; { end case }
  1453. end; { end while }
  1454. opr.typ:= OPR_REGLIST;
  1455. opr.reglist := reglist;
  1456. end
  1457. else
  1458. { error recovery ... }
  1459. Begin
  1460. Message(asmr_e_invalid_reg_list_in_movem);
  1461. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1462. Consume(actasmtoken);
  1463. end;
  1464. end
  1465. else
  1466. { // Range register listing // }
  1467. if (actasmtoken = AS_MINUS) then
  1468. Begin
  1469. Consume(AS_MINUS);
  1470. reg_one:=findregister(tempstr);
  1471. if actasmtoken <> AS_REGISTER then
  1472. Begin
  1473. Message(asmr_e_invalid_reg_list_in_movem);
  1474. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1475. Consume(actasmtoken);
  1476. end
  1477. else
  1478. Begin
  1479. { determine the register range ... }
  1480. reg_two:=findregister(actasmpattern);
  1481. if reg_one > reg_two then
  1482. begin
  1483. for i:=reg_two to reg_one do
  1484. reglist := reglist + [i];
  1485. end
  1486. else
  1487. Begin
  1488. for i:=reg_one to reg_two do
  1489. reglist := reglist + [i];
  1490. end;
  1491. Consume(AS_REGISTER);
  1492. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1493. Begin
  1494. Message(asmr_e_invalid_reg_list_in_movem);
  1495. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1496. Consume(actasmtoken);
  1497. end;
  1498. { set up instruction }
  1499. opr.typ:= OPR_REGLIST;
  1500. opr.reglist := reglist;
  1501. end;
  1502. end
  1503. else
  1504. { DIVSL/DIVS/MULS/MULU with long for MC68020 only }
  1505. if (actasmtoken = AS_COLON) then
  1506. Begin
  1507. if (aktoptprocessor = MC68020) or (cs_compilesystem in aktmoduleswitches) then
  1508. Begin
  1509. Consume(AS_COLON);
  1510. if (actasmtoken = AS_REGISTER) then
  1511. Begin
  1512. { set up old field, since register is valid }
  1513. opr.typ := OPR_REGISTER;
  1514. opr.reg := findregister(tempstr);
  1515. Inc(operandnum);
  1516. opr.typ := OPR_REGISTER;
  1517. opr.reg := findregister(actasmpattern);
  1518. Consume(AS_REGISTER);
  1519. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1520. Begin
  1521. Message(asmr_e_invalid_reg_list_for_opcode);
  1522. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1523. Consume(actasmtoken);
  1524. end;
  1525. end;
  1526. end
  1527. else
  1528. Begin
  1529. Message(asmr_e_68020_mode_required);
  1530. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1531. Begin
  1532. Message(asmr_e_invalid_reg_list_for_opcode);
  1533. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1534. Consume(actasmtoken);
  1535. end;
  1536. end;
  1537. end
  1538. else
  1539. Message(asmr_e_invalid_register);
  1540. end;
  1541. AS_SEPARATOR, AS_COMMA: ;
  1542. else
  1543. Begin
  1544. Message(asmr_e_invalid_opcode_and_operand);
  1545. Consume(actasmtoken);
  1546. end;
  1547. end; { end case }
  1548. end;
  1549. Procedure BuildStringConstant(asciiz: boolean);
  1550. {*********************************************************************}
  1551. { PROCEDURE BuildStringConstant }
  1552. { Description: Takes care of a ASCII, or ASCIIZ directive. }
  1553. { asciiz: boolean -> if true then string will be null terminated. }
  1554. {*********************************************************************}
  1555. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1556. { On ENTRY: Token should point to AS_STRING }
  1557. {*********************************************************************}
  1558. var
  1559. expr: string;
  1560. errorflag : boolean;
  1561. Begin
  1562. errorflag := FALSE;
  1563. Repeat
  1564. Case actasmtoken of
  1565. AS_STRING: Begin
  1566. expr:=actasmpattern;
  1567. if asciiz then
  1568. expr:=expr+#0;
  1569. ConcatPasString(curlist,expr);
  1570. Consume(AS_STRING);
  1571. end;
  1572. AS_COMMA: BEGIN
  1573. Consume(AS_COMMA);
  1574. END;
  1575. AS_SEPARATOR: ;
  1576. else
  1577. Begin
  1578. Consume(actasmtoken);
  1579. if not errorflag then
  1580. Message(asmr_e_invalid_string_expression);
  1581. errorflag := TRUE;
  1582. end;
  1583. end; { end case }
  1584. Until actasmtoken = AS_SEPARATOR;
  1585. end;
  1586. {*****************************************************************************
  1587. TM68kInstruction
  1588. *****************************************************************************}
  1589. type
  1590. TM68kInstruction=class(TInstruction)
  1591. procedure InitOperands;override;
  1592. procedure BuildOpcode;override;
  1593. procedure ConcatInstruction(p : taasmoutput);override;
  1594. Procedure ConcatLabeledInstr(p : taasmoutput);
  1595. end;
  1596. procedure TM68kInstruction.InitOperands;
  1597. var
  1598. i : longint;
  1599. begin
  1600. for i:=1to max_operands do
  1601. Operands[i]:=TM68kOperand.Create;
  1602. end;
  1603. Procedure TM68kInstruction.BuildOpCode;
  1604. {*********************************************************************}
  1605. { PROCEDURE BuildOpcode; }
  1606. { Description: Parses the intel opcode and operands, and writes it }
  1607. { in the TInstruction object. }
  1608. {*********************************************************************}
  1609. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1610. { On ENTRY: Token should point to AS_OPCODE }
  1611. {*********************************************************************}
  1612. var asmtok: tasmop;
  1613. expr: string;
  1614. operandnum : longint;
  1615. Begin
  1616. expr := '';
  1617. asmtok := A_NONE; { assmume no prefix }
  1618. { // opcode // }
  1619. { allow for newline as in gas styled syntax }
  1620. { under DOS you get two AS_SEPARATOR !! }
  1621. while actasmtoken=AS_SEPARATOR do
  1622. Consume(AS_SEPARATOR);
  1623. if (actasmtoken <> AS_OPCODE) then
  1624. Begin
  1625. Message(asmr_e_invalid_or_missing_opcode);
  1626. { error recovery }
  1627. While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1628. Consume(actasmtoken);
  1629. exit;
  1630. end
  1631. else
  1632. Begin
  1633. opcode := findopcode(actasmpattern,opsize);
  1634. Consume(AS_OPCODE);
  1635. { // Zero operand opcode ? // }
  1636. if actasmtoken = AS_SEPARATOR then
  1637. exit
  1638. else
  1639. operandnum := 1;
  1640. end;
  1641. While actasmtoken <> AS_SEPARATOR do
  1642. Begin
  1643. case actasmtoken of
  1644. { // Operand delimiter // }
  1645. AS_COMMA: Begin
  1646. if operandnum > MaxOperands then
  1647. Message(asmr_e_too_many_operands)
  1648. else
  1649. Inc(operandnum);
  1650. Consume(AS_COMMA);
  1651. end;
  1652. { // End of asm operands for this opcode // }
  1653. AS_SEPARATOR: ;
  1654. else
  1655. Operands[operandnum].BuildOperand;
  1656. end; { end case }
  1657. end; { end while }
  1658. end;
  1659. procedure TM68kInstruction.ConcatInstruction(p : taasmoutput);
  1660. var
  1661. fits : boolean;
  1662. Begin
  1663. fits := FALSE;
  1664. { setup specific opcodetions for first pass }
  1665. { Setup special operands }
  1666. { Convert to general form as to conform to the m68k opcode table }
  1667. if (opcode = A_ADDA) or (opcode = A_ADDI)
  1668. then opcode := A_ADD
  1669. else
  1670. { CMPM excluded because of GAS v1.34 BUG }
  1671. if (opcode = A_CMPA) or
  1672. (opcode = A_CMPI) then
  1673. opcode := A_CMP
  1674. else
  1675. if opcode = A_EORI then
  1676. opcode := A_EOR
  1677. else
  1678. if opcode = A_MOVEA then
  1679. opcode := A_MOVE
  1680. else
  1681. if opcode = A_ORI then
  1682. opcode := A_OR
  1683. else
  1684. if (opcode = A_SUBA) or (opcode = A_SUBI) then
  1685. opcode := A_SUB;
  1686. { Setup operand types }
  1687. (*
  1688. in opcode <> A_MOVEM then
  1689. Begin
  1690. while not(fits) do
  1691. begin
  1692. { set the opcodetion cache, if the opcodetion }
  1693. { occurs the first time }
  1694. if (it[i].i=opcode) and (ins_cache[opcode]=-1) then
  1695. ins_cache[opcode]:=i;
  1696. if (it[i].i=opcode) and (instr.ops=it[i].ops) then
  1697. begin
  1698. { first fit }
  1699. case instr.ops of
  1700. 0 : begin
  1701. fits:=true;
  1702. break;
  1703. end;
  1704. 1 :
  1705. Begin
  1706. if (optyp1 and it[i].o1)<>0 then
  1707. Begin
  1708. fits:=true;
  1709. break;
  1710. end;
  1711. end;
  1712. 2 : if ((optyp1 and it[i].o1)<>0) and
  1713. ((optyp2 and it[i].o2)<>0) then
  1714. Begin
  1715. fits:=true;
  1716. break;
  1717. end
  1718. 3 : if ((optyp1 and it[i].o1)<>0) and
  1719. ((optyp2 and it[i].o2)<>0) and
  1720. ((optyp3 and it[i].o3)<>0) then
  1721. Begin
  1722. fits:=true;
  1723. break;
  1724. end;
  1725. end; { end case }
  1726. end; { endif }
  1727. if it[i].i=A_NONE then
  1728. begin
  1729. { NO MATCH! }
  1730. Message(asmr_e_invalid_combination_opcode_and_operand);
  1731. exit;
  1732. end;
  1733. inc(i);
  1734. end; { end while }
  1735. *)
  1736. fits:=TRUE;
  1737. { We add the opcode to the opcode linked list }
  1738. if fits then
  1739. Begin
  1740. case ops of
  1741. 0:
  1742. if opsize <> S_NO then
  1743. p.concat((taicpu.op_none(opcode,opsize)))
  1744. else
  1745. p.concat((taicpu.op_none(opcode,S_NO)));
  1746. 1: Begin
  1747. case operands[1].opr.typ of
  1748. OPR_SYMBOL:
  1749. Begin
  1750. p.concat((taicpu.op_sym_ofs(opcode,
  1751. opsize, operands[1].opr.symbol,operands[1].opr.symofs)));
  1752. end;
  1753. OPR_CONSTANT:
  1754. Begin
  1755. p.concat((taicpu.op_const(opcode,
  1756. opsize, operands[1].opr.val)));
  1757. end;
  1758. OPR_REGISTER:
  1759. p.concat((taicpu.op_reg(opcode,opsize,operands[1].opr.reg)));
  1760. OPR_REFERENCE:
  1761. if opsize <> S_NO then
  1762. Begin
  1763. p.concat((taicpu.op_ref(opcode,
  1764. opsize,operands[1].opr.ref)));
  1765. end
  1766. else
  1767. Begin
  1768. { special jmp and call case with }
  1769. { symbolic references. }
  1770. if opcode in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then
  1771. Begin
  1772. p.concat((taicpu.op_ref(opcode,
  1773. S_NO,operands[1].opr.ref)));
  1774. end
  1775. else
  1776. Message(asmr_e_invalid_opcode_and_operand);
  1777. end;
  1778. OPR_NONE:
  1779. Message(asmr_e_invalid_opcode_and_operand);
  1780. else
  1781. Begin
  1782. Message(asmr_e_invalid_opcode_and_operand);
  1783. end;
  1784. end;
  1785. end;
  1786. 2: Begin
  1787. { source }
  1788. case operands[1].opr.typ of
  1789. { reg,reg }
  1790. { reg,ref }
  1791. OPR_REGISTER:
  1792. Begin
  1793. case operands[2].opr.typ of
  1794. OPR_REGISTER:
  1795. Begin
  1796. p.concat((taicpu.op_reg_reg(opcode,
  1797. opsize,operands[1].opr.reg,operands[2].opr.reg)));
  1798. end;
  1799. OPR_REFERENCE:
  1800. p.concat((taicpu.op_reg_ref(opcode,
  1801. opsize,operands[1].opr.reg,operands[2].opr.ref)));
  1802. else { else case }
  1803. Begin
  1804. Message(asmr_e_invalid_opcode_and_operand);
  1805. end;
  1806. end; { end second operand case for OPR_REGISTER }
  1807. end;
  1808. { reglist, ref }
  1809. OPR_REGLIST:
  1810. Begin
  1811. case operands[2].opr.typ of
  1812. OPR_REFERENCE :
  1813. p.concat((taicpu.op_reglist_ref(opcode,
  1814. opsize,operands[1].opr.reglist,operands[2].opr.ref)));
  1815. else
  1816. Begin
  1817. Message(asmr_e_invalid_opcode_and_operand);
  1818. end;
  1819. end; { end second operand case for OPR_REGLIST }
  1820. end;
  1821. { const,reg }
  1822. { const,const }
  1823. { const,ref }
  1824. OPR_CONSTANT:
  1825. case operands[2].opr.typ of
  1826. { constant, constant does not have a specific size. }
  1827. OPR_CONSTANT:
  1828. p.concat((taicpu.op_const_const(opcode,
  1829. S_NO,operands[1].opr.val,operands[2].opr.val)));
  1830. OPR_REFERENCE:
  1831. Begin
  1832. p.concat((taicpu.op_const_ref(opcode,
  1833. opsize,operands[1].opr.val,
  1834. operands[2].opr.ref)))
  1835. end;
  1836. OPR_REGISTER:
  1837. Begin
  1838. p.concat((taicpu.op_const_reg(opcode,
  1839. opsize,operands[1].opr.val,
  1840. operands[2].opr.reg)))
  1841. end;
  1842. else
  1843. Begin
  1844. Message(asmr_e_invalid_opcode_and_operand);
  1845. end;
  1846. end; { end second operand case for OPR_CONSTANT }
  1847. { ref,reg }
  1848. { ref,ref }
  1849. OPR_REFERENCE:
  1850. case operands[2].opr.typ of
  1851. OPR_REGISTER:
  1852. Begin
  1853. p.concat((taicpu.op_ref_reg(opcode,
  1854. opsize,operands[1].opr.ref,
  1855. operands[2].opr.reg)));
  1856. end;
  1857. OPR_REGLIST:
  1858. Begin
  1859. p.concat((taicpu.op_ref_reglist(opcode,
  1860. opsize,operands[1].opr.ref,
  1861. operands[2].opr.reglist)));
  1862. end;
  1863. OPR_REFERENCE: { special opcodes }
  1864. p.concat((taicpu.op_ref_ref(opcode,
  1865. opsize,operands[1].opr.ref,
  1866. operands[2].opr.ref)));
  1867. else
  1868. Begin
  1869. Message(asmr_e_invalid_opcode_and_operand);
  1870. end;
  1871. end; { end second operand case for OPR_REFERENCE }
  1872. OPR_SYMBOL: case operands[2].opr.typ of
  1873. OPR_REFERENCE:
  1874. Begin
  1875. p.concat((taicpu.op_sym_ofs_ref(opcode,
  1876. opsize,operands[1].opr.symbol,operands[1].opr.symofs,
  1877. operands[2].opr.ref)))
  1878. end;
  1879. OPR_REGISTER:
  1880. Begin
  1881. p.concat((taicpu.op_sym_ofs_reg(opcode,
  1882. opsize,operands[1].opr.symbol,operands[1].opr.symofs,
  1883. operands[2].opr.reg)))
  1884. end;
  1885. else
  1886. Begin
  1887. Message(asmr_e_invalid_opcode_and_operand);
  1888. end;
  1889. end; { end second operand case for OPR_SYMBOL }
  1890. else
  1891. Begin
  1892. Message(asmr_e_invalid_opcode_and_operand);
  1893. end;
  1894. end; { end first operand case }
  1895. end;
  1896. 3: Begin
  1897. if (opcode = A_DIVSL) or (opcode = A_DIVUL) or (opcode = A_MULU)
  1898. or (opcode = A_MULS) or (opcode = A_DIVS) or (opcode = A_DIVU) then
  1899. Begin
  1900. if (operands[1].opr.typ <> OPR_REGISTER)
  1901. or (operands[2].opr.typ <> OPR_REGISTER)
  1902. or (operands[3].opr.typ <> OPR_REGISTER) then
  1903. Begin
  1904. Message(asmr_e_invalid_opcode_and_operand);
  1905. end
  1906. else
  1907. Begin
  1908. p.concat((taicpu. op_reg_reg_reg(opcode,opsize,
  1909. operands[1].opr.reg,operands[2].opr.reg,operands[3].opr.reg)));
  1910. end;
  1911. end
  1912. else
  1913. Message(asmr_e_invalid_opcode_and_operand);
  1914. end;
  1915. end; { end case }
  1916. end;
  1917. end;
  1918. Procedure TM68kInstruction.ConcatLabeledInstr(p : taasmoutput);
  1919. Begin
  1920. if ((opcode >= A_BCC) and (opcode <= A_BVS))
  1921. or (opcode = A_BRA) or (opcode = A_BSR)
  1922. or (opcode = A_JMP) or (opcode = A_JSR)
  1923. or ((opcode >= A_FBEQ) and (opcode <= A_FBNGLE))
  1924. then
  1925. Begin
  1926. if ops > 2 then
  1927. Message(asmr_e_invalid_opcode_and_operand)
  1928. else if operands[1].opr.typ <> OPR_SYMBOL then
  1929. Message(asmr_e_invalid_opcode_and_operand)
  1930. else if (operands[1].opr.typ = OPR_SYMBOL) and
  1931. (ops = 1) then
  1932. if assigned(operands[1].opr.symbol) and
  1933. (operands[1].opr.symofs=0) then
  1934. p.concat(taicpu.op_sym(opcode,S_NO,
  1935. operands[1].opr.symbol))
  1936. else
  1937. Message(asmr_e_invalid_opcode_and_operand);
  1938. end
  1939. else
  1940. if ((opcode >= A_DBCC) and (opcode <= A_DBF))
  1941. or ((opcode >= A_FDBEQ) and (opcode <= A_FBDNGLE)) then
  1942. begin
  1943. if (ops<>2) or
  1944. (operands[1].opr.typ <> OPR_REGISTER) or
  1945. (operands[2].opr.typ <> OPR_SYMBOL) or
  1946. (operands[2].opr.symofs <> 0) then
  1947. Message(asmr_e_invalid_opcode_and_operand)
  1948. else
  1949. p.concat(taicpu.op_reg_sym(opcode,opsize,operands[1].opr.reg,
  1950. operands[2].opr.symbol));
  1951. end
  1952. else
  1953. Message(asmr_e_invalid_opcode_and_operand);
  1954. end;
  1955. Function Assemble: tnode;
  1956. {*********************************************************************}
  1957. { PROCEDURE Assemble; }
  1958. { Description: Parses the att assembler syntax, parsing is done }
  1959. { according to GAs rules. }
  1960. {*********************************************************************}
  1961. Var
  1962. hl: tasmlabel;
  1963. labelptr,nextlabel : tasmlabel;
  1964. commname : string;
  1965. instr : TM68kInstruction;
  1966. Begin
  1967. Message(asmr_d_start_reading);
  1968. firsttoken := TRUE;
  1969. operandnum := 0;
  1970. { sets up all opcode and register tables in uppercase }
  1971. if not _asmsorted then
  1972. Begin
  1973. SetupTables;
  1974. _asmsorted := TRUE;
  1975. end;
  1976. curlist:=TAAsmoutput.Create;
  1977. { setup label linked list }
  1978. LocalLabelList:=TLocalLabelList.Create;
  1979. c:=current_scanner.asmgetchar;
  1980. actasmtoken:=gettoken;
  1981. while actasmtoken<>AS_END do
  1982. Begin
  1983. case actasmtoken of
  1984. AS_LLABEL:
  1985. Begin
  1986. if CreateLocalLabel(actasmpattern,hl,true) then
  1987. ConcatLabel(curlist,hl);
  1988. Consume(AS_LLABEL);
  1989. end;
  1990. AS_LABEL: Begin
  1991. { when looking for Pascal labels, these must }
  1992. { be in uppercase. }
  1993. if SearchLabel(upper(actasmpattern),hl,true) then
  1994. ConcatLabel(curlist,hl)
  1995. else
  1996. Begin
  1997. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1998. end;
  1999. Consume(AS_LABEL);
  2000. end;
  2001. AS_DW: Begin
  2002. Consume(AS_DW);
  2003. BuildConstant($ffff);
  2004. end;
  2005. AS_DB: Begin
  2006. Consume(AS_DB);
  2007. BuildConstant($ff);
  2008. end;
  2009. AS_DD: Begin
  2010. Consume(AS_DD);
  2011. BuildConstant($ffffffff);
  2012. end;
  2013. AS_XDEF:
  2014. Begin
  2015. { normal units should not be able to declare }
  2016. { direct label names like this... anyhow }
  2017. { procedural calls in asm blocks are }
  2018. { supposedely replaced automatically }
  2019. if (cs_compilesystem in aktmoduleswitches) then
  2020. begin
  2021. Consume(AS_XDEF);
  2022. if actasmtoken <> AS_ID then
  2023. Message(asmr_e_invalid_global_def)
  2024. else
  2025. ConcatPublic(curlist,actasmpattern);
  2026. Consume(actasmtoken);
  2027. if actasmtoken <> AS_SEPARATOR then
  2028. Begin
  2029. Message(asmr_e_syntax_error);
  2030. while actasmtoken <> AS_SEPARATOR do
  2031. Consume(actasmtoken);
  2032. end;
  2033. end
  2034. else
  2035. begin
  2036. Message(asmr_w_xdef_not_supported);
  2037. while actasmtoken <> AS_SEPARATOR do
  2038. Consume(actasmtoken);
  2039. end;
  2040. end;
  2041. AS_ALIGN: Begin
  2042. Message(asmr_w_align_not_supported);
  2043. while actasmtoken <> AS_SEPARATOR do
  2044. Consume(actasmtoken);
  2045. end;
  2046. AS_OPCODE: Begin
  2047. instr:=TM68kInstruction.Create;
  2048. instr.BuildOpcode;
  2049. { instr.AddReferenceSizes;}
  2050. { instr.SetInstructionOpsize;}
  2051. { instr.CheckOperandSizes;}
  2052. if instr.labeled then
  2053. instr.ConcatLabeledInstr(curlist)
  2054. else
  2055. instr.ConcatInstruction(curlist);
  2056. instr.Free;
  2057. {
  2058. instr.init;
  2059. BuildOpcode;
  2060. instr.ops := operandnum;
  2061. if instr.labeled then
  2062. ConcatLabeledInstr(instr)
  2063. else
  2064. ConcatOpCode(instr);
  2065. instr.done;}
  2066. end;
  2067. AS_SEPARATOR:Begin
  2068. Consume(AS_SEPARATOR);
  2069. { let us go back to the first operand }
  2070. operandnum := 0;
  2071. end;
  2072. AS_END: ; { end assembly block }
  2073. else
  2074. Begin
  2075. Message(asmr_e_syntax_error);
  2076. { error recovery }
  2077. Consume(actasmtoken);
  2078. end;
  2079. end; { end case }
  2080. end; { end while }
  2081. { Check LocalLabelList }
  2082. LocalLabelList.CheckEmitted;
  2083. LocalLabelList.Free;
  2084. { Return the list in an asmnode }
  2085. assemble:=casmnode.create(curlist);
  2086. Message(asmr_d_finish_reading);
  2087. end;
  2088. procedure ra68kmot_exit;{$ifndef FPC}far;{$endif}
  2089. begin
  2090. if assigned(iasmops) then
  2091. dispose(iasmops);
  2092. exitproc:=old_exit;
  2093. end;
  2094. Begin
  2095. old_exit:=exitproc;
  2096. exitproc:=@ra68kmot_exit;
  2097. end.
  2098. {
  2099. $Log$
  2100. Revision 1.5 2002-08-13 18:01:52 carl
  2101. * rename swatoperands to swapoperands
  2102. + m68k first compilable version (still needs a lot of testing):
  2103. assembler generator, system information , inline
  2104. assembler reader.
  2105. Revision 1.4 2002/08/12 15:08:44 carl
  2106. + stab register indexes for powerpc (moved from gdb to cpubase)
  2107. + tprocessor enumeration moved to cpuinfo
  2108. + linker in target_info is now a class
  2109. * many many updates for m68k (will soon start to compile)
  2110. - removed some ifdef or correct them for correct cpu
  2111. Revision 1.3 2002/08/11 14:32:32 peter
  2112. * renamed current_library to objectlibrary
  2113. Revision 1.2 2002/08/11 13:24:18 peter
  2114. * saving of asmsymbols in ppu supported
  2115. * asmsymbollist global is removed and moved into a new class
  2116. tasmlibrarydata that will hold the info of a .a file which
  2117. corresponds with a single module. Added librarydata to tmodule
  2118. to keep the library info stored for the module. In the future the
  2119. objectfiles will also be stored to the tasmlibrarydata class
  2120. * all getlabel/newasmsymbol and friends are moved to the new class
  2121. Revision 1.1 2002/08/06 15:15:42 carl
  2122. + more m68k fixes
  2123. Revision 1.1.2.7 2001/08/09 11:41:08 pierre
  2124. + add more errors
  2125. Revision 1.1.2.6 2001/08/08 12:21:49 pierre
  2126. * generate correct labeled instruction for DBRA
  2127. * improoved checking of operands
  2128. + support for OPR_SYMBOL in generic instructions like MOVE
  2129. + support for labels in constants like movel #datalabel + const,d0
  2130. Revision 1.1.2.5 2001/08/07 15:55:33 pierre
  2131. + new code for NetBSD, behaves like FreeBSD for now
  2132. Revision 1.1.2.4 2001/08/01 10:58:50 pierre
  2133. * avoid warning about supposed external in asm label is already known
  2134. Revision 1.1.2.3 2001/07/24 23:41:32 pierre
  2135. * firstreg and lastreg renamed firstasmreg and lastasmreg to aviod confusions
  2136. Revision 1.1.2.2 2001/04/24 11:58:37 carl
  2137. * correction of DBRA problems
  2138. Revision 1.1.2.1 2001/03/04 02:19:54 carl
  2139. - renamefest!
  2140. Revision 1.1.2.1 2001/02/25 01:32:56 carl
  2141. - imported from mian directory
  2142. Revision 1.1.2.2 2001/02/23 11:20:40 pierre
  2143. * fix an update problem
  2144. Revision 1.1.2.1 2001/02/23 10:05:19 pierre
  2145. * first bunch of m68k cpu updates
  2146. Revision 1.1 2000/07/13 06:29:56 michael
  2147. + Initial import
  2148. Revision 1.13 2000/02/09 13:23:02 peter
  2149. * log truncated
  2150. Revision 1.12 2000/01/07 01:14:37 peter
  2151. * updated copyright to 2000
  2152. Revision 1.11 1999/11/10 00:06:08 pierre
  2153. * adapted to procinfo as pointer
  2154. Revision 1.10 1999/11/09 23:06:46 peter
  2155. * esi_offset -> selfpointer_offset to be newcg compatible
  2156. * hcogegen -> cgbase fixes for newcg
  2157. Revision 1.9 1999/09/16 23:05:56 florian
  2158. * m68k compiler is again compilable (only gas writer, no assembler reader)
  2159. }