ra68k.pas 82 KB

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