ra386int.pas 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186
  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_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 : t386operand);
  59. procedure BuildOperand(oper: t386operand);
  60. procedure BuildConstantOperand(oper: t386operand);
  61. procedure BuildOpCode(instr : t386instruction);
  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','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. errorflag : boolean;
  659. prevtok : tasmtoken;
  660. hl : tasmlabel;
  661. sym : tsym;
  662. srsymtable : tsymtable;
  663. Begin
  664. { reset }
  665. value:=0;
  666. asmsym:='';
  667. errorflag:=FALSE;
  668. tempstr:='';
  669. expr:='';
  670. inexpression:=TRUE;
  671. parenlevel:=0;
  672. Repeat
  673. Case actasmtoken of
  674. AS_LPAREN:
  675. Begin
  676. Consume(AS_LPAREN);
  677. expr:=expr + '(';
  678. inc(parenlevel);
  679. end;
  680. AS_RPAREN:
  681. Begin
  682. Consume(AS_RPAREN);
  683. expr:=expr + ')';
  684. dec(parenlevel);
  685. end;
  686. AS_SHL:
  687. Begin
  688. Consume(AS_SHL);
  689. expr:=expr + '<';
  690. end;
  691. AS_SHR:
  692. Begin
  693. Consume(AS_SHR);
  694. expr:=expr + '>';
  695. end;
  696. AS_SLASH:
  697. Begin
  698. Consume(AS_SLASH);
  699. expr:=expr + '/';
  700. end;
  701. AS_MOD:
  702. Begin
  703. Consume(AS_MOD);
  704. expr:=expr + '%';
  705. end;
  706. AS_STAR:
  707. Begin
  708. Consume(AS_STAR);
  709. if isref and (actasmtoken=AS_REGISTER) then
  710. break;
  711. expr:=expr + '*';
  712. end;
  713. AS_PLUS:
  714. Begin
  715. Consume(AS_PLUS);
  716. if isref and (actasmtoken=AS_REGISTER) then
  717. break;
  718. expr:=expr + '+';
  719. end;
  720. AS_LBRACKET:
  721. begin
  722. { Support ugly delphi constructs like: [ECX].1+2[EDX] }
  723. if isref then
  724. break;
  725. end;
  726. AS_MINUS:
  727. Begin
  728. Consume(AS_MINUS);
  729. expr:=expr + '-';
  730. end;
  731. AS_AND:
  732. Begin
  733. Consume(AS_AND);
  734. expr:=expr + '&';
  735. end;
  736. AS_NOT:
  737. Begin
  738. Consume(AS_NOT);
  739. expr:=expr + '~';
  740. end;
  741. AS_XOR:
  742. Begin
  743. Consume(AS_XOR);
  744. expr:=expr + '^';
  745. end;
  746. AS_OR:
  747. Begin
  748. Consume(AS_OR);
  749. expr:=expr + '|';
  750. end;
  751. AS_INTNUM:
  752. Begin
  753. expr:=expr + actasmpattern;
  754. Consume(AS_INTNUM);
  755. end;
  756. AS_OFFSET:
  757. begin
  758. Consume(AS_OFFSET);
  759. if actasmtoken<>AS_ID then
  760. Message(asmr_e_offset_without_identifier);
  761. end;
  762. AS_TYPE:
  763. begin
  764. l:=0;
  765. Consume(AS_TYPE);
  766. if actasmtoken<>AS_ID then
  767. Message(asmr_e_type_without_identifier)
  768. else
  769. begin
  770. tempstr:=actasmpattern;
  771. Consume(AS_ID);
  772. if actasmtoken=AS_DOT then
  773. BuildRecordOffsetSize(tempstr,k,l)
  774. else
  775. begin
  776. searchsym(tempstr,sym,srsymtable);
  777. if assigned(sym) then
  778. begin
  779. case sym.typ of
  780. varsym :
  781. l:=tvarsym(sym).getsize;
  782. typedconstsym :
  783. l:=ttypedconstsym(sym).getsize;
  784. typesym :
  785. l:=ttypesym(sym).restype.def.size;
  786. else
  787. Message(asmr_e_wrong_sym_type);
  788. end;
  789. end
  790. else
  791. Message1(sym_e_unknown_id,tempstr);
  792. end;
  793. end;
  794. str(l, tempstr);
  795. expr:=expr + tempstr;
  796. end;
  797. AS_STRING:
  798. Begin
  799. l:=0;
  800. case Length(actasmpattern) of
  801. 1 :
  802. l:=ord(actasmpattern[1]);
  803. 2 :
  804. l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
  805. 3 :
  806. l:=ord(actasmpattern[3]) +
  807. Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
  808. 4 :
  809. l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
  810. Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
  811. else
  812. Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
  813. end;
  814. str(l, tempstr);
  815. expr:=expr + tempstr;
  816. Consume(AS_STRING);
  817. end;
  818. AS_ID:
  819. Begin
  820. hs:='';
  821. tempstr:=actasmpattern;
  822. prevtok:=prevasmtoken;
  823. consume(AS_ID);
  824. if SearchIConstant(tempstr,l) then
  825. begin
  826. str(l, tempstr);
  827. expr:=expr + tempstr;
  828. end
  829. else
  830. begin
  831. if is_locallabel(tempstr) then
  832. begin
  833. CreateLocalLabel(tempstr,hl,false);
  834. hs:=hl.name
  835. end
  836. else
  837. if SearchLabel(tempstr,hl,false) then
  838. hs:=hl.name
  839. else
  840. begin
  841. searchsym(tempstr,sym,srsymtable);
  842. if assigned(sym) then
  843. begin
  844. case sym.typ of
  845. varsym :
  846. begin
  847. if sym.owner.symtabletype in [localsymtable,parasymtable] then
  848. Message(asmr_e_no_local_or_para_allowed);
  849. hs:=tvarsym(sym).mangledname;
  850. end;
  851. typedconstsym :
  852. hs:=ttypedconstsym(sym).mangledname;
  853. procsym :
  854. begin
  855. if Tprocsym(sym).procdef_count>1 then
  856. Message(asmr_w_calling_overload_func);
  857. hs:=tprocsym(sym).first_procdef.mangledname;
  858. end;
  859. typesym :
  860. begin
  861. if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
  862. Message(asmr_e_wrong_sym_type);
  863. end;
  864. else
  865. Message(asmr_e_wrong_sym_type);
  866. end;
  867. end
  868. else
  869. Message1(sym_e_unknown_id,tempstr);
  870. end;
  871. { symbol found? }
  872. if hs<>'' then
  873. begin
  874. if needofs and (prevtok<>AS_OFFSET) then
  875. Message(asmr_e_need_offset);
  876. if asmsym='' then
  877. asmsym:=hs
  878. else
  879. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  880. if (expr='') or (expr[length(expr)]='+') then
  881. begin
  882. { don't remove the + if there could be a record field }
  883. if actasmtoken<>AS_DOT then
  884. delete(expr,length(expr),1);
  885. end
  886. else
  887. Message(asmr_e_only_add_relocatable_symbol);
  888. end;
  889. if actasmtoken=AS_DOT then
  890. begin
  891. BuildRecordOffsetSize(tempstr,l,k);
  892. str(l, tempstr);
  893. expr:=expr + tempstr;
  894. end
  895. else
  896. begin
  897. if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
  898. delete(expr,length(expr),1);
  899. end;
  900. end;
  901. { check if there are wrong operator used like / or mod etc. }
  902. if (hs<>'') and not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END,AS_RBRACKET]) then
  903. Message(asmr_e_only_add_relocatable_symbol);
  904. end;
  905. AS_END,
  906. AS_RBRACKET,
  907. AS_SEPARATOR,
  908. AS_COMMA:
  909. Begin
  910. break;
  911. end;
  912. else
  913. Begin
  914. { write error only once. }
  915. if not errorflag then
  916. Message(asmr_e_invalid_constant_expression);
  917. { consume tokens until we find COMMA or SEPARATOR }
  918. Consume(actasmtoken);
  919. errorflag:=TRUE;
  920. end;
  921. end;
  922. Until false;
  923. { calculate expression }
  924. if not ErrorFlag then
  925. value:=CalculateExpression(expr)
  926. else
  927. value:=0;
  928. { no longer in an expression }
  929. inexpression:=FALSE;
  930. end;
  931. Function ti386intreader.BuildConstExpression:longint;
  932. var
  933. l : longint;
  934. hs : string;
  935. begin
  936. BuildConstSymbolExpression(false,false,l,hs);
  937. if hs<>'' then
  938. Message(asmr_e_relocatable_symbol_not_allowed);
  939. BuildConstExpression:=l;
  940. end;
  941. Function ti386intreader.BuildRefConstExpression:longint;
  942. var
  943. l : longint;
  944. hs : string;
  945. begin
  946. BuildConstSymbolExpression(false,true,l,hs);
  947. if hs<>'' then
  948. Message(asmr_e_relocatable_symbol_not_allowed);
  949. BuildRefConstExpression:=l;
  950. end;
  951. procedure ti386intreader.BuildReference(oper : t386operand);
  952. var
  953. k,l,scale : longint;
  954. tempstr,hs : string;
  955. typesize : longint;
  956. code : integer;
  957. hreg : tregister;
  958. GotStar,GotOffset,HadVar,
  959. GotPlus,Negative : boolean;
  960. Begin
  961. Consume(AS_LBRACKET);
  962. if not(oper.opr.typ in [OPR_LOCAL,OPR_REFERENCE]) then
  963. oper.InitRef;
  964. GotStar:=false;
  965. GotPlus:=true;
  966. GotOffset:=false;
  967. Negative:=false;
  968. Scale:=0;
  969. repeat
  970. if GotOffset and (actasmtoken<>AS_ID) then
  971. Message(asmr_e_invalid_reference_syntax);
  972. Case actasmtoken of
  973. AS_ID: { Constant reference expression OR variable reference expression }
  974. Begin
  975. if not GotPlus then
  976. Message(asmr_e_invalid_reference_syntax);
  977. if actasmpattern[1] = '@' then
  978. Message(asmr_e_local_label_not_allowed_as_ref);
  979. GotStar:=false;
  980. GotPlus:=false;
  981. if SearchIConstant(actasmpattern,l) or
  982. SearchRecordType(actasmpattern) then
  983. begin
  984. l:=BuildRefConstExpression;
  985. GotPlus:=(prevasmtoken=AS_PLUS);
  986. GotStar:=(prevasmtoken=AS_STAR);
  987. case oper.opr.typ of
  988. OPR_LOCAL :
  989. begin
  990. if GotStar then
  991. Message(asmr_e_invalid_reference_syntax);
  992. if negative then
  993. Dec(oper.opr.localsymofs,l)
  994. else
  995. Inc(oper.opr.localsymofs,l);
  996. end;
  997. OPR_REFERENCE :
  998. begin
  999. if GotStar then
  1000. oper.opr.ref.scalefactor:=l
  1001. else
  1002. begin
  1003. if negative then
  1004. Dec(oper.opr.ref.offset,l)
  1005. else
  1006. Inc(oper.opr.ref.offset,l);
  1007. end;
  1008. end;
  1009. end;
  1010. end
  1011. else
  1012. Begin
  1013. if oper.hasvar and not GotOffset then
  1014. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1015. HadVar:=oper.hasvar and GotOffset;
  1016. if negative then
  1017. Message(asmr_e_only_add_relocatable_symbol);
  1018. tempstr:=actasmpattern;
  1019. Consume(AS_ID);
  1020. { typecasting? }
  1021. if (actasmtoken=AS_LPAREN) and
  1022. SearchType(tempstr,typesize) then
  1023. begin
  1024. oper.hastype:=true;
  1025. Consume(AS_LPAREN);
  1026. BuildOperand(oper);
  1027. Consume(AS_RPAREN);
  1028. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  1029. oper.SetSize(typesize,true);
  1030. end
  1031. else
  1032. if not oper.SetupVar(tempstr,GotOffset) then
  1033. Message1(sym_e_unknown_id,tempstr);
  1034. { record.field ? }
  1035. if actasmtoken=AS_DOT then
  1036. begin
  1037. BuildRecordOffsetSize(tempstr,l,k);
  1038. case oper.opr.typ of
  1039. OPR_LOCAL :
  1040. inc(oper.opr.localsymofs,l);
  1041. OPR_REFERENCE :
  1042. inc(oper.opr.ref.offset,l);
  1043. end;
  1044. end;
  1045. if GotOffset then
  1046. begin
  1047. if oper.hasvar and (oper.opr.ref.base=current_procinfo.framepointer) then
  1048. begin
  1049. if (oper.opr.typ=OPR_REFERENCE) then
  1050. oper.opr.ref.base:=NR_NO;
  1051. oper.hasvar:=hadvar;
  1052. end
  1053. else
  1054. begin
  1055. if oper.hasvar and hadvar then
  1056. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1057. { should we allow ?? }
  1058. end;
  1059. end;
  1060. end;
  1061. GotOffset:=false;
  1062. end;
  1063. AS_PLUS :
  1064. Begin
  1065. Consume(AS_PLUS);
  1066. Negative:=false;
  1067. GotPlus:=true;
  1068. GotStar:=false;
  1069. Scale:=0;
  1070. end;
  1071. AS_MINUS :
  1072. begin
  1073. Consume(AS_MINUS);
  1074. Negative:=true;
  1075. GotPlus:=true;
  1076. GotStar:=false;
  1077. Scale:=0;
  1078. end;
  1079. AS_STAR : { Scaling, with eax*4 order }
  1080. begin
  1081. Consume(AS_STAR);
  1082. hs:='';
  1083. l:=0;
  1084. case actasmtoken of
  1085. AS_LPAREN :
  1086. l:=BuildConstExpression;
  1087. AS_INTNUM:
  1088. Begin
  1089. hs:=actasmpattern;
  1090. Consume(AS_INTNUM);
  1091. end;
  1092. AS_REGISTER :
  1093. begin
  1094. case oper.opr.typ of
  1095. OPR_REFERENCE :
  1096. begin
  1097. if oper.opr.ref.scalefactor=0 then
  1098. begin
  1099. if scale<>0 then
  1100. begin
  1101. oper.opr.ref.scalefactor:=scale;
  1102. scale:=0;
  1103. end
  1104. else
  1105. Message(asmr_e_wrong_scale_factor);
  1106. end
  1107. else
  1108. Message(asmr_e_invalid_reference_syntax);
  1109. end;
  1110. OPR_LOCAL :
  1111. begin
  1112. if oper.opr.localscale=0 then
  1113. begin
  1114. if scale<>0 then
  1115. begin
  1116. oper.opr.localscale:=scale;
  1117. scale:=0;
  1118. end
  1119. else
  1120. Message(asmr_e_wrong_scale_factor);
  1121. end
  1122. else
  1123. Message(asmr_e_invalid_reference_syntax);
  1124. end;
  1125. end;
  1126. end;
  1127. else
  1128. Message(asmr_e_invalid_reference_syntax);
  1129. end;
  1130. if actasmtoken<>AS_REGISTER then
  1131. begin
  1132. if hs<>'' then
  1133. val(hs,l,code);
  1134. case oper.opr.typ of
  1135. OPR_REFERENCE :
  1136. oper.opr.ref.scalefactor:=l;
  1137. OPR_LOCAL :
  1138. oper.opr.localscale:=l;
  1139. end;
  1140. if l>9 then
  1141. Message(asmr_e_wrong_scale_factor);
  1142. end;
  1143. GotPlus:=false;
  1144. GotStar:=false;
  1145. end;
  1146. AS_REGISTER :
  1147. begin
  1148. if not((GotPlus and (not Negative)) or
  1149. GotStar) then
  1150. Message(asmr_e_invalid_reference_syntax);
  1151. hreg:=actasmregister;
  1152. Consume(AS_REGISTER);
  1153. { this register will be the index:
  1154. 1. just read a *
  1155. 2. next token is a *
  1156. 3. base register is already used }
  1157. case oper.opr.typ of
  1158. OPR_LOCAL :
  1159. begin
  1160. if (oper.opr.localindexreg<>NR_NO) then
  1161. Message(asmr_e_multiple_index);
  1162. oper.opr.localindexreg:=hreg;
  1163. if scale<>0 then
  1164. begin
  1165. oper.opr.localscale:=scale;
  1166. scale:=0;
  1167. end;
  1168. end;
  1169. OPR_REFERENCE :
  1170. begin
  1171. if (GotStar) or
  1172. (actasmtoken=AS_STAR) or
  1173. (oper.opr.ref.base<>NR_NO) then
  1174. begin
  1175. if (oper.opr.ref.index<>NR_NO) then
  1176. Message(asmr_e_multiple_index);
  1177. oper.opr.ref.index:=hreg;
  1178. if scale<>0 then
  1179. begin
  1180. oper.opr.ref.scalefactor:=scale;
  1181. scale:=0;
  1182. end;
  1183. end
  1184. else
  1185. oper.opr.ref.base:=hreg;
  1186. end;
  1187. end;
  1188. GotPlus:=false;
  1189. GotStar:=false;
  1190. end;
  1191. AS_OFFSET :
  1192. begin
  1193. Consume(AS_OFFSET);
  1194. GotOffset:=true;
  1195. end;
  1196. AS_TYPE,
  1197. AS_NOT,
  1198. AS_STRING,
  1199. AS_INTNUM,
  1200. AS_LPAREN : { Constant reference expression }
  1201. begin
  1202. if not GotPlus and not GotStar then
  1203. Message(asmr_e_invalid_reference_syntax);
  1204. BuildConstSymbolExpression(true,true,l,tempstr);
  1205. if tempstr<>'' then
  1206. begin
  1207. if GotStar then
  1208. Message(asmr_e_only_add_relocatable_symbol);
  1209. if not assigned(oper.opr.ref.symbol) then
  1210. oper.opr.ref.symbol:=objectlibrary.newasmsymbol(tempstr)
  1211. else
  1212. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1213. end;
  1214. case oper.opr.typ of
  1215. OPR_REFERENCE :
  1216. begin
  1217. if GotStar then
  1218. oper.opr.ref.scalefactor:=l
  1219. else if (prevasmtoken = AS_STAR) then
  1220. begin
  1221. if scale<>0 then
  1222. scale:=l*scale
  1223. else
  1224. scale:=l;
  1225. end
  1226. else
  1227. begin
  1228. if negative then
  1229. Dec(oper.opr.ref.offset,l)
  1230. else
  1231. Inc(oper.opr.ref.offset,l);
  1232. end;
  1233. end;
  1234. OPR_LOCAL :
  1235. begin
  1236. if GotStar then
  1237. oper.opr.localscale:=l
  1238. else if (prevasmtoken = AS_STAR) then
  1239. begin
  1240. if scale<>0 then
  1241. scale:=l*scale
  1242. else
  1243. scale:=l;
  1244. end
  1245. else
  1246. begin
  1247. if negative then
  1248. Dec(oper.opr.localsymofs,l)
  1249. else
  1250. Inc(oper.opr.localsymofs,l);
  1251. end;
  1252. end;
  1253. end;
  1254. GotPlus:=(prevasmtoken=AS_PLUS) or
  1255. (prevasmtoken=AS_MINUS);
  1256. if GotPlus then
  1257. negative := prevasmtoken = AS_MINUS;
  1258. GotStar:=(prevasmtoken=AS_STAR);
  1259. end;
  1260. AS_RBRACKET :
  1261. begin
  1262. if GotPlus or GotStar then
  1263. Message(asmr_e_invalid_reference_syntax);
  1264. Consume(AS_RBRACKET);
  1265. break;
  1266. end;
  1267. else
  1268. Begin
  1269. Message(asmr_e_invalid_reference_syntax);
  1270. RecoverConsume(true);
  1271. break;
  1272. end;
  1273. end;
  1274. until false;
  1275. end;
  1276. Procedure ti386intreader.BuildConstantOperand(oper: t386operand);
  1277. var
  1278. l : longint;
  1279. tempstr : string;
  1280. begin
  1281. if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1282. Message(asmr_e_invalid_operand_type);
  1283. BuildConstSymbolExpression(true,false,l,tempstr);
  1284. if tempstr<>'' then
  1285. begin
  1286. oper.opr.typ:=OPR_SYMBOL;
  1287. oper.opr.symofs:=l;
  1288. oper.opr.symbol:=objectlibrary.newasmsymbol(tempstr);
  1289. end
  1290. else
  1291. begin
  1292. if oper.opr.typ=OPR_NONE then
  1293. begin
  1294. oper.opr.typ:=OPR_CONSTANT;
  1295. oper.opr.val:=l;
  1296. end
  1297. else
  1298. inc(oper.opr.val,l);
  1299. end;
  1300. end;
  1301. Procedure ti386intreader.BuildOperand(oper: t386operand);
  1302. procedure AddLabelOperand(hl:tasmlabel);
  1303. begin
  1304. if is_calljmp(actopcode) then
  1305. begin
  1306. oper.opr.typ:=OPR_SYMBOL;
  1307. oper.opr.symbol:=hl;
  1308. end
  1309. else
  1310. begin
  1311. oper.InitRef;
  1312. oper.opr.ref.symbol:=hl;
  1313. end;
  1314. end;
  1315. var
  1316. expr : string;
  1317. tempreg : tregister;
  1318. typesize,
  1319. l : longint;
  1320. hl : tasmlabel;
  1321. toffset,
  1322. tsize : longint;
  1323. Begin
  1324. expr:='';
  1325. repeat
  1326. if actasmtoken=AS_DOT then
  1327. begin
  1328. if expr<>'' then
  1329. begin
  1330. BuildRecordOffsetSize(expr,toffset,tsize);
  1331. oper.SetSize(tsize,true);
  1332. case oper.opr.typ of
  1333. OPR_LOCAL :
  1334. begin
  1335. { don't allow direct access to fields of parameters, becuase that
  1336. will generate buggy code. Allow it only for explicit typecasting
  1337. and when the parameter is in a register (delphi compatible) }
  1338. if (not oper.hastype) and
  1339. (tvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
  1340. (current_procinfo.procdef.proccalloption<>pocall_register) then
  1341. Message(asmr_e_cannot_access_field_directly_for_parameters);
  1342. inc(oper.opr.localsymofs,toffset)
  1343. end;
  1344. OPR_CONSTANT :
  1345. inc(oper.opr.val,toffset);
  1346. OPR_REFERENCE :
  1347. inc(oper.opr.ref.offset,toffset);
  1348. OPR_NONE :
  1349. begin
  1350. oper.opr.typ:=OPR_CONSTANT;
  1351. oper.opr.val:=toffset;
  1352. end;
  1353. else
  1354. internalerror(200309222);
  1355. end;
  1356. expr:='';
  1357. end
  1358. else
  1359. begin
  1360. { See it as a separator }
  1361. Consume(AS_DOT);
  1362. end;
  1363. end;
  1364. case actasmtoken of
  1365. AS_OFFSET,
  1366. AS_TYPE,
  1367. AS_NOT,
  1368. AS_STRING :
  1369. Begin
  1370. BuildConstantOperand(oper);
  1371. end;
  1372. AS_PLUS,
  1373. AS_MINUS,
  1374. AS_LPAREN,
  1375. AS_INTNUM :
  1376. begin
  1377. case oper.opr.typ of
  1378. OPR_REFERENCE :
  1379. inc(oper.opr.ref.offset,BuildRefConstExpression);
  1380. OPR_LOCAL :
  1381. inc(oper.opr.localsymofs,BuildConstExpression);
  1382. OPR_NONE,
  1383. OPR_CONSTANT :
  1384. BuildConstantOperand(oper);
  1385. else
  1386. Message(asmr_e_invalid_operand_type);
  1387. end;
  1388. end;
  1389. AS_ID : { A constant expression, or a Variable ref. }
  1390. Begin
  1391. { Label or Special symbol reference? }
  1392. if actasmpattern[1] = '@' then
  1393. Begin
  1394. if actasmpattern = '@RESULT' then
  1395. Begin
  1396. oper.SetupResult;
  1397. Consume(AS_ID);
  1398. end
  1399. else
  1400. if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
  1401. begin
  1402. Message(asmr_w_CODE_and_DATA_not_supported);
  1403. Consume(AS_ID);
  1404. end
  1405. else
  1406. { Local Label }
  1407. begin
  1408. CreateLocalLabel(actasmpattern,hl,false);
  1409. Consume(AS_ID);
  1410. AddLabelOperand(hl);
  1411. if not (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1412. Message(asmr_e_syntax_error);
  1413. end;
  1414. end
  1415. else
  1416. { support result for delphi modes }
  1417. if (m_objpas in aktmodeswitches) and (actasmpattern='RESULT') then
  1418. begin
  1419. oper.SetUpResult;
  1420. Consume(AS_ID);
  1421. end
  1422. { probably a variable or normal expression }
  1423. { or a procedure (such as in CALL ID) }
  1424. else
  1425. Begin
  1426. { is it a constant ? }
  1427. if SearchIConstant(actasmpattern,l) then
  1428. Begin
  1429. case oper.opr.typ of
  1430. OPR_REFERENCE :
  1431. inc(oper.opr.ref.offset,BuildRefConstExpression);
  1432. OPR_LOCAL :
  1433. inc(oper.opr.localsymofs,BuildRefConstExpression);
  1434. OPR_NONE,
  1435. OPR_CONSTANT :
  1436. BuildConstantOperand(oper);
  1437. else
  1438. Message(asmr_e_invalid_operand_type);
  1439. end;
  1440. end
  1441. else
  1442. { Check for pascal label }
  1443. if SearchLabel(actasmpattern,hl,false) then
  1444. begin
  1445. Consume(AS_ID);
  1446. AddLabelOperand(hl);
  1447. if not (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1448. Message(asmr_e_syntax_error);
  1449. end
  1450. else
  1451. { is it a normal variable ? }
  1452. Begin
  1453. expr:=actasmpattern;
  1454. Consume(AS_ID);
  1455. { typecasting? }
  1456. if SearchType(expr,typesize) then
  1457. begin
  1458. oper.hastype:=true;
  1459. if (actasmtoken=AS_LPAREN) then
  1460. begin
  1461. Consume(AS_LPAREN);
  1462. BuildOperand(oper);
  1463. Consume(AS_RPAREN);
  1464. if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
  1465. oper.SetSize(typesize,true);
  1466. end;
  1467. end
  1468. else
  1469. begin
  1470. if not oper.SetupVar(expr,false) then
  1471. Begin
  1472. { not a variable, check special variables.. }
  1473. if expr = 'SELF' then
  1474. oper.SetupSelf
  1475. else
  1476. Message1(sym_e_unknown_id,expr);
  1477. expr:='';
  1478. end;
  1479. end;
  1480. end;
  1481. end;
  1482. end;
  1483. AS_REGISTER : { Register, a variable reference or a constant reference }
  1484. begin
  1485. { save the type of register used. }
  1486. tempreg:=actasmregister;
  1487. Consume(AS_REGISTER);
  1488. if actasmtoken = AS_COLON then
  1489. Begin
  1490. Consume(AS_COLON);
  1491. oper.InitRef;
  1492. oper.opr.ref.segment:=tempreg;
  1493. BuildReference(oper);
  1494. end
  1495. else
  1496. { Simple register }
  1497. begin
  1498. if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1499. Message(asmr_e_invalid_operand_type);
  1500. oper.opr.typ:=OPR_REGISTER;
  1501. oper.opr.reg:=tempreg;
  1502. oper.SetSize(tcgsize2size[cg.reg_cgsize(oper.opr.reg)],true);
  1503. end;
  1504. end;
  1505. AS_LBRACKET: { a variable reference, register ref. or a constant reference }
  1506. Begin
  1507. BuildReference(oper);
  1508. end;
  1509. AS_SEG :
  1510. Begin
  1511. Message(asmr_e_seg_not_supported);
  1512. Consume(actasmtoken);
  1513. end;
  1514. AS_SEPARATOR,
  1515. AS_END,
  1516. AS_COMMA:
  1517. break;
  1518. else
  1519. Message(asmr_e_syn_operand);
  1520. end;
  1521. until not(actasmtoken in [AS_DOT,AS_PLUS,AS_LBRACKET]);
  1522. if not((actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) or
  1523. (oper.hastype and (actasmtoken=AS_RPAREN))) then
  1524. begin
  1525. Message(asmr_e_syntax_error);
  1526. RecoverConsume(true);
  1527. end;
  1528. end;
  1529. Procedure ti386intreader.BuildOpCode(instr : t386instruction);
  1530. var
  1531. PrefixOp,OverrideOp: tasmop;
  1532. size,
  1533. operandnum : longint;
  1534. Begin
  1535. PrefixOp:=A_None;
  1536. OverrideOp:=A_None;
  1537. { prefix seg opcode / prefix opcode }
  1538. repeat
  1539. if is_prefix(actopcode) then
  1540. begin
  1541. with instr do
  1542. begin
  1543. OpOrder:=op_intel;
  1544. PrefixOp:=ActOpcode;
  1545. opcode:=ActOpcode;
  1546. condition:=ActCondition;
  1547. opsize:=ActOpsize;
  1548. ConcatInstruction(curlist);
  1549. end;
  1550. Consume(AS_OPCODE);
  1551. end
  1552. else
  1553. if is_override(actopcode) then
  1554. begin
  1555. with instr do
  1556. begin
  1557. OpOrder:=op_intel;
  1558. OverrideOp:=ActOpcode;
  1559. opcode:=ActOpcode;
  1560. condition:=ActCondition;
  1561. opsize:=ActOpsize;
  1562. ConcatInstruction(curlist);
  1563. end;
  1564. Consume(AS_OPCODE);
  1565. end
  1566. else
  1567. break;
  1568. { allow for newline after prefix or override }
  1569. while actasmtoken=AS_SEPARATOR do
  1570. Consume(AS_SEPARATOR);
  1571. until (actasmtoken<>AS_OPCODE);
  1572. { opcode }
  1573. if (actasmtoken <> AS_OPCODE) then
  1574. Begin
  1575. Message(asmr_e_invalid_or_missing_opcode);
  1576. RecoverConsume(false);
  1577. exit;
  1578. end;
  1579. { Fill the instr object with the current state }
  1580. with instr do
  1581. begin
  1582. OpOrder:=op_intel;
  1583. Opcode:=ActOpcode;
  1584. condition:=ActCondition;
  1585. opsize:=ActOpsize;
  1586. { Valid combination of prefix/override and instruction ? }
  1587. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1588. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1589. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1590. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1591. end;
  1592. { We are reading operands, so opcode will be an AS_ID }
  1593. operandnum:=1;
  1594. Consume(AS_OPCODE);
  1595. { Zero operand opcode ? }
  1596. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1597. begin
  1598. operandnum:=0;
  1599. exit;
  1600. end;
  1601. { Read Operands }
  1602. repeat
  1603. case actasmtoken of
  1604. { End of asm operands for this opcode }
  1605. AS_END,
  1606. AS_SEPARATOR :
  1607. break;
  1608. { Operand delimiter }
  1609. AS_COMMA :
  1610. Begin
  1611. if operandnum > Max_Operands then
  1612. Message(asmr_e_too_many_operands)
  1613. else
  1614. Inc(operandnum);
  1615. Consume(AS_COMMA);
  1616. end;
  1617. { Typecast, Constant Expression, Type Specifier }
  1618. AS_DWORD,
  1619. AS_BYTE,
  1620. AS_WORD,
  1621. AS_TBYTE,
  1622. AS_QWORD :
  1623. Begin
  1624. { load the size in a temp variable, so it can be set when the
  1625. operand is read }
  1626. size:=0;
  1627. Case actasmtoken of
  1628. AS_DWORD : size:=4;
  1629. AS_WORD : size:=2;
  1630. AS_BYTE : size:=1;
  1631. AS_QWORD : size:=8;
  1632. AS_TBYTE : size:=extended_size;
  1633. end;
  1634. Consume(actasmtoken);
  1635. if actasmtoken=AS_PTR then
  1636. begin
  1637. Consume(AS_PTR);
  1638. instr.Operands[operandnum].InitRef;
  1639. end;
  1640. BuildOperand(instr.Operands[operandnum] as t386operand);
  1641. { now set the size which was specified by the override }
  1642. instr.Operands[operandnum].setsize(size,true);
  1643. end;
  1644. { Type specifier }
  1645. AS_NEAR,
  1646. AS_FAR :
  1647. Begin
  1648. if actasmtoken = AS_NEAR then
  1649. begin
  1650. Message(asmr_w_near_ignored);
  1651. instr.opsize:=S_NEAR;
  1652. end
  1653. else
  1654. begin
  1655. Message(asmr_w_far_ignored);
  1656. instr.opsize:=S_FAR;
  1657. end;
  1658. Consume(actasmtoken);
  1659. if actasmtoken=AS_PTR then
  1660. begin
  1661. Consume(AS_PTR);
  1662. instr.Operands[operandnum].InitRef;
  1663. end;
  1664. BuildOperand(instr.Operands[operandnum] as t386operand);
  1665. end;
  1666. else
  1667. BuildOperand(instr.Operands[operandnum] as t386operand);
  1668. end; { end case }
  1669. until false;
  1670. instr.Ops:=operandnum;
  1671. end;
  1672. Procedure ti386intreader.BuildConstant(maxvalue: longint);
  1673. var
  1674. strlength: byte;
  1675. asmsym,
  1676. expr: string;
  1677. value : longint;
  1678. Begin
  1679. strlength:=0; { assume it is a DB }
  1680. Repeat
  1681. Case actasmtoken of
  1682. AS_STRING:
  1683. Begin
  1684. if maxvalue = $ffff then
  1685. strlength:=2
  1686. else
  1687. if maxvalue = longint($ffffffff) then
  1688. strlength:=4;
  1689. { DD and DW cases }
  1690. if strlength <> 0 then
  1691. Begin
  1692. if Not PadZero(actasmpattern,strlength) then
  1693. Message(scan_f_string_exceeds_line);
  1694. end;
  1695. expr:=actasmpattern;
  1696. Consume(AS_STRING);
  1697. Case actasmtoken of
  1698. AS_COMMA:
  1699. Consume(AS_COMMA);
  1700. AS_END,
  1701. AS_SEPARATOR: ;
  1702. else
  1703. Message(asmr_e_invalid_string_expression);
  1704. end;
  1705. ConcatString(curlist,expr);
  1706. end;
  1707. AS_PLUS,
  1708. AS_MINUS,
  1709. AS_LPAREN,
  1710. AS_NOT,
  1711. AS_INTNUM,
  1712. AS_ID :
  1713. Begin
  1714. BuildConstSymbolExpression(false,false,value,asmsym);
  1715. if asmsym<>'' then
  1716. begin
  1717. if maxvalue<>longint($ffffffff) then
  1718. Message1(asmr_w_const32bit_for_address,asmsym);
  1719. ConcatConstSymbol(curlist,asmsym,value)
  1720. end
  1721. else
  1722. ConcatConstant(curlist,value,maxvalue);
  1723. end;
  1724. AS_COMMA:
  1725. Consume(AS_COMMA);
  1726. AS_END,
  1727. AS_SEPARATOR:
  1728. break;
  1729. else
  1730. begin
  1731. Message(asmr_e_syn_constant);
  1732. RecoverConsume(false);
  1733. end
  1734. end;
  1735. Until false;
  1736. end;
  1737. function ti386intreader.Assemble: tlinkedlist;
  1738. Var
  1739. hl : tasmlabel;
  1740. instr : T386Instruction;
  1741. Begin
  1742. Message1(asmr_d_start_reading,'intel');
  1743. inexpression:=FALSE;
  1744. firsttoken:=TRUE;
  1745. { sets up all opcode and register tables in uppercase
  1746. done in the construtor now
  1747. if not _asmsorted then
  1748. Begin
  1749. SetupTables;
  1750. _asmsorted:=TRUE;
  1751. end;
  1752. }
  1753. curlist:=TAAsmoutput.Create;
  1754. { setup label linked list }
  1755. LocalLabelList:=TLocalLabelList.Create;
  1756. { start tokenizer }
  1757. c:=current_scanner.asmgetcharstart;
  1758. gettoken;
  1759. { main loop }
  1760. repeat
  1761. case actasmtoken of
  1762. AS_LLABEL:
  1763. Begin
  1764. if CreateLocalLabel(actasmpattern,hl,true) then
  1765. ConcatLabel(curlist,hl);
  1766. Consume(AS_LLABEL);
  1767. end;
  1768. AS_LABEL:
  1769. Begin
  1770. if SearchLabel(upper(actasmpattern),hl,true) then
  1771. ConcatLabel(curlist,hl)
  1772. else
  1773. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1774. Consume(AS_LABEL);
  1775. end;
  1776. AS_DW :
  1777. Begin
  1778. inexpression:=true;
  1779. Consume(AS_DW);
  1780. BuildConstant($ffff);
  1781. inexpression:=false;
  1782. end;
  1783. AS_DB :
  1784. Begin
  1785. inexpression:=true;
  1786. Consume(AS_DB);
  1787. BuildConstant($ff);
  1788. inexpression:=false;
  1789. end;
  1790. AS_DD :
  1791. Begin
  1792. inexpression:=true;
  1793. Consume(AS_DD);
  1794. BuildConstant(longint($ffffffff));
  1795. inexpression:=false;
  1796. end;
  1797. AS_OPCODE :
  1798. Begin
  1799. instr:=T386Instruction.Create(T386Operand);
  1800. BuildOpcode(instr);
  1801. with instr do
  1802. begin
  1803. { We need AT&T style operands }
  1804. Swapoperands;
  1805. { Must be done with args in ATT order }
  1806. CheckNonCommutativeOpcodes;
  1807. AddReferenceSizes;
  1808. SetInstructionOpsize;
  1809. CheckOperandSizes;
  1810. ConcatInstruction(curlist);
  1811. end;
  1812. instr.Free;
  1813. end;
  1814. AS_SEPARATOR :
  1815. Begin
  1816. Consume(AS_SEPARATOR);
  1817. end;
  1818. AS_END :
  1819. break; { end assembly block }
  1820. else
  1821. Begin
  1822. Message(asmr_e_syntax_error);
  1823. RecoverConsume(false);
  1824. end;
  1825. end; { end case }
  1826. until false;
  1827. { Check LocalLabelList }
  1828. LocalLabelList.CheckEmitted;
  1829. LocalLabelList.Free;
  1830. { Return the list in an asmnode }
  1831. assemble:=curlist;
  1832. Message1(asmr_d_finish_reading,'intel');
  1833. end;
  1834. {*****************************************************************************
  1835. Initialize
  1836. *****************************************************************************}
  1837. const
  1838. asmmode_i386_intel_info : tasmmodeinfo =
  1839. (
  1840. id : asmmode_i386_intel;
  1841. idtxt : 'INTEL';
  1842. casmreader : ti386intreader;
  1843. );
  1844. begin
  1845. RegisterAsmMode(asmmode_i386_intel_info);
  1846. end.
  1847. {
  1848. $Log$
  1849. Revision 1.65 2003-11-12 16:05:39 florian
  1850. * assembler readers OOPed
  1851. + typed currency constants
  1852. + typed 128 bit float constants if the CPU supports it
  1853. Revision 1.64 2003/11/10 19:08:32 peter
  1854. * line numbering is now only done when #10, #10#13 is really parsed
  1855. instead of when it is the next character
  1856. Revision 1.63 2003/10/30 19:59:00 peter
  1857. * support scalefactor for opr_local
  1858. * support reference with opr_local set, fixes tw2631
  1859. Revision 1.62 2003/10/29 16:47:18 peter
  1860. * fix field offset in reference
  1861. Revision 1.61 2003/10/29 15:40:20 peter
  1862. * support indexing and offset retrieval for locals
  1863. Revision 1.60 2003/10/27 15:29:43 peter
  1864. * fixed trec.field to return constant
  1865. Revision 1.59 2003/10/24 17:39:03 peter
  1866. * more intel parser updates
  1867. Revision 1.58 2003/10/23 17:19:44 peter
  1868. * typecasting fixes
  1869. * reference building more delphi compatible
  1870. Revision 1.57 2003/10/21 18:17:40 peter
  1871. * ignore @ in Unit.@Proc
  1872. Revision 1.56 2003/10/10 17:48:14 peter
  1873. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  1874. * tregisteralloctor renamed to trgobj
  1875. * removed rgobj from a lot of units
  1876. * moved location_* and reference_* to cgobj
  1877. * first things for mmx register allocation
  1878. Revision 1.55 2003/10/07 18:21:18 peter
  1879. * fix crash
  1880. * allow parameter subscription for register parameters
  1881. Revision 1.54 2003/10/02 21:17:38 peter
  1882. * fix operand order when a prefix opcode is supplied
  1883. Revision 1.53 2003/10/01 20:34:49 peter
  1884. * procinfo unit contains tprocinfo
  1885. * cginfo renamed to cgbase
  1886. * moved cgmessage to verbose
  1887. * fixed ppc and sparc compiles
  1888. Revision 1.52 2003/09/23 20:37:53 peter
  1889. * fix global var+offset
  1890. Revision 1.51 2003/09/23 17:56:06 peter
  1891. * locals and paras are allocated in the code generation
  1892. * tvarsym.localloc contains the location of para/local when
  1893. generating code for the current procedure
  1894. Revision 1.50 2003/09/03 15:55:01 peter
  1895. * NEWRA branch merged
  1896. Revision 1.49.2.2 2003/08/31 15:46:26 peter
  1897. * more updates for tregister
  1898. Revision 1.49.2.1 2003/08/28 18:35:08 peter
  1899. * tregister changed to cardinal
  1900. Revision 1.49 2003/06/06 14:41:59 peter
  1901. * use setsize for size specifier
  1902. Revision 1.48 2003/05/30 23:57:08 peter
  1903. * more sparc cleanup
  1904. * accumulator removed, splitted in function_return_reg (called) and
  1905. function_result_reg (caller)
  1906. Revision 1.47 2003/04/30 15:45:35 florian
  1907. * merged more x86-64/i386 code
  1908. Revision 1.46 2003/04/27 11:21:35 peter
  1909. * aktprocdef renamed to current_procdef
  1910. * procinfo renamed to current_procinfo
  1911. * procinfo will now be stored in current_module so it can be
  1912. cleaned up properly
  1913. * gen_main_procsym changed to create_main_proc and release_main_proc
  1914. to also generate a tprocinfo structure
  1915. * fixed unit implicit initfinal
  1916. Revision 1.45 2003/04/21 20:05:10 peter
  1917. * removed some ie checks
  1918. Revision 1.44 2003/03/28 19:16:57 peter
  1919. * generic constructor working for i386
  1920. * remove fixed self register
  1921. * esi added as address register for i386
  1922. Revision 1.43 2003/03/18 18:15:53 peter
  1923. * changed reg2opsize to function
  1924. Revision 1.42 2003/03/17 21:32:52 peter
  1925. * allow character constants in reference declaration
  1926. Revision 1.41 2003/02/26 22:57:44 daniel
  1927. * Changed no longer correct fillchar of reference into location_reset
  1928. Revision 1.40 2003/02/19 22:00:16 daniel
  1929. * Code generator converted to new register notation
  1930. - Horribily outdated todo.txt removed
  1931. Revision 1.39 2003/01/08 18:43:57 daniel
  1932. * Tregister changed into a record
  1933. Revision 1.38 2002/12/14 15:02:03 carl
  1934. * maxoperands -> max_operands (for portability in rautils.pas)
  1935. * fix some range-check errors with loadconst
  1936. + add ncgadd unit to m68k
  1937. * some bugfix of a_param_reg with LOC_CREFERENCE
  1938. Revision 1.37 2002/12/01 22:08:34 carl
  1939. * some small cleanup (remove some specific operators which are not supported)
  1940. Revision 1.36 2002/11/15 01:58:59 peter
  1941. * merged changes from 1.0.7 up to 04-11
  1942. - -V option for generating bug report tracing
  1943. - more tracing for option parsing
  1944. - errors for cdecl and high()
  1945. - win32 import stabs
  1946. - win32 records<=8 are returned in eax:edx (turned off by default)
  1947. - heaptrc update
  1948. - more info for temp management in .s file with EXTDEBUG
  1949. Revision 1.35 2002/09/16 19:07:00 peter
  1950. * support [eax].constant as reference
  1951. Revision 1.34 2002/09/03 16:26:28 daniel
  1952. * Make Tprocdef.defs protected
  1953. Revision 1.33 2002/08/17 09:23:47 florian
  1954. * first part of procinfo rewrite
  1955. Revision 1.32 2002/08/13 18:01:52 carl
  1956. * rename swatoperands to swapoperands
  1957. + m68k first compilable version (still needs a lot of testing):
  1958. assembler generator, system information , inline
  1959. assembler reader.
  1960. Revision 1.31 2002/08/11 14:32:31 peter
  1961. * renamed current_library to objectlibrary
  1962. Revision 1.30 2002/08/11 13:24:17 peter
  1963. * saving of asmsymbols in ppu supported
  1964. * asmsymbollist global is removed and moved into a new class
  1965. tasmlibrarydata that will hold the info of a .a file which
  1966. corresponds with a single module. Added librarydata to tmodule
  1967. to keep the library info stored for the module. In the future the
  1968. objectfiles will also be stored to the tasmlibrarydata class
  1969. * all getlabel/newasmsymbol and friends are moved to the new class
  1970. Revision 1.29 2002/07/01 18:46:34 peter
  1971. * internal linker
  1972. * reorganized aasm layer
  1973. Revision 1.28 2002/05/18 13:34:26 peter
  1974. * readded missing revisions
  1975. Revision 1.27 2002/05/16 19:46:52 carl
  1976. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1977. + try to fix temp allocation (still in ifdef)
  1978. + generic constructor calls
  1979. + start of tassembler / tmodulebase class cleanup
  1980. Revision 1.25 2002/04/20 21:37:07 carl
  1981. + generic FPC_CHECKPOINTER
  1982. + first parameter offset in stack now portable
  1983. * rename some constants
  1984. + move some cpu stuff to other units
  1985. - remove unused constents
  1986. * fix stacksize for some targets
  1987. * fix generic size problems which depend now on EXTEND_SIZE constant
  1988. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  1989. Revision 1.24 2002/04/15 19:44:22 peter
  1990. * fixed stackcheck that would be called recursively when a stack
  1991. error was found
  1992. * generic changeregsize(reg,size) for i386 register resizing
  1993. * removed some more routines from cga unit
  1994. * fixed returnvalue handling
  1995. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  1996. Revision 1.23 2002/04/15 19:12:09 carl
  1997. + target_info.size_of_pointer -> pointer_size
  1998. + some cleanup of unused types/variables
  1999. * move several constants from cpubase to their specific units
  2000. (where they are used)
  2001. + att_Reg2str -> gas_reg2str
  2002. + int_reg2str -> std_reg2str
  2003. Revision 1.22 2002/04/04 19:06:13 peter
  2004. * removed unused units
  2005. * use tlocation.size in cg.a_*loc*() routines
  2006. Revision 1.21 2002/04/02 17:11:39 peter
  2007. * tlocation,treference update
  2008. * LOC_CONSTANT added for better constant handling
  2009. * secondadd splitted in multiple routines
  2010. * location_force_reg added for loading a location to a register
  2011. of a specified size
  2012. * secondassignment parses now first the right and then the left node
  2013. (this is compatible with Kylix). This saves a lot of push/pop especially
  2014. with string operations
  2015. * adapted some routines to use the new cg methods
  2016. Revision 1.20 2002/01/24 18:25:53 peter
  2017. * implicit result variable generation for assembler routines
  2018. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  2019. }