ra68kmot.pas 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239
  1. {
  2. $Id$
  3. Copyright (c) 1997-98 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. m68k,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,AsmUtils,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 = ' ') or (c = #9) do
  203. begin
  204. c := asmgetchar;
  205. end;
  206. { Possiblities for first token in a statement: }
  207. { Local Label, Label, Directive, Prefix or Opcode.... }
  208. tokenpos.line:=current_module^.current_inputfile^.line_no;
  209. tokenpos.column:=get_file_col;
  210. tokenpos.fileindex:=current_module^.current_index;
  211. if firsttoken and not (c in [newline,#13,'{',';']) then
  212. begin
  213. firsttoken := FALSE;
  214. if c = '@' then
  215. begin
  216. token := AS_LLABEL; { this is a local label }
  217. { Let us point to the next character }
  218. c := asmgetchar;
  219. end;
  220. while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
  221. begin
  222. { if there is an at_sign, then this must absolutely be a label }
  223. if c = '@' then forcelabel:=TRUE;
  224. actasmpattern := actasmpattern + c;
  225. c := asmgetchar;
  226. end;
  227. uppervar(actasmpattern);
  228. if c = ':' then
  229. begin
  230. case token of
  231. AS_NONE: token := AS_LABEL;
  232. AS_LLABEL: ; { do nothing }
  233. end; { end case }
  234. { let us point to the next character }
  235. c := asmgetchar;
  236. gettoken := token;
  237. exit;
  238. end;
  239. { Are we trying to create an identifier with }
  240. { an at-sign...? }
  241. if forcelabel then
  242. Message(assem_e_none_label_contain_at);
  243. If is_asmopcode(actasmpattern) then
  244. Begin
  245. gettoken := AS_OPCODE;
  246. exit;
  247. end;
  248. is_asmdirective(actasmpattern, token);
  249. if (token <> AS_NONE) then
  250. Begin
  251. gettoken := token;
  252. exit
  253. end
  254. else
  255. begin
  256. gettoken := AS_NONE;
  257. Message1(assem_e_invalid_operand,actasmpattern);
  258. end;
  259. end
  260. else { else firsttoken }
  261. { Here we must handle all possible cases }
  262. begin
  263. case c of
  264. '@': { possiblities : - local label reference , such as in jmp @local1 }
  265. { - @Result, @Code or @Data special variables. }
  266. begin
  267. actasmpattern := c;
  268. c:= asmgetchar;
  269. while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
  270. begin
  271. actasmpattern := actasmpattern + c;
  272. c := asmgetchar;
  273. end;
  274. uppervar(actasmpattern);
  275. gettoken := AS_ID;
  276. exit;
  277. end;
  278. { identifier, register, opcode, prefix or directive }
  279. 'A'..'Z','a'..'z','_': begin
  280. actasmpattern := c;
  281. c:= asmgetchar;
  282. while c in ['A'..'Z','a'..'z','0'..'9','_','.'] do
  283. begin
  284. actasmpattern := actasmpattern + c;
  285. c := asmgetchar;
  286. end;
  287. uppervar(actasmpattern);
  288. If is_asmopcode(actasmpattern) then
  289. Begin
  290. gettoken := AS_OPCODE;
  291. exit;
  292. end;
  293. is_register(actasmpattern, token);
  294. {is_asmoperator(actasmpattern,token);}
  295. is_asmdirective(actasmpattern,token);
  296. { if found }
  297. if (token <> AS_NONE) then
  298. begin
  299. gettoken := token;
  300. exit;
  301. end
  302. { this is surely an identifier }
  303. else
  304. token := AS_ID;
  305. gettoken := token;
  306. exit;
  307. end;
  308. { override operator... not supported }
  309. '&': begin
  310. c:=asmgetchar;
  311. gettoken := AS_AND;
  312. end;
  313. { string or character }
  314. '''' :
  315. begin
  316. actasmpattern:='';
  317. while true do
  318. begin
  319. if c = '''' then
  320. begin
  321. c:=asmgetchar;
  322. if c=newline then
  323. begin
  324. Message(scan_f_string_exceeds_line);
  325. break;
  326. end;
  327. repeat
  328. if c=''''then
  329. begin
  330. c:=asmgetchar;
  331. if c='''' then
  332. begin
  333. actasmpattern:=actasmpattern+'''';
  334. c:=asmgetchar;
  335. if c=newline then
  336. begin
  337. Message(scan_f_string_exceeds_line);
  338. break;
  339. end;
  340. end
  341. else break;
  342. end
  343. else
  344. begin
  345. actasmpattern:=actasmpattern+c;
  346. c:=asmgetchar;
  347. if c=newline then
  348. begin
  349. Message(scan_f_string_exceeds_line);
  350. break
  351. end;
  352. end;
  353. until false; { end repeat }
  354. end
  355. else break; { end if }
  356. end; { end while }
  357. token:=AS_STRING;
  358. gettoken := token;
  359. exit;
  360. end;
  361. '$' : begin
  362. c:=asmgetchar;
  363. while c in ['0'..'9','A'..'F','a'..'f'] do
  364. begin
  365. actasmpattern := actasmpattern + c;
  366. c := asmgetchar;
  367. end;
  368. gettoken := AS_HEXNUM;
  369. exit;
  370. end;
  371. ',' : begin
  372. gettoken := AS_COMMA;
  373. c:=asmgetchar;
  374. exit;
  375. end;
  376. '(' : begin
  377. gettoken := AS_LPAREN;
  378. c:=asmgetchar;
  379. exit;
  380. end;
  381. ')' : begin
  382. gettoken := AS_RPAREN;
  383. c:=asmgetchar;
  384. exit;
  385. end;
  386. ':' : begin
  387. gettoken := AS_COLON;
  388. c:=asmgetchar;
  389. exit;
  390. end;
  391. { '.' : begin
  392. gettoken := AS_DOT;
  393. c:=asmgetchar;
  394. exit;
  395. end; }
  396. '+' : begin
  397. gettoken := AS_PLUS;
  398. c:=asmgetchar;
  399. exit;
  400. end;
  401. '-' : begin
  402. gettoken := AS_MINUS;
  403. c:=asmgetchar;
  404. exit;
  405. end;
  406. '*' : begin
  407. gettoken := AS_STAR;
  408. c:=asmgetchar;
  409. exit;
  410. end;
  411. '/' : begin
  412. gettoken := AS_SLASH;
  413. c:=asmgetchar;
  414. exit;
  415. end;
  416. '<' : begin
  417. c := asmgetchar;
  418. { invalid characters }
  419. if c <> '<' then
  420. Message(assem_e_invalid_char_smaller);
  421. { still assume << }
  422. gettoken := AS_SHL;
  423. c := asmgetchar;
  424. exit;
  425. end;
  426. '>' : begin
  427. c := asmgetchar;
  428. { invalid characters }
  429. if c <> '>' then
  430. Message(assem_e_invalid_char_greater);
  431. { still assume << }
  432. gettoken := AS_SHR;
  433. c := asmgetchar;
  434. exit;
  435. end;
  436. '|' : begin
  437. gettoken := AS_OR;
  438. c := asmgetchar;
  439. exit;
  440. end;
  441. '^' : begin
  442. gettoken := AS_XOR;
  443. c := asmgetchar;
  444. exit;
  445. end;
  446. '#' : begin
  447. gettoken:=AS_APPT;
  448. c:=asmgetchar;
  449. exit;
  450. end;
  451. '%' : begin
  452. c:=asmgetchar;
  453. while c in ['0','1'] do
  454. Begin
  455. actasmpattern := actasmpattern + c;
  456. c := asmgetchar;
  457. end;
  458. gettoken := AS_BINNUM;
  459. exit;
  460. end;
  461. { integer number }
  462. '0'..'9': begin
  463. actasmpattern := c;
  464. c := asmgetchar;
  465. while c in ['0'..'9'] do
  466. Begin
  467. actasmpattern := actasmpattern + c;
  468. c:= asmgetchar;
  469. end;
  470. gettoken := AS_INTNUM;
  471. exit;
  472. end;
  473. ';' : begin
  474. repeat
  475. c:=asmgetchar;
  476. until c=newline;
  477. firsttoken := TRUE;
  478. gettoken:=AS_SEPARATOR;
  479. end;
  480. '{',#13,newline : begin
  481. c:=asmgetchar;
  482. firsttoken := TRUE;
  483. gettoken:=AS_SEPARATOR;
  484. end;
  485. else
  486. Begin
  487. Message(scan_f_illegal_char);
  488. end;
  489. end; { end case }
  490. end; { end else if }
  491. end;
  492. {---------------------------------------------------------------------}
  493. { Routines for the parsing }
  494. {---------------------------------------------------------------------}
  495. procedure consume(t : tmotorolatoken);
  496. begin
  497. if t<>actasmtoken then
  498. Message(assem_e_syntax_error);
  499. actasmtoken:=gettoken;
  500. { if the token must be ignored, then }
  501. { get another token to parse. }
  502. if actasmtoken = AS_NONE then
  503. actasmtoken := gettoken;
  504. end;
  505. function findregister(const s : string): tregister;
  506. {*********************************************************************}
  507. { FUNCTION findregister(s: string):tasmop; }
  508. { Description: Determines if the s string is a valid register, }
  509. { if so returns correct tregister token, or R_NO if not found. }
  510. {*********************************************************************}
  511. var
  512. i: tregister;
  513. begin
  514. findregister := R_NO;
  515. for i:=firstreg to lastreg do
  516. if s = iasmregs[i] then
  517. Begin
  518. findregister := i;
  519. exit;
  520. end;
  521. if s = 'A7' then
  522. Begin
  523. findregister := R_SP;
  524. exit;
  525. end;
  526. end;
  527. function findopcode(s: string): tasmop;
  528. {*********************************************************************}
  529. { FUNCTION findopcode(s: string): tasmop; }
  530. { Description: Determines if the s string is a valid opcode }
  531. { if so returns correct tasmop token. }
  532. {*********************************************************************}
  533. var
  534. i: tasmop;
  535. j: byte;
  536. op_size: string;
  537. Begin
  538. findopcode := A_NONE;
  539. j:=pos('.',s);
  540. if j<>0 then
  541. begin
  542. op_size:=copy(s,j+1,1);
  543. case op_size[1] of
  544. { For the motorola only stropsize size is used to }
  545. { determine the size of the operands. }
  546. 'B': instr.stropsize := S_B;
  547. 'W': instr.stropsize := S_W;
  548. 'L': instr.stropsize := S_L;
  549. 'S': instr.stropsize := S_FS;
  550. 'D': instr.stropsize := S_FL;
  551. 'X': instr.stropsize := S_FX;
  552. else
  553. Message1(assem_e_invalid_opcode,s);
  554. end;
  555. { delete everything starting from dot }
  556. delete(s,j,length(s));
  557. end;
  558. for i:=firstop to lastop do
  559. if s = iasmops^[i] then
  560. begin
  561. findopcode:=i;
  562. exit;
  563. end;
  564. end;
  565. Procedure InitAsmRef(var instr: TInstruction);
  566. {*********************************************************************}
  567. { Description: This routine first check if the instruction is of }
  568. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  569. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  570. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  571. { to point to the default segment. }
  572. {*********************************************************************}
  573. Begin
  574. With instr do
  575. Begin
  576. case operands[operandnum].operandtype of
  577. OPR_REFERENCE: exit;
  578. OPR_NONE: ;
  579. else
  580. Message(assem_e_invalid_operand_type);
  581. end;
  582. operands[operandnum].ref.direction := dir_none;
  583. operands[operandnum].operandtype := OPR_REFERENCE;
  584. operands[operandnum].ref.segment := R_DEFAULT_SEG;
  585. end;
  586. end;
  587. Function CalculateExpression(expression: string): longint;
  588. var
  589. expr: TExprParse;
  590. Begin
  591. expr.Init;
  592. CalculateExpression := expr.Evaluate(expression);
  593. expr.Done;
  594. end;
  595. Procedure ConcatOpCode(var instr: TInstruction);
  596. var
  597. fits : boolean;
  598. i: longint;
  599. opsize: topsize;
  600. optyp1, optyp2, optyp3: longint;
  601. instruc: tasmop;
  602. op: tasmop;
  603. Begin
  604. fits := FALSE;
  605. { setup specific instructions for first pass }
  606. instruc := instr.getinstruction;
  607. { Setup special operands }
  608. { Convert to general form as to conform to the m68k opcode table }
  609. if (instruc = A_ADDA) or (instruc = A_ADDI)
  610. then instruc := A_ADD
  611. else
  612. { CMPM excluded because of GAS v1.34 BUG }
  613. if (instruc = A_CMPA) or
  614. (instruc = A_CMPI) then
  615. instruc := A_CMP
  616. else
  617. if instruc = A_EORI then
  618. instruc := A_EOR
  619. else
  620. if instruc = A_MOVEA then
  621. instruc := A_MOVE
  622. else
  623. if instruc = A_ORI then
  624. instruc := A_OR
  625. else
  626. if (instruc = A_SUBA) or (instruc = A_SUBI) then
  627. instruc := A_SUB;
  628. { Setup operand types }
  629. (*
  630. in instruc <> A_MOVEM then
  631. Begin
  632. while not(fits) do
  633. begin
  634. { set the instruction cache, if the instruction }
  635. { occurs the first time }
  636. if (it[i].i=instruc) and (ins_cache[instruc]=-1) then
  637. ins_cache[instruc]:=i;
  638. if (it[i].i=instruc) and (instr.numops=it[i].ops) then
  639. begin
  640. { first fit }
  641. case instr.numops of
  642. 0 : begin
  643. fits:=true;
  644. break;
  645. end;
  646. 1 :
  647. Begin
  648. if (optyp1 and it[i].o1)<>0 then
  649. Begin
  650. fits:=true;
  651. break;
  652. end;
  653. end;
  654. 2 : if ((optyp1 and it[i].o1)<>0) and
  655. ((optyp2 and it[i].o2)<>0) then
  656. Begin
  657. fits:=true;
  658. break;
  659. end
  660. 3 : if ((optyp1 and it[i].o1)<>0) and
  661. ((optyp2 and it[i].o2)<>0) and
  662. ((optyp3 and it[i].o3)<>0) then
  663. Begin
  664. fits:=true;
  665. break;
  666. end;
  667. end; { end case }
  668. end; { endif }
  669. if it[i].i=A_NONE then
  670. begin
  671. { NO MATCH! }
  672. Message(assem_e_invalid_combination_opcode_and_operand);
  673. exit;
  674. end;
  675. inc(i);
  676. end; { end while }
  677. *)
  678. fits:=TRUE;
  679. { We add the opcode to the opcode linked list }
  680. if fits then
  681. Begin
  682. case instr.numops of
  683. 0:
  684. if instr.stropsize <> S_NO then
  685. p^.concat(new(pai68k,op_none(instruc,instr.stropsize)))
  686. else
  687. p^.concat(new(pai68k,op_none(instruc,S_NO)));
  688. 1: Begin
  689. case instr.operands[1].operandtype of
  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.ESI_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 aktswitches) 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. BuildReference(instr);
  1585. end
  1586. else
  1587. Begin
  1588. Message(assem_e_syntax_error);
  1589. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1590. Consume(actasmtoken);
  1591. end;
  1592. end;
  1593. { // Register, a variable reference or a constant reference // }
  1594. AS_REGISTER: Begin
  1595. { save the type of register used. }
  1596. tempstr := actasmpattern;
  1597. Consume(AS_REGISTER);
  1598. { // Simple register // }
  1599. if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
  1600. Begin
  1601. if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_REGISTER]) then
  1602. Message(assem_e_invalid_operand_type);
  1603. instr.operands[operandnum].operandtype := OPR_REGISTER;
  1604. instr.operands[operandnum].reg := findregister(tempstr);
  1605. end
  1606. else
  1607. { HERE WE MUST HANDLE THE SPECIAL CASE OF MOVEM AND FMOVEM }
  1608. { // Individual register listing // }
  1609. if (actasmtoken = AS_SLASH) then
  1610. Begin
  1611. reglist := [findregister(tempstr)];
  1612. Consume(AS_SLASH);
  1613. if actasmtoken = AS_REGISTER then
  1614. Begin
  1615. While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1616. Begin
  1617. case actasmtoken of
  1618. AS_REGISTER: Begin
  1619. reglist := reglist + [findregister(actasmpattern)];
  1620. Consume(AS_REGISTER);
  1621. end;
  1622. AS_SLASH: Consume(AS_SLASH);
  1623. AS_SEPARATOR,AS_COMMA: break;
  1624. else
  1625. Begin
  1626. Message(assem_e_invalid_reg_list_in_movem);
  1627. Consume(actasmtoken);
  1628. end;
  1629. end; { end case }
  1630. end; { end while }
  1631. instr.operands[operandnum].operandtype:= OPR_REGLIST;
  1632. instr.operands[operandnum].list := reglist;
  1633. end
  1634. else
  1635. { error recovery ... }
  1636. Begin
  1637. Message(assem_e_invalid_reg_list_in_movem);
  1638. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1639. Consume(actasmtoken);
  1640. end;
  1641. end
  1642. else
  1643. { // Range register listing // }
  1644. if (actasmtoken = AS_MINUS) then
  1645. Begin
  1646. Consume(AS_MINUS);
  1647. reg_one:=findregister(tempstr);
  1648. if actasmtoken <> AS_REGISTER then
  1649. Begin
  1650. Message(assem_e_invalid_reg_list_in_movem);
  1651. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1652. Consume(actasmtoken);
  1653. end
  1654. else
  1655. Begin
  1656. { determine the register range ... }
  1657. reg_two:=findregister(actasmpattern);
  1658. if reg_one > reg_two then
  1659. begin
  1660. for i:=reg_two to reg_one do
  1661. reglist := reglist + [i];
  1662. end
  1663. else
  1664. Begin
  1665. for i:=reg_one to reg_two do
  1666. reglist := reglist + [i];
  1667. end;
  1668. Consume(AS_REGISTER);
  1669. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1670. Begin
  1671. Message(assem_e_invalid_reg_list_in_movem);
  1672. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1673. Consume(actasmtoken);
  1674. end;
  1675. { set up instruction }
  1676. instr.operands[operandnum].operandtype:= OPR_REGLIST;
  1677. instr.operands[operandnum].list := reglist;
  1678. end;
  1679. end
  1680. else
  1681. { DIVSL/DIVS/MULS/MULU with long for MC68020 only }
  1682. if (actasmtoken = AS_COLON) then
  1683. Begin
  1684. if (aktoptprocessor = MC68020) or (cs_compilesystem in aktswitches) then
  1685. Begin
  1686. Consume(AS_COLON);
  1687. if (actasmtoken = AS_REGISTER) then
  1688. Begin
  1689. { set up old field, since register is valid }
  1690. instr.operands[operandnum].operandtype := OPR_REGISTER;
  1691. instr.operands[operandnum].reg := findregister(tempstr);
  1692. Inc(operandnum);
  1693. instr.operands[operandnum].operandtype := OPR_REGISTER;
  1694. instr.operands[operandnum].reg := findregister(actasmpattern);
  1695. Consume(AS_REGISTER);
  1696. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1697. Begin
  1698. Message(assem_e_invalid_reg_list_for_opcode);
  1699. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1700. Consume(actasmtoken);
  1701. end;
  1702. end;
  1703. end
  1704. else
  1705. Begin
  1706. Message(assem_e_68020_mode_required);
  1707. if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1708. Begin
  1709. Message(assem_e_invalid_reg_list_for_opcode);
  1710. while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1711. Consume(actasmtoken);
  1712. end;
  1713. end;
  1714. end
  1715. else
  1716. Message1(assem_e_syn_register,tempstr);
  1717. end;
  1718. AS_SEPARATOR, AS_COMMA: ;
  1719. else
  1720. Begin
  1721. Message(assem_e_syn_opcode_operand);
  1722. Consume(actasmtoken);
  1723. end;
  1724. end; { end case }
  1725. end;
  1726. Procedure BuildConstant(maxvalue: longint);
  1727. {*********************************************************************}
  1728. { PROCEDURE BuildConstant }
  1729. { Description: This routine takes care of parsing a DB,DD,or DW }
  1730. { line and adding those to the assembler node. Expressions, range- }
  1731. { checking are fullly taken care of. }
  1732. { maxvalue: $ff -> indicates that this is a DB node. }
  1733. { $ffff -> indicates that this is a DW node. }
  1734. { $ffffffff -> indicates that this is a DD node. }
  1735. {*********************************************************************}
  1736. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1737. {*********************************************************************}
  1738. var
  1739. strlength: byte;
  1740. expr: string;
  1741. tempstr: string;
  1742. value : longint;
  1743. Begin
  1744. Repeat
  1745. Case actasmtoken of
  1746. AS_STRING: Begin
  1747. if maxvalue = $ff then
  1748. strlength := 1
  1749. else
  1750. Message(assem_e_string_not_allowed_as_const);
  1751. expr := actasmpattern;
  1752. if length(expr) > 1 then
  1753. Message(assem_e_string_not_allowed_as_const);
  1754. Consume(AS_STRING);
  1755. Case actasmtoken of
  1756. AS_COMMA: Consume(AS_COMMA);
  1757. AS_SEPARATOR: ;
  1758. else
  1759. Message(assem_e_invalid_string_expression);
  1760. end; { end case }
  1761. ConcatString(p,expr);
  1762. end;
  1763. AS_INTNUM,AS_BINNUM,
  1764. AS_OCTALNUM,AS_HEXNUM:
  1765. Begin
  1766. value:=BuildExpression;
  1767. ConcatConstant(p,value,maxvalue);
  1768. end;
  1769. AS_ID:
  1770. Begin
  1771. value:=BuildExpression;
  1772. if value > maxvalue then
  1773. Begin
  1774. Message(assem_e_constant_out_of_bounds);
  1775. { assuming a value of maxvalue }
  1776. value := maxvalue;
  1777. end;
  1778. ConcatConstant(p,value,maxvalue);
  1779. end;
  1780. { These terms can start an assembler expression }
  1781. AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: Begin
  1782. value := BuildExpression;
  1783. ConcatConstant(p,value,maxvalue);
  1784. end;
  1785. AS_COMMA: BEGIN
  1786. Consume(AS_COMMA);
  1787. END;
  1788. AS_SEPARATOR: ;
  1789. else
  1790. Begin
  1791. Message(assem_f_internal_error_in_buildconstant);
  1792. end;
  1793. end; { end case }
  1794. Until actasmtoken = AS_SEPARATOR;
  1795. end;
  1796. Procedure BuildStringConstant(asciiz: boolean);
  1797. {*********************************************************************}
  1798. { PROCEDURE BuildStringConstant }
  1799. { Description: Takes care of a ASCII, or ASCIIZ directive. }
  1800. { asciiz: boolean -> if true then string will be null terminated. }
  1801. {*********************************************************************}
  1802. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1803. { On ENTRY: Token should point to AS_STRING }
  1804. {*********************************************************************}
  1805. var
  1806. expr: string;
  1807. errorflag : boolean;
  1808. Begin
  1809. errorflag := FALSE;
  1810. Repeat
  1811. Case actasmtoken of
  1812. AS_STRING: Begin
  1813. expr:=actasmpattern;
  1814. if asciiz then
  1815. expr:=expr+#0;
  1816. ConcatPasString(p,expr);
  1817. Consume(AS_STRING);
  1818. end;
  1819. AS_COMMA: BEGIN
  1820. Consume(AS_COMMA);
  1821. END;
  1822. AS_SEPARATOR: ;
  1823. else
  1824. Begin
  1825. Consume(actasmtoken);
  1826. if not errorflag then
  1827. Message(assem_e_invalid_string_expression);
  1828. errorflag := TRUE;
  1829. end;
  1830. end; { end case }
  1831. Until actasmtoken = AS_SEPARATOR;
  1832. end;
  1833. Procedure BuildOpCode;
  1834. {*********************************************************************}
  1835. { PROCEDURE BuildOpcode; }
  1836. { Description: Parses the intel opcode and operands, and writes it }
  1837. { in the TInstruction object. }
  1838. {*********************************************************************}
  1839. { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
  1840. { On ENTRY: Token should point to AS_OPCODE }
  1841. {*********************************************************************}
  1842. var asmtok: tasmop;
  1843. op: tasmop;
  1844. expr: string;
  1845. segreg: tregister;
  1846. Begin
  1847. expr := '';
  1848. asmtok := A_NONE; { assmume no prefix }
  1849. segreg := R_NO; { assume no segment override }
  1850. { // opcode // }
  1851. { allow for newline as in gas styled syntax }
  1852. { under DOS you get two AS_SEPARATOR !! }
  1853. while actasmtoken=AS_SEPARATOR do
  1854. Consume(AS_SEPARATOR);
  1855. if (actasmtoken <> AS_OPCODE) then
  1856. Begin
  1857. Message(assem_e_invalid_or_missing_opcode);
  1858. { error recovery }
  1859. While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1860. Consume(actasmtoken);
  1861. exit;
  1862. end
  1863. else
  1864. Begin
  1865. op := findopcode(actasmpattern);
  1866. instr.addinstr(op);
  1867. Consume(AS_OPCODE);
  1868. { // Zero operand opcode ? // }
  1869. if actasmtoken = AS_SEPARATOR then
  1870. exit
  1871. else
  1872. operandnum := 1;
  1873. end;
  1874. While actasmtoken <> AS_SEPARATOR do
  1875. Begin
  1876. case actasmtoken of
  1877. { // Operand delimiter // }
  1878. AS_COMMA: Begin
  1879. if operandnum > MaxOperands then
  1880. Message(assem_e_too_many_operands)
  1881. else
  1882. Inc(operandnum);
  1883. Consume(AS_COMMA);
  1884. end;
  1885. { // End of asm operands for this opcode // }
  1886. AS_SEPARATOR: ;
  1887. else
  1888. BuildOperand(instr);
  1889. end; { end case }
  1890. end; { end while }
  1891. end;
  1892. Function Assemble: Ptree;
  1893. {*********************************************************************}
  1894. { PROCEDURE Assemble; }
  1895. { Description: Parses the att assembler syntax, parsing is done }
  1896. { according to GAs rules. }
  1897. {*********************************************************************}
  1898. Var
  1899. hl: plabel;
  1900. labelptr,nextlabel : pasmlabel;
  1901. commname : string;
  1902. store_p : paasmoutput;
  1903. Begin
  1904. Message(assem_d_start_motorola);
  1905. firsttoken := TRUE;
  1906. operandnum := 0;
  1907. { sets up all opcode and register tables in uppercase }
  1908. if not _asmsorted then
  1909. Begin
  1910. SetupTables;
  1911. _asmsorted := TRUE;
  1912. end;
  1913. p:=new(paasmoutput,init);
  1914. { save pointer code section }
  1915. store_p:=p;
  1916. { setup label linked list }
  1917. labellist.init;
  1918. c:=asmgetchar;
  1919. actasmtoken:=gettoken;
  1920. while actasmtoken<>AS_END do
  1921. Begin
  1922. case actasmtoken of
  1923. AS_LLABEL: Begin
  1924. labelptr := labellist.search(actasmpattern);
  1925. if not assigned(labelptr) then
  1926. Begin
  1927. getlabel(hl);
  1928. labellist.insert(actasmpattern,hl,TRUE);
  1929. ConcatLabel(p,A_LABEL,hl);
  1930. end
  1931. else
  1932. { the label has already been inserted into the }
  1933. { label list, either as an instruction label (in}
  1934. { this case it has not been emitted), or as a }
  1935. { duplicate local symbol (in this case it has }
  1936. { already been emitted). }
  1937. Begin
  1938. if labelptr^.emitted then
  1939. Message1(assem_e_dup_local_sym,'@'+labelptr^.name^)
  1940. else
  1941. Begin
  1942. if assigned(labelptr^.lab) then
  1943. ConcatLabel(p,A_LABEL,labelptr^.lab);
  1944. labelptr^.emitted := TRUE;
  1945. end;
  1946. end;
  1947. Consume(AS_LLABEL);
  1948. end;
  1949. AS_LABEL: Begin
  1950. { when looking for Pascal labels, these must }
  1951. { be in uppercase. }
  1952. if SearchLabel(upper(actasmpattern),hl) then
  1953. ConcatLabel(p,A_LABEL, hl)
  1954. else
  1955. Begin
  1956. Message1(assem_e_unknown_label_identifer,actasmpattern);
  1957. end;
  1958. Consume(AS_LABEL);
  1959. end;
  1960. AS_DW: Begin
  1961. Consume(AS_DW);
  1962. BuildConstant($ffff);
  1963. end;
  1964. AS_DB: Begin
  1965. Consume(AS_DB);
  1966. BuildConstant($ff);
  1967. end;
  1968. AS_DD: Begin
  1969. Consume(AS_DD);
  1970. BuildConstant($ffffffff);
  1971. end;
  1972. AS_XDEF:
  1973. Begin
  1974. { normal units should not be able to declare }
  1975. { direct label names like this... anyhow }
  1976. { procedural calls in asm blocks are }
  1977. { supposedely replaced automatically }
  1978. if (cs_compilesystem in aktswitches) then
  1979. begin
  1980. Consume(AS_XDEF);
  1981. if actasmtoken <> AS_ID then
  1982. Message(assem_e_invalid_global_def)
  1983. else
  1984. ConcatPublic(p,actasmpattern);
  1985. Consume(actasmtoken);
  1986. if actasmtoken <> AS_SEPARATOR then
  1987. Begin
  1988. Message(assem_e_line_separator_expected);
  1989. while actasmtoken <> AS_SEPARATOR do
  1990. Consume(actasmtoken);
  1991. end;
  1992. end
  1993. else
  1994. begin
  1995. Message(assem_w_xdef_not_supported);
  1996. while actasmtoken <> AS_SEPARATOR do
  1997. Consume(actasmtoken);
  1998. end;
  1999. end;
  2000. AS_ALIGN: Begin
  2001. Message(assem_w_align_not_supported);
  2002. while actasmtoken <> AS_SEPARATOR do
  2003. Consume(actasmtoken);
  2004. end;
  2005. AS_OPCODE: Begin
  2006. instr.init;
  2007. BuildOpcode;
  2008. instr.numops := operandnum;
  2009. if instr.labeled then
  2010. ConcatLabeledInstr(instr)
  2011. else
  2012. ConcatOpCode(instr);
  2013. end;
  2014. AS_SEPARATOR:Begin
  2015. Consume(AS_SEPARATOR);
  2016. { let us go back to the first operand }
  2017. operandnum := 0;
  2018. end;
  2019. AS_END: ; { end assembly block }
  2020. else
  2021. Begin
  2022. Message(assem_e_assemble_node_syntax_error);
  2023. { error recovery }
  2024. Consume(actasmtoken);
  2025. end;
  2026. end; { end case }
  2027. end; { end while }
  2028. { check if there were undefined symbols. }
  2029. { if so, then list each of those undefined }
  2030. { labels. }
  2031. if assigned(labellist.First) then
  2032. Begin
  2033. labelptr := labellist.First;
  2034. While labelptr <> nil do
  2035. Begin
  2036. nextlabel:=labelptr^.next;
  2037. if not labelptr^.emitted then
  2038. Message1(assem_e_local_sym_not_found_in_asm_statement,'@'+labelptr^.name^);
  2039. labelptr:=nextlabel;
  2040. end;
  2041. end;
  2042. assemble := genasmnode(p);
  2043. labellist.done;
  2044. Message(assem_d_finish_motorola);
  2045. end;
  2046. procedure ra68kmot_exit;{$ifndef FPC}far;{$endif}
  2047. begin
  2048. if assigned(iasmops) then
  2049. dispose(iasmops);
  2050. exitproc:=old_exit;
  2051. end;
  2052. Begin
  2053. old_exit:=exitproc;
  2054. exitproc:=@ra68kmot_exit;
  2055. end.
  2056. {
  2057. $Log$
  2058. Revision 1.2 1998-06-24 14:06:39 peter
  2059. * fixed the name changes
  2060. Revision 1.1 1998/06/23 14:00:20 peter
  2061. * renamed RA* units
  2062. Revision 1.5 1998/06/12 10:32:31 pierre
  2063. * column problem hopefully solved
  2064. + C vars declaration changed
  2065. Revision 1.4 1998/06/04 23:51:56 peter
  2066. * m68k compiles
  2067. + .def file creation moved to gendef.pas so it could also be used
  2068. for win32
  2069. Revision 1.3 1998/05/20 09:42:36 pierre
  2070. + UseTokenInfo now default
  2071. * unit in interface uses and implementation uses gives error now
  2072. * only one error for unknown symbol (uses lastsymknown boolean)
  2073. the problem came from the label code !
  2074. + first inlined procedures and function work
  2075. (warning there might be allowed cases were the result is still wrong !!)
  2076. * UseBrower updated gives a global list of all position of all used symbols
  2077. with switch -gb
  2078. Revision 1.2 1998/04/29 10:34:01 pierre
  2079. + added some code for ansistring (not complete nor working yet)
  2080. * corrected operator overloading
  2081. * corrected nasm output
  2082. + started inline procedures
  2083. + added starstarn : use ** for exponentiation (^ gave problems)
  2084. + started UseTokenInfo cond to get accurate positions
  2085. Revision 1.1.1.1 1998/03/25 11:18:15 root
  2086. * Restored version
  2087. Revision 1.14 1998/03/22 12:45:38 florian
  2088. * changes of Carl-Eric to m68k target commit:
  2089. - wrong nodes because of the new string cg in intel, I had to create
  2090. this under m68k also ... had to work it out to fix potential alignment
  2091. problems --> this removes the crash of the m68k compiler.
  2092. - added absolute addressing in m68k assembler (required for Amiga startup)
  2093. - fixed alignment problems (because of byte return values, alignment
  2094. would not be always valid) -- is this ok if i change the offset if odd in
  2095. setfirsttemp ?? -- it seems ok...
  2096. Revision 1.13 1998/03/10 16:27:43 pierre
  2097. * better line info in stabs debug
  2098. * symtabletype and lexlevel separated into two fields of tsymtable
  2099. + ifdef MAKELIB for direct library output, not complete
  2100. + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  2101. working
  2102. + ifdef TESTFUNCRET for setting func result in underfunction, not
  2103. working
  2104. Revision 1.12 1998/03/10 01:17:25 peter
  2105. * all files have the same header
  2106. * messages are fully implemented, EXTDEBUG uses Comment()
  2107. + AG... files for the Assembler generation
  2108. }