2
0

rasm.pas 84 KB

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