ra68kmot.pas 81 KB

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