ra386int.pas 74 KB

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