ra386int.pas 74 KB

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