ra386int.pas 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. Does the parsing process for the intel styled 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 Ra386int;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. node;
  23. function assemble: tnode;
  24. Implementation
  25. uses
  26. { common }
  27. cutils,cclasses,
  28. { global }
  29. globtype,globals,verbose,
  30. systems,
  31. { aasm }
  32. cpuinfo,cpubase,aasmbase,aasmtai,aasmcpu,
  33. { symtable }
  34. symconst,symbase,symtype,symsym,symtable,
  35. { pass 1 }
  36. nbas,
  37. { parser }
  38. scanner,
  39. { register allocator }
  40. rautils,rax86,itx86int,
  41. { codegen }
  42. cgbase,cgobj,procinfo
  43. ;
  44. type
  45. tasmtoken = (
  46. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
  47. AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
  48. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
  49. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,
  50. {------------------ Assembler directives --------------------}
  51. AS_DB,AS_DW,AS_DD,AS_END,
  52. {------------------ Assembler Operators --------------------}
  53. AS_BYTE,AS_WORD,AS_DWORD,AS_QWORD,AS_TBYTE,AS_NEAR,AS_FAR,
  54. AS_HIGH,AS_LOW,AS_OFFSET,AS_SEG,AS_TYPE,AS_PTR,AS_MOD,AS_SHL,AS_SHR,AS_NOT,
  55. AS_AND,AS_OR,AS_XOR);
  56. tasmkeyword = string[6];
  57. const
  58. { These tokens should be modified accordingly to the modifications }
  59. { in the different enumerations. }
  60. firstdirective = AS_DB;
  61. lastdirective = AS_END;
  62. firstoperator = AS_BYTE;
  63. lastoperator = AS_XOR;
  64. _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  65. _count_asmoperators = longint(lastoperator)-longint(firstoperator);
  66. _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  67. ('DB','DW','DD','END');
  68. { problems with shl,shr,not,and,or and xor, they are }
  69. { context sensitive. }
  70. _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
  71. 'BYTE','WORD','DWORD','QWORD','TBYTE','NEAR','FAR','HIGH',
  72. 'LOW','OFFSET','SEG','TYPE','PTR','MOD','SHL','SHR','NOT','AND',
  73. 'OR','XOR');
  74. token2str : array[tasmtoken] of string[10] = (
  75. '','Label','LLabel','String','Integer',
  76. ',','[',']','(',
  77. ')',':','.','+','-','*',
  78. ';','identifier','register','opcode','/',
  79. '','','','END',
  80. '','','','','','','','',
  81. '','','','type','ptr','mod','shl','shr','not',
  82. 'and','or','xor'
  83. );
  84. const
  85. newline = #10;
  86. firsttoken : boolean = TRUE;
  87. var
  88. _asmsorted : boolean;
  89. inexpression : boolean;
  90. curlist : TAAsmoutput;
  91. c : char;
  92. prevasmtoken : tasmtoken;
  93. actasmtoken : tasmtoken;
  94. actasmpattern : string;
  95. actasmregister : tregister;
  96. actopcode : tasmop;
  97. actopsize : topsize;
  98. actcondition : tasmcond;
  99. iasmops : tdictionary;
  100. Procedure SetupTables;
  101. { creates uppercased symbol tables for speed access }
  102. var
  103. i : tasmop;
  104. str2opentry: tstr2opentry;
  105. Begin
  106. { opcodes }
  107. iasmops:=tdictionary.create;
  108. iasmops.delete_doubles:=true;
  109. for i:=firstop to lastop do
  110. begin
  111. str2opentry:=tstr2opentry.createname(upper(std_op2str[i]));
  112. str2opentry.op:=i;
  113. iasmops.insert(str2opentry);
  114. end;
  115. end;
  116. {---------------------------------------------------------------------}
  117. { Routines for the tokenizing }
  118. {---------------------------------------------------------------------}
  119. function is_asmopcode(const s: string):boolean;
  120. var
  121. str2opentry: tstr2opentry;
  122. cond : string[4];
  123. cnd : tasmcond;
  124. j: longint;
  125. Begin
  126. is_asmopcode:=FALSE;
  127. actopcode:=A_None;
  128. actcondition:=C_None;
  129. actopsize:=S_NO;
  130. str2opentry:=tstr2opentry(iasmops.search(s));
  131. if assigned(str2opentry) then
  132. begin
  133. actopcode:=str2opentry.op;
  134. actasmtoken:=AS_OPCODE;
  135. is_asmopcode:=TRUE;
  136. exit;
  137. end;
  138. { not found yet, check condition opcodes }
  139. j:=0;
  140. while (j<CondAsmOps) do
  141. begin
  142. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  143. begin
  144. cond:=Copy(s,Length(CondAsmOpStr[j])+1,255);
  145. if cond<>'' then
  146. begin
  147. for cnd:=low(TasmCond) to high(TasmCond) do
  148. if Cond=Upper(cond2str[cnd]) then
  149. begin
  150. actopcode:=CondASmOp[j];
  151. actcondition:=cnd;
  152. is_asmopcode:=TRUE;
  153. actasmtoken:=AS_OPCODE;
  154. exit
  155. end;
  156. end;
  157. end;
  158. inc(j);
  159. end;
  160. end;
  161. function is_asmoperator(const s: string):boolean;
  162. var
  163. i : longint;
  164. Begin
  165. for i:=0 to _count_asmoperators do
  166. if s=_asmoperators[i] then
  167. begin
  168. actasmtoken:=tasmtoken(longint(firstoperator)+i);
  169. is_asmoperator:=true;
  170. exit;
  171. end;
  172. is_asmoperator:=false;
  173. end;
  174. Function is_asmdirective(const s: string):boolean;
  175. var
  176. i : longint;
  177. Begin
  178. for i:=0 to _count_asmdirectives do
  179. if s=_asmdirectives[i] then
  180. begin
  181. actasmtoken:=tasmtoken(longint(firstdirective)+i);
  182. is_asmdirective:=true;
  183. exit;
  184. end;
  185. is_asmdirective:=false;
  186. end;
  187. function is_register(const s:string):boolean;
  188. begin
  189. is_register:=false;
  190. actasmregister:=masm_regnum_search(lower(s));
  191. if actasmregister<>NR_NO then
  192. begin
  193. is_register:=true;
  194. actasmtoken:=AS_REGISTER;
  195. end;
  196. end;
  197. function is_locallabel(const s:string):boolean;
  198. begin
  199. is_locallabel:=(length(s)>1) and (s[1]='@');
  200. end;
  201. Procedure GetToken;
  202. var
  203. len : longint;
  204. forcelabel : boolean;
  205. srsym : tsym;
  206. srsymtable : tsymtable;
  207. begin
  208. { save old token and reset new token }
  209. prevasmtoken:=actasmtoken;
  210. actasmtoken:=AS_NONE;
  211. { reset }
  212. forcelabel:=FALSE;
  213. actasmpattern:='';
  214. { while space and tab , continue scan... }
  215. while (c in [' ',#9]) do
  216. c:=current_scanner.asmgetchar;
  217. { get token pos }
  218. if not (c in [newline,#13,'{',';']) then
  219. current_scanner.gettokenpos;
  220. { Local Label, Label, Directive, Prefix or Opcode }
  221. if firsttoken and not (c in [newline,#13,'{',';']) then
  222. begin
  223. firsttoken:=FALSE;
  224. len:=0;
  225. while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
  226. begin
  227. { if there is an at_sign, then this must absolutely be a label }
  228. if c = '@' then
  229. forcelabel:=TRUE;
  230. inc(len);
  231. actasmpattern[len]:=c;
  232. c:=current_scanner.asmgetchar;
  233. end;
  234. actasmpattern[0]:=chr(len);
  235. uppervar(actasmpattern);
  236. { label ? }
  237. if c = ':' then
  238. begin
  239. if actasmpattern[1]='@' then
  240. actasmtoken:=AS_LLABEL
  241. else
  242. actasmtoken:=AS_LABEL;
  243. { let us point to the next character }
  244. c:=current_scanner.asmgetchar;
  245. firsttoken:=true;
  246. exit;
  247. end;
  248. { Are we trying to create an identifier with }
  249. { an at-sign...? }
  250. if forcelabel then
  251. Message(asmr_e_none_label_contain_at);
  252. { opcode ? }
  253. If is_asmopcode(actasmpattern) then
  254. Begin
  255. { check if we are in an expression }
  256. { then continue with asm directives }
  257. if not inexpression then
  258. exit;
  259. end;
  260. if is_asmdirective(actasmpattern) then
  261. exit;
  262. message1(asmr_e_unknown_opcode,actasmpattern);
  263. actasmtoken:=AS_NONE;
  264. exit;
  265. end
  266. else { else firsttoken }
  267. begin
  268. case c of
  269. '@' : { possiblities : - local label reference , such as in jmp @local1 }
  270. { - @Result, @Code or @Data special variables. }
  271. begin
  272. actasmpattern:=c;
  273. c:=current_scanner.asmgetchar;
  274. while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
  275. begin
  276. actasmpattern:=actasmpattern + c;
  277. c:=current_scanner.asmgetchar;
  278. end;
  279. uppervar(actasmpattern);
  280. actasmtoken:=AS_ID;
  281. exit;
  282. end;
  283. 'A'..'Z','a'..'z','_': { identifier, register, opcode, prefix or directive }
  284. begin
  285. actasmpattern:=c;
  286. c:=current_scanner.asmgetchar;
  287. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  288. begin
  289. actasmpattern:=actasmpattern + c;
  290. c:=current_scanner.asmgetchar;
  291. end;
  292. uppervar(actasmpattern);
  293. { after prefix we allow also a new opcode }
  294. If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
  295. Begin
  296. { if we are not in a constant }
  297. { expression than this is an }
  298. { opcode. }
  299. if not inexpression then
  300. exit;
  301. end;
  302. { support st(X) for fpu registers }
  303. if (actasmpattern = 'ST') and (c='(') then
  304. Begin
  305. actasmpattern:=actasmpattern+c;
  306. c:=current_scanner.asmgetchar;
  307. if c in ['0'..'7'] then
  308. actasmpattern:=actasmpattern + c
  309. else
  310. Message(asmr_e_invalid_fpu_register);
  311. c:=current_scanner.asmgetchar;
  312. if c <> ')' then
  313. Message(asmr_e_invalid_fpu_register)
  314. else
  315. Begin
  316. actasmpattern:=actasmpattern + c;
  317. c:=current_scanner.asmgetchar;
  318. end;
  319. end;
  320. if is_register(actasmpattern) then
  321. exit;
  322. if is_asmdirective(actasmpattern) then
  323. exit;
  324. if is_asmoperator(actasmpattern) then
  325. exit;
  326. { if next is a '.' and this is a unitsym then we also need to
  327. parse the identifier }
  328. if (c='.') then
  329. begin
  330. searchsym(actasmpattern,srsym,srsymtable);
  331. if assigned(srsym) and
  332. (srsym.typ=unitsym) and
  333. (srsym.owner.unitid=0) then
  334. begin
  335. { Add . to create System.Identifier }
  336. actasmpattern:=actasmpattern+c;
  337. c:=current_scanner.asmgetchar;
  338. { Delphi allows System.@Halt, just ignore the @ }
  339. if c='@' then
  340. c:=current_scanner.asmgetchar;
  341. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  342. begin
  343. actasmpattern:=actasmpattern + upcase(c);
  344. c:=current_scanner.asmgetchar;
  345. end;
  346. end;
  347. end;
  348. actasmtoken:=AS_ID;
  349. exit;
  350. end;
  351. '''' : { string or character }
  352. begin
  353. actasmpattern:='';
  354. current_scanner.in_asm_string:=true;
  355. repeat
  356. if c = '''' then
  357. begin
  358. c:=current_scanner.asmgetchar;
  359. if c=newline then
  360. begin
  361. Message(scan_f_string_exceeds_line);
  362. break;
  363. end;
  364. repeat
  365. if c='''' then
  366. begin
  367. c:=current_scanner.asmgetchar;
  368. if c='''' then
  369. begin
  370. actasmpattern:=actasmpattern+'''';
  371. c:=current_scanner.asmgetchar;
  372. if c=newline then
  373. begin
  374. Message(scan_f_string_exceeds_line);
  375. break;
  376. end;
  377. end
  378. else
  379. break;
  380. end
  381. else
  382. begin
  383. actasmpattern:=actasmpattern+c;
  384. c:=current_scanner.asmgetchar;
  385. if c=newline then
  386. begin
  387. Message(scan_f_string_exceeds_line);
  388. break
  389. end;
  390. end;
  391. until false; { end repeat }
  392. end
  393. else
  394. break; { end if }
  395. until false;
  396. current_scanner.in_asm_string:=false;
  397. actasmtoken:=AS_STRING;
  398. exit;
  399. end;
  400. '"' : { string or character }
  401. begin
  402. current_scanner.in_asm_string:=true;
  403. actasmpattern:='';
  404. repeat
  405. if c = '"' then
  406. begin
  407. c:=current_scanner.asmgetchar;
  408. if c=newline then
  409. begin
  410. Message(scan_f_string_exceeds_line);
  411. break;
  412. end;
  413. repeat
  414. if c='"' then
  415. begin
  416. c:=current_scanner.asmgetchar;
  417. if c='"' then
  418. begin
  419. actasmpattern:=actasmpattern+'"';
  420. c:=current_scanner.asmgetchar;
  421. if c=newline then
  422. begin
  423. Message(scan_f_string_exceeds_line);
  424. break;
  425. end;
  426. end
  427. else
  428. break;
  429. end
  430. else
  431. begin
  432. actasmpattern:=actasmpattern+c;
  433. c:=current_scanner.asmgetchar;
  434. if c=newline then
  435. begin
  436. Message(scan_f_string_exceeds_line);
  437. break
  438. end;
  439. end;
  440. until false; { end repeat }
  441. end
  442. else
  443. break; { end if }
  444. until false;
  445. current_scanner.in_asm_string:=false;
  446. actasmtoken:=AS_STRING;
  447. exit;
  448. end;
  449. '$' :
  450. begin
  451. c:=current_scanner.asmgetchar;
  452. while c in ['0'..'9','A'..'F','a'..'f'] do
  453. begin
  454. actasmpattern:=actasmpattern + c;
  455. c:=current_scanner.asmgetchar;
  456. end;
  457. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  458. actasmtoken:=AS_INTNUM;
  459. exit;
  460. end;
  461. ',' :
  462. begin
  463. actasmtoken:=AS_COMMA;
  464. c:=current_scanner.asmgetchar;
  465. exit;
  466. end;
  467. '[' :
  468. begin
  469. actasmtoken:=AS_LBRACKET;
  470. c:=current_scanner.asmgetchar;
  471. exit;
  472. end;
  473. ']' :
  474. begin
  475. actasmtoken:=AS_RBRACKET;
  476. c:=current_scanner.asmgetchar;
  477. exit;
  478. end;
  479. '(' :
  480. begin
  481. actasmtoken:=AS_LPAREN;
  482. c:=current_scanner.asmgetchar;
  483. exit;
  484. end;
  485. ')' :
  486. begin
  487. actasmtoken:=AS_RPAREN;
  488. c:=current_scanner.asmgetchar;
  489. exit;
  490. end;
  491. ':' :
  492. begin
  493. actasmtoken:=AS_COLON;
  494. c:=current_scanner.asmgetchar;
  495. exit;
  496. end;
  497. '.' :
  498. begin
  499. actasmtoken:=AS_DOT;
  500. c:=current_scanner.asmgetchar;
  501. exit;
  502. end;
  503. '+' :
  504. begin
  505. actasmtoken:=AS_PLUS;
  506. c:=current_scanner.asmgetchar;
  507. exit;
  508. end;
  509. '-' :
  510. begin
  511. actasmtoken:=AS_MINUS;
  512. c:=current_scanner.asmgetchar;
  513. exit;
  514. end;
  515. '*' :
  516. begin
  517. actasmtoken:=AS_STAR;
  518. c:=current_scanner.asmgetchar;
  519. exit;
  520. end;
  521. '/' :
  522. begin
  523. actasmtoken:=AS_SLASH;
  524. c:=current_scanner.asmgetchar;
  525. exit;
  526. end;
  527. '0'..'9':
  528. begin
  529. actasmpattern:=c;
  530. c:=current_scanner.asmgetchar;
  531. { Get the possible characters }
  532. while c in ['0'..'9','A'..'F','a'..'f'] do
  533. begin
  534. actasmpattern:=actasmpattern + c;
  535. c:=current_scanner.asmgetchar;
  536. end;
  537. { Get ending character }
  538. uppervar(actasmpattern);
  539. c:=upcase(c);
  540. { possibly a binary number. }
  541. if (actasmpattern[length(actasmpattern)] = 'B') and (c <> 'H') then
  542. Begin
  543. { Delete the last binary specifier }
  544. delete(actasmpattern,length(actasmpattern),1);
  545. actasmpattern:=tostr(ValBinary(actasmpattern));
  546. actasmtoken:=AS_INTNUM;
  547. exit;
  548. end
  549. else
  550. Begin
  551. case c of
  552. 'O' :
  553. Begin
  554. actasmpattern:=tostr(ValOctal(actasmpattern));
  555. actasmtoken:=AS_INTNUM;
  556. c:=current_scanner.asmgetchar;
  557. exit;
  558. end;
  559. 'H' :
  560. Begin
  561. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  562. actasmtoken:=AS_INTNUM;
  563. c:=current_scanner.asmgetchar;
  564. exit;
  565. end;
  566. else { must be an integer number }
  567. begin
  568. actasmpattern:=tostr(ValDecimal(actasmpattern));
  569. actasmtoken:=AS_INTNUM;
  570. exit;
  571. end;
  572. end;
  573. end;
  574. end;
  575. ';','{',#13,newline :
  576. begin
  577. c:=current_scanner.asmgetchar;
  578. firsttoken:=TRUE;
  579. actasmtoken:=AS_SEPARATOR;
  580. exit;
  581. end;
  582. else
  583. current_scanner.illegal_char(c);
  584. end;
  585. end;
  586. end;
  587. function consume(t : tasmtoken):boolean;
  588. begin
  589. Consume:=true;
  590. if t<>actasmtoken then
  591. begin
  592. Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
  593. Consume:=false;
  594. end;
  595. repeat
  596. gettoken;
  597. until actasmtoken<>AS_NONE;
  598. end;
  599. procedure RecoverConsume(allowcomma:boolean);
  600. begin
  601. While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
  602. begin
  603. if allowcomma and (actasmtoken=AS_COMMA) then
  604. break;
  605. Consume(actasmtoken);
  606. end;
  607. end;
  608. {*****************************************************************************
  609. Parsing Helpers
  610. *****************************************************************************}
  611. Procedure BuildRecordOffsetSize(const expr: string;var offset:longint;var size:longint);
  612. { Description: This routine builds up a record offset after a AS_DOT }
  613. { token is encountered. }
  614. { On entry actasmtoken should be equal to AS_DOT }
  615. var
  616. s : string;
  617. Begin
  618. offset:=0;
  619. size:=0;
  620. s:=expr;
  621. while (actasmtoken=AS_DOT) do
  622. begin
  623. Consume(AS_DOT);
  624. if actasmtoken=AS_ID then
  625. s:=s+'.'+actasmpattern;
  626. if not Consume(AS_ID) then
  627. begin
  628. RecoverConsume(true);
  629. break;
  630. end;
  631. end;
  632. if not GetRecordOffsetSize(s,offset,size) then
  633. Message(asmr_e_building_record_offset);
  634. end;
  635. Procedure BuildConstSymbolExpression(needofs,isref:boolean;var value:longint;var asmsym:string);
  636. var
  637. tempstr,expr,hs : string;
  638. parenlevel,l,k : longint;
  639. errorflag : boolean;
  640. prevtok : tasmtoken;
  641. hl : tasmlabel;
  642. sym : tsym;
  643. srsymtable : tsymtable;
  644. Begin
  645. { reset }
  646. value:=0;
  647. asmsym:='';
  648. errorflag:=FALSE;
  649. tempstr:='';
  650. expr:='';
  651. inexpression:=TRUE;
  652. parenlevel:=0;
  653. Repeat
  654. Case actasmtoken of
  655. AS_LPAREN:
  656. Begin
  657. Consume(AS_LPAREN);
  658. expr:=expr + '(';
  659. inc(parenlevel);
  660. end;
  661. AS_RPAREN:
  662. Begin
  663. Consume(AS_RPAREN);
  664. expr:=expr + ')';
  665. dec(parenlevel);
  666. end;
  667. AS_SHL:
  668. Begin
  669. Consume(AS_SHL);
  670. expr:=expr + '<';
  671. end;
  672. AS_SHR:
  673. Begin
  674. Consume(AS_SHR);
  675. expr:=expr + '>';
  676. end;
  677. AS_SLASH:
  678. Begin
  679. Consume(AS_SLASH);
  680. expr:=expr + '/';
  681. end;
  682. AS_MOD:
  683. Begin
  684. Consume(AS_MOD);
  685. expr:=expr + '%';
  686. end;
  687. AS_STAR:
  688. Begin
  689. Consume(AS_STAR);
  690. if isref and (actasmtoken=AS_REGISTER) then
  691. break;
  692. expr:=expr + '*';
  693. end;
  694. AS_PLUS:
  695. Begin
  696. Consume(AS_PLUS);
  697. if isref and (actasmtoken=AS_REGISTER) then
  698. break;
  699. expr:=expr + '+';
  700. end;
  701. AS_LBRACKET:
  702. begin
  703. { Support ugly delphi constructs like: [ECX].1+2[EDX] }
  704. if isref then
  705. break;
  706. end;
  707. AS_MINUS:
  708. Begin
  709. Consume(AS_MINUS);
  710. expr:=expr + '-';
  711. end;
  712. AS_AND:
  713. Begin
  714. Consume(AS_AND);
  715. expr:=expr + '&';
  716. end;
  717. AS_NOT:
  718. Begin
  719. Consume(AS_NOT);
  720. expr:=expr + '~';
  721. end;
  722. AS_XOR:
  723. Begin
  724. Consume(AS_XOR);
  725. expr:=expr + '^';
  726. end;
  727. AS_OR:
  728. Begin
  729. Consume(AS_OR);
  730. expr:=expr + '|';
  731. end;
  732. AS_INTNUM:
  733. Begin
  734. expr:=expr + actasmpattern;
  735. Consume(AS_INTNUM);
  736. end;
  737. AS_OFFSET:
  738. begin
  739. Consume(AS_OFFSET);
  740. if actasmtoken<>AS_ID then
  741. Message(asmr_e_offset_without_identifier);
  742. end;
  743. AS_TYPE:
  744. begin
  745. l:=0;
  746. Consume(AS_TYPE);
  747. if actasmtoken<>AS_ID then
  748. Message(asmr_e_type_without_identifier)
  749. else
  750. begin
  751. tempstr:=actasmpattern;
  752. Consume(AS_ID);
  753. if actasmtoken=AS_DOT then
  754. BuildRecordOffsetSize(tempstr,k,l)
  755. else
  756. begin
  757. searchsym(tempstr,sym,srsymtable);
  758. if assigned(sym) then
  759. begin
  760. case sym.typ of
  761. varsym :
  762. l:=tvarsym(sym).getsize;
  763. typedconstsym :
  764. l:=ttypedconstsym(sym).getsize;
  765. typesym :
  766. l:=ttypesym(sym).restype.def.size;
  767. else
  768. Message(asmr_e_wrong_sym_type);
  769. end;
  770. end
  771. else
  772. Message1(sym_e_unknown_id,tempstr);
  773. end;
  774. end;
  775. str(l, tempstr);
  776. expr:=expr + tempstr;
  777. end;
  778. AS_STRING:
  779. Begin
  780. l:=0;
  781. case Length(actasmpattern) of
  782. 1 :
  783. l:=ord(actasmpattern[1]);
  784. 2 :
  785. l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
  786. 3 :
  787. l:=ord(actasmpattern[3]) +
  788. Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
  789. 4 :
  790. l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
  791. Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
  792. else
  793. Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
  794. end;
  795. str(l, tempstr);
  796. expr:=expr + tempstr;
  797. Consume(AS_STRING);
  798. end;
  799. AS_ID:
  800. Begin
  801. hs:='';
  802. tempstr:=actasmpattern;
  803. prevtok:=prevasmtoken;
  804. consume(AS_ID);
  805. if SearchIConstant(tempstr,l) then
  806. begin
  807. str(l, tempstr);
  808. expr:=expr + tempstr;
  809. end
  810. else
  811. begin
  812. if is_locallabel(tempstr) then
  813. begin
  814. CreateLocalLabel(tempstr,hl,false);
  815. hs:=hl.name
  816. end
  817. else
  818. if SearchLabel(tempstr,hl,false) then
  819. hs:=hl.name
  820. else
  821. begin
  822. searchsym(tempstr,sym,srsymtable);
  823. if assigned(sym) then
  824. begin
  825. case sym.typ of
  826. varsym :
  827. begin
  828. if sym.owner.symtabletype in [localsymtable,parasymtable] then
  829. Message(asmr_e_no_local_or_para_allowed);
  830. hs:=tvarsym(sym).mangledname;
  831. end;
  832. typedconstsym :
  833. hs:=ttypedconstsym(sym).mangledname;
  834. procsym :
  835. begin
  836. if Tprocsym(sym).procdef_count>1 then
  837. Message(asmr_w_calling_overload_func);
  838. hs:=tprocsym(sym).first_procdef.mangledname;
  839. end;
  840. typesym :
  841. begin
  842. if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
  843. Message(asmr_e_wrong_sym_type);
  844. end;
  845. else
  846. Message(asmr_e_wrong_sym_type);
  847. end;
  848. end
  849. else
  850. Message1(sym_e_unknown_id,tempstr);
  851. end;
  852. { symbol found? }
  853. if hs<>'' then
  854. begin
  855. if needofs and (prevtok<>AS_OFFSET) then
  856. Message(asmr_e_need_offset);
  857. if asmsym='' then
  858. asmsym:=hs
  859. else
  860. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  861. if (expr='') or (expr[length(expr)]='+') then
  862. begin
  863. { don't remove the + if there could be a record field }
  864. if actasmtoken<>AS_DOT then
  865. delete(expr,length(expr),1);
  866. end
  867. else
  868. Message(asmr_e_only_add_relocatable_symbol);
  869. end;
  870. if actasmtoken=AS_DOT then
  871. begin
  872. BuildRecordOffsetSize(tempstr,l,k);
  873. str(l, tempstr);
  874. expr:=expr + tempstr;
  875. end
  876. else
  877. begin
  878. if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
  879. delete(expr,length(expr),1);
  880. end;
  881. end;
  882. { check if there are wrong operator used like / or mod etc. }
  883. if (hs<>'') and not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END,AS_RBRACKET]) then
  884. Message(asmr_e_only_add_relocatable_symbol);
  885. end;
  886. AS_END,
  887. AS_RBRACKET,
  888. AS_SEPARATOR,
  889. AS_COMMA:
  890. Begin
  891. break;
  892. end;
  893. else
  894. Begin
  895. { write error only once. }
  896. if not errorflag then
  897. Message(asmr_e_invalid_constant_expression);
  898. { consume tokens until we find COMMA or SEPARATOR }
  899. Consume(actasmtoken);
  900. errorflag:=TRUE;
  901. end;
  902. end;
  903. Until false;
  904. { calculate expression }
  905. if not ErrorFlag then
  906. value:=CalculateExpression(expr)
  907. else
  908. value:=0;
  909. { no longer in an expression }
  910. inexpression:=FALSE;
  911. end;
  912. Function BuildConstExpression:longint;
  913. var
  914. l : longint;
  915. hs : string;
  916. begin
  917. BuildConstSymbolExpression(false,false,l,hs);
  918. if hs<>'' then
  919. Message(asmr_e_relocatable_symbol_not_allowed);
  920. BuildConstExpression:=l;
  921. end;
  922. Function BuildRefConstExpression:longint;
  923. var
  924. l : longint;
  925. hs : string;
  926. begin
  927. BuildConstSymbolExpression(false,true,l,hs);
  928. if hs<>'' then
  929. Message(asmr_e_relocatable_symbol_not_allowed);
  930. BuildRefConstExpression:=l;
  931. end;
  932. {****************************************************************************
  933. T386IntelOperand
  934. ****************************************************************************}
  935. type
  936. T386IntelOperand=class(T386Operand)
  937. Procedure BuildOperand;override;
  938. private
  939. Procedure BuildReference;
  940. Procedure BuildConstant;
  941. end;
  942. Procedure T386IntelOperand.BuildReference;
  943. var
  944. k,l,scale : longint;
  945. tempstr,hs : string;
  946. typesize : longint;
  947. code : integer;
  948. hreg,
  949. oldbase : tregister;
  950. GotStar,GotOffset,HadVar,
  951. GotPlus,Negative : boolean;
  952. Begin
  953. Consume(AS_LBRACKET);
  954. InitRef;
  955. GotStar:=false;
  956. GotPlus:=true;
  957. GotOffset:=false;
  958. Negative:=false;
  959. Scale:=0;
  960. repeat
  961. if GotOffset and (actasmtoken<>AS_ID) then
  962. Message(asmr_e_invalid_reference_syntax);
  963. Case actasmtoken of
  964. AS_ID: { Constant reference expression OR variable reference expression }
  965. Begin
  966. if not GotPlus then
  967. Message(asmr_e_invalid_reference_syntax);
  968. if actasmpattern[1] = '@' then
  969. Message(asmr_e_local_label_not_allowed_as_ref);
  970. GotStar:=false;
  971. GotPlus:=false;
  972. if SearchIConstant(actasmpattern,l) or
  973. SearchRecordType(actasmpattern) then
  974. begin
  975. l:=BuildRefConstExpression;
  976. GotPlus:=(prevasmtoken=AS_PLUS);
  977. GotStar:=(prevasmtoken=AS_STAR);
  978. if GotStar then
  979. opr.ref.scalefactor:=l
  980. else
  981. begin
  982. if negative then
  983. Dec(opr.ref.offset,l)
  984. else
  985. Inc(opr.ref.offset,l);
  986. end;
  987. end
  988. else
  989. Begin
  990. if hasvar and not GotOffset then
  991. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  992. HadVar:=hasvar and GotOffset;
  993. if negative then
  994. Message(asmr_e_only_add_relocatable_symbol);
  995. tempstr:=actasmpattern;
  996. Consume(AS_ID);
  997. { typecasting? }
  998. if (actasmtoken=AS_LPAREN) and
  999. SearchType(tempstr,typesize) then
  1000. begin
  1001. hastype:=true;
  1002. Consume(AS_LPAREN);
  1003. BuildOperand;
  1004. Consume(AS_RPAREN);
  1005. if opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  1006. SetSize(typesize,true);
  1007. end
  1008. else
  1009. if not SetupVar(tempstr,GotOffset) then
  1010. Message1(sym_e_unknown_id,tempstr);
  1011. { record.field ? }
  1012. if actasmtoken=AS_DOT then
  1013. begin
  1014. BuildRecordOffsetSize(tempstr,l,k);
  1015. case opr.typ of
  1016. OPR_LOCAL :
  1017. inc(opr.localsymofs,l);
  1018. OPR_REFERENCE :
  1019. inc(opr.ref.offset,l);
  1020. end;
  1021. end;
  1022. if GotOffset then
  1023. begin
  1024. if hasvar and (opr.ref.base=current_procinfo.framepointer) then
  1025. begin
  1026. if (opr.typ=OPR_REFERENCE) then
  1027. opr.ref.base:=NR_NO;
  1028. hasvar:=hadvar;
  1029. end
  1030. else
  1031. begin
  1032. if hasvar and hadvar then
  1033. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1034. { should we allow ?? }
  1035. end;
  1036. end;
  1037. (*
  1038. if (opr.typ=OPR_REFERENCE) then
  1039. begin
  1040. { is the base register loaded by the var ? }
  1041. if (opr.ref.base<>NR_NO) then
  1042. begin
  1043. { check if we can move the old base to the index register }
  1044. if (opr.ref.index<>NR_NO) then
  1045. Message(asmr_e_wrong_base_index)
  1046. else
  1047. opr.ref.index:=oldbase;
  1048. end
  1049. else
  1050. opr.ref.base:=oldbase;
  1051. { we can't have a Constant here so add the constant value to the
  1052. offset }
  1053. if opr.typ=OPR_CONSTANT then
  1054. begin
  1055. opr.typ:=OPR_REFERENCE;
  1056. inc(opr.ref.offset,opr.val);
  1057. end;
  1058. end;
  1059. *)
  1060. end;
  1061. GotOffset:=false;
  1062. end;
  1063. AS_PLUS :
  1064. Begin
  1065. Consume(AS_PLUS);
  1066. Negative:=false;
  1067. GotPlus:=true;
  1068. GotStar:=false;
  1069. Scale:=0;
  1070. end;
  1071. AS_MINUS :
  1072. begin
  1073. Consume(AS_MINUS);
  1074. Negative:=true;
  1075. GotPlus:=true;
  1076. GotStar:=false;
  1077. Scale:=0;
  1078. end;
  1079. AS_STAR : { Scaling, with eax*4 order }
  1080. begin
  1081. Consume(AS_STAR);
  1082. hs:='';
  1083. l:=0;
  1084. case actasmtoken of
  1085. AS_LPAREN :
  1086. l:=BuildConstExpression;
  1087. AS_INTNUM:
  1088. Begin
  1089. hs:=actasmpattern;
  1090. Consume(AS_INTNUM);
  1091. end;
  1092. AS_REGISTER :
  1093. begin
  1094. if opr.ref.scalefactor=0 then
  1095. if scale<>0 then
  1096. begin
  1097. opr.ref.scalefactor:=scale;
  1098. scale:=0;
  1099. end
  1100. else
  1101. Message(asmr_e_wrong_scale_factor);
  1102. end;
  1103. else
  1104. Message(asmr_e_invalid_reference_syntax);
  1105. end;
  1106. if actasmtoken<>AS_REGISTER then
  1107. begin
  1108. if hs<>'' then
  1109. val(hs,l,code);
  1110. opr.ref.scalefactor:=l;
  1111. if l>9 then
  1112. Message(asmr_e_wrong_scale_factor);
  1113. end;
  1114. GotPlus:=false;
  1115. GotStar:=false;
  1116. end;
  1117. AS_REGISTER :
  1118. begin
  1119. if not((GotPlus and (not Negative)) or
  1120. GotStar) then
  1121. Message(asmr_e_invalid_reference_syntax);
  1122. hreg:=actasmregister;
  1123. Consume(AS_REGISTER);
  1124. if opr.typ=OPR_LOCAL then
  1125. begin
  1126. if (opr.localindexreg<>NR_NO) then
  1127. Message(asmr_e_multiple_index);
  1128. opr.localindexreg:=hreg;
  1129. end
  1130. else
  1131. begin
  1132. { this register will be the index:
  1133. 1. just read a *
  1134. 2. next token is a *
  1135. 3. base register is already used }
  1136. if (GotStar) or
  1137. (actasmtoken=AS_STAR) or
  1138. (opr.ref.base<>NR_NO) then
  1139. begin
  1140. if (opr.ref.index<>NR_NO) then
  1141. Message(asmr_e_multiple_index);
  1142. opr.ref.index:=hreg;
  1143. if scale<>0 then
  1144. begin
  1145. opr.ref.scalefactor:=scale;
  1146. scale:=0;
  1147. end;
  1148. end
  1149. else
  1150. opr.ref.base:=hreg;
  1151. end;
  1152. GotPlus:=false;
  1153. GotStar:=false;
  1154. end;
  1155. AS_OFFSET :
  1156. begin
  1157. Consume(AS_OFFSET);
  1158. GotOffset:=true;
  1159. end;
  1160. AS_TYPE,
  1161. AS_NOT,
  1162. AS_STRING,
  1163. AS_INTNUM,
  1164. AS_LPAREN : { Constant reference expression }
  1165. begin
  1166. if not GotPlus and not GotStar then
  1167. Message(asmr_e_invalid_reference_syntax);
  1168. BuildConstSymbolExpression(true,true,l,tempstr);
  1169. if tempstr<>'' then
  1170. begin
  1171. if GotStar then
  1172. Message(asmr_e_only_add_relocatable_symbol);
  1173. if not assigned(opr.ref.symbol) then
  1174. opr.ref.symbol:=objectlibrary.newasmsymbol(tempstr)
  1175. else
  1176. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1177. end;
  1178. if GotStar then
  1179. opr.ref.scalefactor:=l
  1180. else if (prevasmtoken = AS_STAR) then
  1181. begin
  1182. if scale<>0 then
  1183. scale:=l*scale
  1184. else
  1185. scale:=l;
  1186. end
  1187. else
  1188. begin
  1189. if negative then
  1190. Dec(opr.ref.offset,l)
  1191. else
  1192. Inc(opr.ref.offset,l);
  1193. end;
  1194. GotPlus:=(prevasmtoken=AS_PLUS) or
  1195. (prevasmtoken=AS_MINUS);
  1196. if GotPlus then
  1197. negative := prevasmtoken = AS_MINUS;
  1198. GotStar:=(prevasmtoken=AS_STAR);
  1199. end;
  1200. AS_RBRACKET :
  1201. begin
  1202. if GotPlus or GotStar then
  1203. Message(asmr_e_invalid_reference_syntax);
  1204. Consume(AS_RBRACKET);
  1205. break;
  1206. end;
  1207. else
  1208. Begin
  1209. Message(asmr_e_invalid_reference_syntax);
  1210. RecoverConsume(true);
  1211. break;
  1212. end;
  1213. end;
  1214. until false;
  1215. end;
  1216. Procedure T386IntelOperand.BuildConstant;
  1217. var
  1218. l : longint;
  1219. tempstr : string;
  1220. begin
  1221. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1222. Message(asmr_e_invalid_operand_type);
  1223. BuildConstSymbolExpression(true,false,l,tempstr);
  1224. if tempstr<>'' then
  1225. begin
  1226. opr.typ:=OPR_SYMBOL;
  1227. opr.symofs:=l;
  1228. opr.symbol:=objectlibrary.newasmsymbol(tempstr);
  1229. end
  1230. else
  1231. begin
  1232. if opr.typ=OPR_NONE then
  1233. begin
  1234. opr.typ:=OPR_CONSTANT;
  1235. opr.val:=l;
  1236. end
  1237. else
  1238. inc(opr.val,l);
  1239. end;
  1240. end;
  1241. Procedure T386IntelOperand.BuildOperand;
  1242. procedure AddLabelOperand(hl:tasmlabel);
  1243. begin
  1244. if is_calljmp(actopcode) then
  1245. begin
  1246. opr.typ:=OPR_SYMBOL;
  1247. opr.symbol:=hl;
  1248. end
  1249. else
  1250. begin
  1251. InitRef;
  1252. opr.ref.symbol:=hl;
  1253. end;
  1254. end;
  1255. var
  1256. expr : string;
  1257. tempreg : tregister;
  1258. typesize,
  1259. l : longint;
  1260. hl : tasmlabel;
  1261. toffset,
  1262. tsize : longint;
  1263. Begin
  1264. expr:='';
  1265. repeat
  1266. if actasmtoken=AS_DOT then
  1267. begin
  1268. if expr<>'' then
  1269. begin
  1270. BuildRecordOffsetSize(expr,toffset,tsize);
  1271. SetSize(tsize,true);
  1272. case opr.typ of
  1273. OPR_LOCAL :
  1274. begin
  1275. { don't allow direct access to fields of parameters, becuase that
  1276. will generate buggy code. Allow it only for explicit typecasting
  1277. and when the parameter is in a register (delphi compatible) }
  1278. if (not hastype) and
  1279. (tvarsym(opr.localsym).owner.symtabletype=parasymtable) and
  1280. (current_procinfo.procdef.proccalloption<>pocall_register) then
  1281. Message(asmr_e_cannot_access_field_directly_for_parameters);
  1282. inc(opr.localsymofs,toffset)
  1283. end;
  1284. OPR_CONSTANT :
  1285. inc(opr.val,toffset);
  1286. OPR_REFERENCE :
  1287. inc(opr.ref.offset,toffset);
  1288. OPR_NONE :
  1289. begin
  1290. opr.typ:=OPR_CONSTANT;
  1291. opr.val:=toffset;
  1292. end;
  1293. else
  1294. internalerror(200309222);
  1295. end;
  1296. expr:='';
  1297. end
  1298. else
  1299. begin
  1300. { See it as a separator }
  1301. Consume(AS_DOT);
  1302. end;
  1303. end;
  1304. case actasmtoken of
  1305. AS_OFFSET,
  1306. AS_TYPE,
  1307. AS_NOT,
  1308. AS_STRING :
  1309. Begin
  1310. BuildConstant;
  1311. end;
  1312. AS_PLUS,
  1313. AS_MINUS,
  1314. AS_LPAREN,
  1315. AS_INTNUM :
  1316. begin
  1317. case opr.typ of
  1318. OPR_REFERENCE :
  1319. inc(opr.ref.offset,BuildRefConstExpression);
  1320. OPR_LOCAL :
  1321. inc(opr.localsymofs,BuildConstExpression);
  1322. OPR_NONE,
  1323. OPR_CONSTANT :
  1324. BuildConstant;
  1325. else
  1326. Message(asmr_e_invalid_operand_type);
  1327. end;
  1328. end;
  1329. AS_ID : { A constant expression, or a Variable ref. }
  1330. Begin
  1331. { Label or Special symbol reference? }
  1332. if actasmpattern[1] = '@' then
  1333. Begin
  1334. if actasmpattern = '@RESULT' then
  1335. Begin
  1336. SetupResult;
  1337. Consume(AS_ID);
  1338. end
  1339. else
  1340. if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
  1341. begin
  1342. Message(asmr_w_CODE_and_DATA_not_supported);
  1343. Consume(AS_ID);
  1344. end
  1345. else
  1346. { Local Label }
  1347. begin
  1348. CreateLocalLabel(actasmpattern,hl,false);
  1349. Consume(AS_ID);
  1350. AddLabelOperand(hl);
  1351. if not (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1352. Message(asmr_e_syntax_error);
  1353. end;
  1354. end
  1355. else
  1356. { support result for delphi modes }
  1357. if (m_objpas in aktmodeswitches) and (actasmpattern='RESULT') then
  1358. begin
  1359. SetUpResult;
  1360. Consume(AS_ID);
  1361. end
  1362. { probably a variable or normal expression }
  1363. { or a procedure (such as in CALL ID) }
  1364. else
  1365. Begin
  1366. { is it a constant ? }
  1367. if SearchIConstant(actasmpattern,l) then
  1368. Begin
  1369. case opr.typ of
  1370. OPR_REFERENCE :
  1371. inc(opr.ref.offset,BuildRefConstExpression);
  1372. OPR_LOCAL :
  1373. inc(opr.localsymofs,BuildRefConstExpression);
  1374. OPR_NONE,
  1375. OPR_CONSTANT :
  1376. BuildConstant;
  1377. else
  1378. Message(asmr_e_invalid_operand_type);
  1379. end;
  1380. end
  1381. else
  1382. { Check for pascal label }
  1383. if SearchLabel(actasmpattern,hl,false) then
  1384. begin
  1385. Consume(AS_ID);
  1386. AddLabelOperand(hl);
  1387. if not (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1388. Message(asmr_e_syntax_error);
  1389. end
  1390. else
  1391. { is it a normal variable ? }
  1392. Begin
  1393. expr:=actasmpattern;
  1394. Consume(AS_ID);
  1395. { typecasting? }
  1396. if SearchType(expr,typesize) then
  1397. begin
  1398. hastype:=true;
  1399. if (actasmtoken=AS_LPAREN) then
  1400. begin
  1401. Consume(AS_LPAREN);
  1402. BuildOperand;
  1403. Consume(AS_RPAREN);
  1404. if opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  1405. SetSize(typesize,true);
  1406. end;
  1407. end
  1408. else
  1409. begin
  1410. if not SetupVar(expr,false) then
  1411. Begin
  1412. { not a variable, check special variables.. }
  1413. if expr = 'SELF' then
  1414. SetupSelf
  1415. else
  1416. Message1(sym_e_unknown_id,expr);
  1417. expr:='';
  1418. end;
  1419. end;
  1420. end;
  1421. end;
  1422. end;
  1423. AS_REGISTER : { Register, a variable reference or a constant reference }
  1424. begin
  1425. { save the type of register used. }
  1426. tempreg:=actasmregister;
  1427. Consume(AS_REGISTER);
  1428. if actasmtoken = AS_COLON then
  1429. Begin
  1430. Consume(AS_COLON);
  1431. InitRef;
  1432. opr.ref.segment:=tempreg;
  1433. BuildReference;
  1434. end
  1435. else
  1436. { Simple register }
  1437. begin
  1438. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1439. Message(asmr_e_invalid_operand_type);
  1440. opr.typ:=OPR_REGISTER;
  1441. opr.reg:=tempreg;
  1442. SetSize(tcgsize2size[cg.reg_cgsize(opr.reg)],true);
  1443. end;
  1444. end;
  1445. AS_LBRACKET: { a variable reference, register ref. or a constant reference }
  1446. Begin
  1447. InitRef;
  1448. BuildReference;
  1449. end;
  1450. AS_SEG :
  1451. Begin
  1452. Message(asmr_e_seg_not_supported);
  1453. Consume(actasmtoken);
  1454. end;
  1455. AS_SEPARATOR,
  1456. AS_END,
  1457. AS_COMMA:
  1458. break;
  1459. else
  1460. Message(asmr_e_syn_operand);
  1461. end;
  1462. until not(actasmtoken in [AS_DOT,AS_PLUS,AS_LBRACKET]);
  1463. if not((actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) or
  1464. (hastype and (actasmtoken=AS_RPAREN))) then
  1465. begin
  1466. Message(asmr_e_syntax_error);
  1467. RecoverConsume(true);
  1468. end;
  1469. end;
  1470. {*****************************************************************************
  1471. T386IntelInstruction
  1472. *****************************************************************************}
  1473. type
  1474. T386IntelInstruction=class(T386Instruction)
  1475. procedure InitOperands;override;
  1476. procedure BuildOpcode;override;
  1477. end;
  1478. procedure T386IntelInstruction.InitOperands;
  1479. var
  1480. i : longint;
  1481. begin
  1482. for i:=1 to 3 do
  1483. Operands[i]:=T386IntelOperand.Create;
  1484. end;
  1485. Procedure T386IntelInstruction.BuildOpCode;
  1486. var
  1487. PrefixOp,OverrideOp: tasmop;
  1488. size,
  1489. operandnum : longint;
  1490. Begin
  1491. PrefixOp:=A_None;
  1492. OverrideOp:=A_None;
  1493. { prefix seg opcode / prefix opcode }
  1494. repeat
  1495. if is_prefix(actopcode) then
  1496. begin
  1497. OpOrder:=op_intel;
  1498. PrefixOp:=ActOpcode;
  1499. opcode:=ActOpcode;
  1500. condition:=ActCondition;
  1501. opsize:=ActOpsize;
  1502. ConcatInstruction(curlist);
  1503. Consume(AS_OPCODE);
  1504. end
  1505. else
  1506. if is_override(actopcode) then
  1507. begin
  1508. OpOrder:=op_intel;
  1509. OverrideOp:=ActOpcode;
  1510. opcode:=ActOpcode;
  1511. condition:=ActCondition;
  1512. opsize:=ActOpsize;
  1513. ConcatInstruction(curlist);
  1514. Consume(AS_OPCODE);
  1515. end
  1516. else
  1517. break;
  1518. { allow for newline after prefix or override }
  1519. while actasmtoken=AS_SEPARATOR do
  1520. Consume(AS_SEPARATOR);
  1521. until (actasmtoken<>AS_OPCODE);
  1522. { opcode }
  1523. if (actasmtoken <> AS_OPCODE) then
  1524. Begin
  1525. Message(asmr_e_invalid_or_missing_opcode);
  1526. RecoverConsume(false);
  1527. exit;
  1528. end;
  1529. { Fill the instr object with the current state }
  1530. OpOrder:=op_intel;
  1531. Opcode:=ActOpcode;
  1532. condition:=ActCondition;
  1533. opsize:=ActOpsize;
  1534. { Valid combination of prefix/override and instruction ? }
  1535. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1536. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1537. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1538. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1539. { We are reading operands, so opcode will be an AS_ID }
  1540. operandnum:=1;
  1541. Consume(AS_OPCODE);
  1542. { Zero operand opcode ? }
  1543. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1544. begin
  1545. operandnum:=0;
  1546. exit;
  1547. end;
  1548. { Read Operands }
  1549. repeat
  1550. case actasmtoken of
  1551. { End of asm operands for this opcode }
  1552. AS_END,
  1553. AS_SEPARATOR :
  1554. break;
  1555. { Operand delimiter }
  1556. AS_COMMA :
  1557. Begin
  1558. if operandnum > Max_Operands then
  1559. Message(asmr_e_too_many_operands)
  1560. else
  1561. Inc(operandnum);
  1562. Consume(AS_COMMA);
  1563. end;
  1564. { Typecast, Constant Expression, Type Specifier }
  1565. AS_DWORD,
  1566. AS_BYTE,
  1567. AS_WORD,
  1568. AS_TBYTE,
  1569. AS_QWORD :
  1570. Begin
  1571. { load the size in a temp variable, so it can be set when the
  1572. operand is read }
  1573. size:=0;
  1574. Case actasmtoken of
  1575. AS_DWORD : size:=4;
  1576. AS_WORD : size:=2;
  1577. AS_BYTE : size:=1;
  1578. AS_QWORD : size:=8;
  1579. AS_TBYTE : size:=extended_size;
  1580. end;
  1581. Consume(actasmtoken);
  1582. if actasmtoken=AS_PTR then
  1583. begin
  1584. Consume(AS_PTR);
  1585. Operands[operandnum].InitRef;
  1586. end;
  1587. Operands[operandnum].BuildOperand;
  1588. { now set the size which was specified by the override }
  1589. Operands[operandnum].setsize(size,true);
  1590. end;
  1591. { Type specifier }
  1592. AS_NEAR,
  1593. AS_FAR :
  1594. Begin
  1595. if actasmtoken = AS_NEAR then
  1596. begin
  1597. Message(asmr_w_near_ignored);
  1598. opsize:=S_NEAR;
  1599. end
  1600. else
  1601. begin
  1602. Message(asmr_w_far_ignored);
  1603. opsize:=S_FAR;
  1604. end;
  1605. Consume(actasmtoken);
  1606. if actasmtoken=AS_PTR then
  1607. begin
  1608. Consume(AS_PTR);
  1609. Operands[operandnum].InitRef;
  1610. end;
  1611. Operands[operandnum].BuildOperand;
  1612. end;
  1613. else
  1614. Operands[operandnum].BuildOperand;
  1615. end; { end case }
  1616. until false;
  1617. Ops:=operandnum;
  1618. end;
  1619. Procedure BuildConstant(maxvalue: longint);
  1620. var
  1621. strlength: byte;
  1622. asmsym,
  1623. expr: string;
  1624. value : longint;
  1625. Begin
  1626. strlength:=0; { assume it is a DB }
  1627. Repeat
  1628. Case actasmtoken of
  1629. AS_STRING:
  1630. Begin
  1631. if maxvalue = $ffff then
  1632. strlength:=2
  1633. else
  1634. if maxvalue = longint($ffffffff) then
  1635. strlength:=4;
  1636. { DD and DW cases }
  1637. if strlength <> 0 then
  1638. Begin
  1639. if Not PadZero(actasmpattern,strlength) then
  1640. Message(scan_f_string_exceeds_line);
  1641. end;
  1642. expr:=actasmpattern;
  1643. Consume(AS_STRING);
  1644. Case actasmtoken of
  1645. AS_COMMA:
  1646. Consume(AS_COMMA);
  1647. AS_END,
  1648. AS_SEPARATOR: ;
  1649. else
  1650. Message(asmr_e_invalid_string_expression);
  1651. end;
  1652. ConcatString(curlist,expr);
  1653. end;
  1654. AS_PLUS,
  1655. AS_MINUS,
  1656. AS_LPAREN,
  1657. AS_NOT,
  1658. AS_INTNUM,
  1659. AS_ID :
  1660. Begin
  1661. BuildConstSymbolExpression(false,false,value,asmsym);
  1662. if asmsym<>'' then
  1663. begin
  1664. if maxvalue<>longint($ffffffff) then
  1665. Message1(asmr_w_const32bit_for_address,asmsym);
  1666. ConcatConstSymbol(curlist,asmsym,value)
  1667. end
  1668. else
  1669. ConcatConstant(curlist,value,maxvalue);
  1670. end;
  1671. AS_COMMA:
  1672. Consume(AS_COMMA);
  1673. AS_END,
  1674. AS_SEPARATOR:
  1675. break;
  1676. else
  1677. begin
  1678. Message(asmr_e_syn_constant);
  1679. RecoverConsume(false);
  1680. end
  1681. end;
  1682. Until false;
  1683. end;
  1684. Function Assemble: tnode;
  1685. Var
  1686. hl : tasmlabel;
  1687. instr : T386IntelInstruction;
  1688. Begin
  1689. Message1(asmr_d_start_reading,'intel');
  1690. inexpression:=FALSE;
  1691. firsttoken:=TRUE;
  1692. { sets up all opcode and register tables in uppercase }
  1693. if not _asmsorted then
  1694. Begin
  1695. SetupTables;
  1696. _asmsorted:=TRUE;
  1697. end;
  1698. curlist:=TAAsmoutput.Create;
  1699. { setup label linked list }
  1700. LocalLabelList:=TLocalLabelList.Create;
  1701. { start tokenizer }
  1702. c:=current_scanner.asmgetchar;
  1703. gettoken;
  1704. { main loop }
  1705. repeat
  1706. case actasmtoken of
  1707. AS_LLABEL:
  1708. Begin
  1709. if CreateLocalLabel(actasmpattern,hl,true) then
  1710. ConcatLabel(curlist,hl);
  1711. Consume(AS_LLABEL);
  1712. end;
  1713. AS_LABEL:
  1714. Begin
  1715. if SearchLabel(upper(actasmpattern),hl,true) then
  1716. ConcatLabel(curlist,hl)
  1717. else
  1718. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1719. Consume(AS_LABEL);
  1720. end;
  1721. AS_DW :
  1722. Begin
  1723. inexpression:=true;
  1724. Consume(AS_DW);
  1725. BuildConstant($ffff);
  1726. inexpression:=false;
  1727. end;
  1728. AS_DB :
  1729. Begin
  1730. inexpression:=true;
  1731. Consume(AS_DB);
  1732. BuildConstant($ff);
  1733. inexpression:=false;
  1734. end;
  1735. AS_DD :
  1736. Begin
  1737. inexpression:=true;
  1738. Consume(AS_DD);
  1739. BuildConstant(longint($ffffffff));
  1740. inexpression:=false;
  1741. end;
  1742. AS_OPCODE :
  1743. Begin
  1744. instr:=T386IntelInstruction.Create;
  1745. instr.BuildOpcode;
  1746. { We need AT&T style operands }
  1747. instr.Swapoperands;
  1748. { Must be done with args in ATT order }
  1749. instr.CheckNonCommutativeOpcodes;
  1750. instr.AddReferenceSizes;
  1751. instr.SetInstructionOpsize;
  1752. instr.CheckOperandSizes;
  1753. instr.ConcatInstruction(curlist);
  1754. instr.Free;
  1755. end;
  1756. AS_SEPARATOR :
  1757. Begin
  1758. Consume(AS_SEPARATOR);
  1759. end;
  1760. AS_END :
  1761. break; { end assembly block }
  1762. else
  1763. Begin
  1764. Message(asmr_e_syntax_error);
  1765. RecoverConsume(false);
  1766. end;
  1767. end; { end case }
  1768. until false;
  1769. { Check LocalLabelList }
  1770. LocalLabelList.CheckEmitted;
  1771. LocalLabelList.Free;
  1772. { Return the list in an asmnode }
  1773. assemble:=casmnode.create(curlist);
  1774. Message1(asmr_d_finish_reading,'intel');
  1775. end;
  1776. {*****************************************************************************
  1777. Initialize
  1778. *****************************************************************************}
  1779. const
  1780. asmmode_i386_intel_info : tasmmodeinfo =
  1781. (
  1782. id : asmmode_i386_intel;
  1783. idtxt : 'INTEL'
  1784. );
  1785. initialization
  1786. RegisterAsmMode(asmmode_i386_intel_info);
  1787. finalization
  1788. if assigned(iasmops) then
  1789. iasmops.Free;
  1790. end.
  1791. {
  1792. $Log$
  1793. Revision 1.62 2003-10-29 16:47:18 peter
  1794. * fix field offset in reference
  1795. Revision 1.61 2003/10/29 15:40:20 peter
  1796. * support indexing and offset retrieval for locals
  1797. Revision 1.60 2003/10/27 15:29:43 peter
  1798. * fixed trec.field to return constant
  1799. Revision 1.59 2003/10/24 17:39:03 peter
  1800. * more intel parser updates
  1801. Revision 1.58 2003/10/23 17:19:44 peter
  1802. * typecasting fixes
  1803. * reference building more delphi compatible
  1804. Revision 1.57 2003/10/21 18:17:40 peter
  1805. * ignore @ in Unit.@Proc
  1806. Revision 1.56 2003/10/10 17:48:14 peter
  1807. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  1808. * tregisteralloctor renamed to trgobj
  1809. * removed rgobj from a lot of units
  1810. * moved location_* and reference_* to cgobj
  1811. * first things for mmx register allocation
  1812. Revision 1.55 2003/10/07 18:21:18 peter
  1813. * fix crash
  1814. * allow parameter subscription for register parameters
  1815. Revision 1.54 2003/10/02 21:17:38 peter
  1816. * fix operand order when a prefix opcode is supplied
  1817. Revision 1.53 2003/10/01 20:34:49 peter
  1818. * procinfo unit contains tprocinfo
  1819. * cginfo renamed to cgbase
  1820. * moved cgmessage to verbose
  1821. * fixed ppc and sparc compiles
  1822. Revision 1.52 2003/09/23 20:37:53 peter
  1823. * fix global var+offset
  1824. Revision 1.51 2003/09/23 17:56:06 peter
  1825. * locals and paras are allocated in the code generation
  1826. * tvarsym.localloc contains the location of para/local when
  1827. generating code for the current procedure
  1828. Revision 1.50 2003/09/03 15:55:01 peter
  1829. * NEWRA branch merged
  1830. Revision 1.49.2.2 2003/08/31 15:46:26 peter
  1831. * more updates for tregister
  1832. Revision 1.49.2.1 2003/08/28 18:35:08 peter
  1833. * tregister changed to cardinal
  1834. Revision 1.49 2003/06/06 14:41:59 peter
  1835. * use setsize for size specifier
  1836. Revision 1.48 2003/05/30 23:57:08 peter
  1837. * more sparc cleanup
  1838. * accumulator removed, splitted in function_return_reg (called) and
  1839. function_result_reg (caller)
  1840. Revision 1.47 2003/04/30 15:45:35 florian
  1841. * merged more x86-64/i386 code
  1842. Revision 1.46 2003/04/27 11:21:35 peter
  1843. * aktprocdef renamed to current_procdef
  1844. * procinfo renamed to current_procinfo
  1845. * procinfo will now be stored in current_module so it can be
  1846. cleaned up properly
  1847. * gen_main_procsym changed to create_main_proc and release_main_proc
  1848. to also generate a tprocinfo structure
  1849. * fixed unit implicit initfinal
  1850. Revision 1.45 2003/04/21 20:05:10 peter
  1851. * removed some ie checks
  1852. Revision 1.44 2003/03/28 19:16:57 peter
  1853. * generic constructor working for i386
  1854. * remove fixed self register
  1855. * esi added as address register for i386
  1856. Revision 1.43 2003/03/18 18:15:53 peter
  1857. * changed reg2opsize to function
  1858. Revision 1.42 2003/03/17 21:32:52 peter
  1859. * allow character constants in reference declaration
  1860. Revision 1.41 2003/02/26 22:57:44 daniel
  1861. * Changed no longer correct fillchar of reference into location_reset
  1862. Revision 1.40 2003/02/19 22:00:16 daniel
  1863. * Code generator converted to new register notation
  1864. - Horribily outdated todo.txt removed
  1865. Revision 1.39 2003/01/08 18:43:57 daniel
  1866. * Tregister changed into a record
  1867. Revision 1.38 2002/12/14 15:02:03 carl
  1868. * maxoperands -> max_operands (for portability in rautils.pas)
  1869. * fix some range-check errors with loadconst
  1870. + add ncgadd unit to m68k
  1871. * some bugfix of a_param_reg with LOC_CREFERENCE
  1872. Revision 1.37 2002/12/01 22:08:34 carl
  1873. * some small cleanup (remove some specific operators which are not supported)
  1874. Revision 1.36 2002/11/15 01:58:59 peter
  1875. * merged changes from 1.0.7 up to 04-11
  1876. - -V option for generating bug report tracing
  1877. - more tracing for option parsing
  1878. - errors for cdecl and high()
  1879. - win32 import stabs
  1880. - win32 records<=8 are returned in eax:edx (turned off by default)
  1881. - heaptrc update
  1882. - more info for temp management in .s file with EXTDEBUG
  1883. Revision 1.35 2002/09/16 19:07:00 peter
  1884. * support [eax].constant as reference
  1885. Revision 1.34 2002/09/03 16:26:28 daniel
  1886. * Make Tprocdef.defs protected
  1887. Revision 1.33 2002/08/17 09:23:47 florian
  1888. * first part of procinfo rewrite
  1889. Revision 1.32 2002/08/13 18:01:52 carl
  1890. * rename swatoperands to swapoperands
  1891. + m68k first compilable version (still needs a lot of testing):
  1892. assembler generator, system information , inline
  1893. assembler reader.
  1894. Revision 1.31 2002/08/11 14:32:31 peter
  1895. * renamed current_library to objectlibrary
  1896. Revision 1.30 2002/08/11 13:24:17 peter
  1897. * saving of asmsymbols in ppu supported
  1898. * asmsymbollist global is removed and moved into a new class
  1899. tasmlibrarydata that will hold the info of a .a file which
  1900. corresponds with a single module. Added librarydata to tmodule
  1901. to keep the library info stored for the module. In the future the
  1902. objectfiles will also be stored to the tasmlibrarydata class
  1903. * all getlabel/newasmsymbol and friends are moved to the new class
  1904. Revision 1.29 2002/07/01 18:46:34 peter
  1905. * internal linker
  1906. * reorganized aasm layer
  1907. Revision 1.28 2002/05/18 13:34:26 peter
  1908. * readded missing revisions
  1909. Revision 1.27 2002/05/16 19:46:52 carl
  1910. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1911. + try to fix temp allocation (still in ifdef)
  1912. + generic constructor calls
  1913. + start of tassembler / tmodulebase class cleanup
  1914. Revision 1.25 2002/04/20 21:37:07 carl
  1915. + generic FPC_CHECKPOINTER
  1916. + first parameter offset in stack now portable
  1917. * rename some constants
  1918. + move some cpu stuff to other units
  1919. - remove unused constents
  1920. * fix stacksize for some targets
  1921. * fix generic size problems which depend now on EXTEND_SIZE constant
  1922. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  1923. Revision 1.24 2002/04/15 19:44:22 peter
  1924. * fixed stackcheck that would be called recursively when a stack
  1925. error was found
  1926. * generic changeregsize(reg,size) for i386 register resizing
  1927. * removed some more routines from cga unit
  1928. * fixed returnvalue handling
  1929. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  1930. Revision 1.23 2002/04/15 19:12:09 carl
  1931. + target_info.size_of_pointer -> pointer_size
  1932. + some cleanup of unused types/variables
  1933. * move several constants from cpubase to their specific units
  1934. (where they are used)
  1935. + att_Reg2str -> gas_reg2str
  1936. + int_reg2str -> std_reg2str
  1937. Revision 1.22 2002/04/04 19:06:13 peter
  1938. * removed unused units
  1939. * use tlocation.size in cg.a_*loc*() routines
  1940. Revision 1.21 2002/04/02 17:11:39 peter
  1941. * tlocation,treference update
  1942. * LOC_CONSTANT added for better constant handling
  1943. * secondadd splitted in multiple routines
  1944. * location_force_reg added for loading a location to a register
  1945. of a specified size
  1946. * secondassignment parses now first the right and then the left node
  1947. (this is compatible with Kylix). This saves a lot of push/pop especially
  1948. with string operations
  1949. * adapted some routines to use the new cg methods
  1950. Revision 1.20 2002/01/24 18:25:53 peter
  1951. * implicit result variable generation for assembler routines
  1952. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1953. }