rautils.pas 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. This unit implements some support routines for assembler parsing
  5. independent of the processor
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. **********************************************************************}
  18. Unit RAUtils;
  19. {$i fpcdefs.inc}
  20. Interface
  21. Uses
  22. cutils,cclasses,
  23. globtype,aasmbase,aasmtai,cpubase,cpuinfo,
  24. symconst,symbase,symtype,symdef;
  25. Const
  26. RPNMax = 10; { I think you only need 4, but just to be safe }
  27. OpMax = 25;
  28. maxoperands = 3; { Maximum operands for assembler instructions }
  29. {---------------------------------------------------------------------
  30. Local Label Management
  31. ---------------------------------------------------------------------}
  32. Type
  33. { Each local label has this structure associated with it }
  34. TLocalLabel = class(TNamedIndexItem)
  35. Emitted : boolean;
  36. constructor Create(const n:string);
  37. function Gettasmlabel:tasmlabel;
  38. private
  39. lab : tasmlabel;
  40. end;
  41. TLocalLabelList = class(TDictionary)
  42. procedure CheckEmitted;
  43. end;
  44. var
  45. LocalLabelList : TLocalLabelList;
  46. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  47. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  48. {---------------------------------------------------------------------
  49. Instruction management
  50. ---------------------------------------------------------------------}
  51. type
  52. TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,
  53. OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST);
  54. TOprRec = record
  55. case typ:TOprType of
  56. OPR_NONE : ();
  57. OPR_CONSTANT : (val:longint);
  58. OPR_SYMBOL : (symbol:tasmsymbol;symofs:longint);
  59. OPR_REFERENCE : (ref:treference);
  60. OPR_REGISTER : (reg:tregister);
  61. {$ifdef m68k}
  62. OPR_REGLIST : (reglist:tregisterlist);
  63. {$else not m68k}
  64. OPR_REGLIST : ();
  65. {$endif m68k}
  66. end;
  67. TOperand = class
  68. size : topsize;
  69. hastype, { if the operand has typecasted variable }
  70. hasvar : boolean; { if the operand is loaded with a variable }
  71. opr : TOprRec;
  72. constructor create;
  73. destructor destroy;override;
  74. Procedure BuildOperand;virtual;
  75. Procedure SetSize(_size:longint;force:boolean);
  76. Procedure SetCorrectSize(opcode:tasmop);virtual;
  77. Function SetupResult:boolean;virtual;
  78. Function SetupSelf:boolean;
  79. Function SetupOldEBP:boolean;
  80. Function SetupVar(const s:string;GetOffset : boolean): Boolean;
  81. Function SetupDirectVar(const hs:string): Boolean;
  82. Procedure InitRef;
  83. end;
  84. TInstruction = class
  85. opcode : tasmop;
  86. opsize : topsize;
  87. condition : tasmcond;
  88. ops : byte;
  89. labeled : boolean;
  90. operands : array[1..maxoperands] of toperand;
  91. constructor create;
  92. destructor destroy;override;
  93. Procedure InitOperands;virtual;
  94. Procedure BuildOpcode;virtual;
  95. procedure ConcatInstruction(p:TAAsmoutput);virtual;
  96. Procedure Swapoperands;
  97. end;
  98. {---------------------------------------------------------------------}
  99. { Expression parser types }
  100. {---------------------------------------------------------------------}
  101. TExprOperator = record
  102. ch: char; { operator }
  103. is_prefix: boolean; { was it a prefix, possible prefixes are +,- and not }
  104. end;
  105. String15 = String[15];
  106. {**********************************************************************}
  107. { The following operators are supported: }
  108. { '+' : addition }
  109. { '-' : subtraction }
  110. { '*' : multiplication }
  111. { '/' : modulo division }
  112. { '^' : exclusive or }
  113. { '<' : shift left }
  114. { '>' : shift right }
  115. { '&' : bitwise and }
  116. { '|' : bitwise or }
  117. { '~' : bitwise complement }
  118. { '%' : modulo division }
  119. { nnn: longint numbers }
  120. { ( and ) parenthesis }
  121. {**********************************************************************}
  122. TExprParse = class
  123. public
  124. Constructor create;
  125. Destructor Destroy;override;
  126. Function Evaluate(Expr: String): longint;
  127. Function Priority(_Operator: Char): longint;
  128. private
  129. RPNStack : Array[1..RPNMax] of longint; { Stack For RPN calculator }
  130. RPNTop : longint;
  131. OpStack : Array[1..OpMax] of TExprOperator; { Operator stack For conversion }
  132. OpTop : longint;
  133. Procedure RPNPush(Num: Longint);
  134. Function RPNPop: Longint;
  135. Procedure RPNCalc(token: String15; prefix: boolean);
  136. Procedure OpPush(_Operator: char; prefix: boolean);
  137. { In reality returns TExprOperaotr }
  138. Procedure OpPop(var _Operator:TExprOperator);
  139. end;
  140. { Evaluate an expression string to a longint }
  141. Function CalculateExpression(const expression: string): longint;
  142. {---------------------------------------------------------------------}
  143. { String routines }
  144. {---------------------------------------------------------------------}
  145. Function ValDecimal(const S:String):longint;
  146. Function ValOctal(const S:String):longint;
  147. Function ValBinary(const S:String):longint;
  148. Function ValHexaDecimal(const S:String):longint;
  149. Function PadZero(Var s: String; n: byte): Boolean;
  150. Function EscapeToPascal(const s:string): string;
  151. {---------------------------------------------------------------------
  152. Symbol helper routines
  153. ---------------------------------------------------------------------}
  154. procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:tsymtable);
  155. Function GetRecordOffsetSize(s:string;Var Offset: longint;var Size:longint):boolean;
  156. Function SearchType(const hs:string): Boolean;
  157. Function SearchRecordType(const s:string): boolean;
  158. Function SearchIConstant(const s:string; var l:longint): boolean;
  159. {---------------------------------------------------------------------
  160. Instruction generation routines
  161. ---------------------------------------------------------------------}
  162. Procedure ConcatPasString(p : TAAsmoutput;s:string);
  163. Procedure ConcatDirect(p : TAAsmoutput;s:string);
  164. Procedure ConcatLabel(p: TAAsmoutput;var l : tasmlabel);
  165. Procedure ConcatConstant(p : TAAsmoutput;value: longint; maxvalue: longint);
  166. Procedure ConcatConstSymbol(p : TAAsmoutput;const sym:string;l:longint);
  167. Procedure ConcatRealConstant(p : TAAsmoutput;value: bestreal; real_typ : tfloattype);
  168. Procedure ConcatString(p : TAAsmoutput;s:string);
  169. procedure ConcatAlign(p:TAAsmoutput;l:longint);
  170. Procedure ConcatPublic(p:TAAsmoutput;const s : string);
  171. Procedure ConcatLocal(p:TAAsmoutput;const s : string);
  172. Procedure ConcatGlobalBss(const s : string;size : longint);
  173. Procedure ConcatLocalBss(const s : string;size : longint);
  174. Implementation
  175. uses
  176. {$ifdef delphi}
  177. sysutils,
  178. {$else}
  179. strings,
  180. {$endif}
  181. defbase,systems,verbose,globals,
  182. symsym,symtable,paramgr,
  183. aasmcpu,
  184. cgbase;
  185. {*************************************************************************
  186. TExprParse
  187. *************************************************************************}
  188. Constructor TExprParse.create;
  189. Begin
  190. end;
  191. Procedure TExprParse.RPNPush(Num : longint);
  192. { Add an operand to the top of the RPN stack }
  193. begin
  194. if RPNTop < RPNMax then
  195. begin
  196. Inc(RPNTop);
  197. RPNStack[RPNTop]:=Num;
  198. end
  199. else
  200. Message(asmr_e_expr_illegal);
  201. end;
  202. Function TExprParse.RPNPop : longint;
  203. { Get the operand at the top of the RPN stack }
  204. begin
  205. if RPNTop > 0 then
  206. begin
  207. RPNPop:=RPNStack[RPNTop];
  208. Dec(RPNTop);
  209. end
  210. else
  211. Message(asmr_e_expr_illegal);
  212. end;
  213. Procedure TExprParse.RPNCalc(Token : String15; prefix:boolean); { RPN Calculator }
  214. Var
  215. Temp : longint;
  216. n1,n2 : longint;
  217. LocalError : Integer;
  218. begin
  219. { Handle operators }
  220. if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/','&','|','%','^','~','<','>']) then
  221. Case Token[1] of
  222. '+' :
  223. Begin
  224. if not prefix then
  225. RPNPush(RPNPop + RPNPop);
  226. end;
  227. '-' :
  228. Begin
  229. if prefix then
  230. RPNPush(-(RPNPop))
  231. else
  232. begin
  233. n1:=RPNPop;
  234. n2:=RPNPop;
  235. RPNPush(n2 - n1);
  236. end;
  237. end;
  238. '*' : RPNPush(RPNPop * RPNPop);
  239. '&' :
  240. begin
  241. n1:=RPNPop;
  242. n2:=RPNPop;
  243. RPNPush(n2 and n1);
  244. end;
  245. '|' :
  246. begin
  247. n1:=RPNPop;
  248. n2:=RPNPop;
  249. RPNPush(n2 or n1);
  250. end;
  251. '~' : RPNPush(NOT RPNPop);
  252. '<' :
  253. begin
  254. n1:=RPNPop;
  255. n2:=RPNPop;
  256. RPNPush(n2 SHL n1);
  257. end;
  258. '>' :
  259. begin
  260. n1:=RPNPop;
  261. n2:=RPNPop;
  262. RPNPush(n2 SHR n1);
  263. end;
  264. '%' :
  265. begin
  266. Temp:=RPNPop;
  267. if Temp <> 0 then
  268. RPNPush(RPNPop mod Temp)
  269. else
  270. begin
  271. Message(asmr_e_expr_zero_divide);
  272. { push 1 for error recovery }
  273. RPNPush(1);
  274. end;
  275. end;
  276. '^' : RPNPush(RPNPop XOR RPNPop);
  277. '/' :
  278. begin
  279. Temp:=RPNPop;
  280. if Temp <> 0 then
  281. RPNPush(RPNPop div Temp)
  282. else
  283. begin
  284. Message(asmr_e_expr_zero_divide);
  285. { push 1 for error recovery }
  286. RPNPush(1);
  287. end;
  288. end;
  289. end
  290. else
  291. begin
  292. { Convert String to number and add to stack }
  293. Val(Token, Temp, LocalError);
  294. if LocalError = 0 then
  295. RPNPush(Temp)
  296. else
  297. begin
  298. Message(asmr_e_expr_illegal);
  299. { push 1 for error recovery }
  300. RPNPush(1);
  301. end;
  302. end;
  303. end;
  304. Procedure TExprParse.OpPush(_Operator : char;prefix: boolean);
  305. { Add an operator onto top of the stack }
  306. begin
  307. if OpTop < OpMax then
  308. begin
  309. Inc(OpTop);
  310. OpStack[OpTop].ch:=_Operator;
  311. OpStack[OpTop].is_prefix:=prefix;
  312. end
  313. else
  314. Message(asmr_e_expr_illegal);
  315. end;
  316. Procedure TExprParse.OpPop(var _Operator:TExprOperator);
  317. { Get operator at the top of the stack }
  318. begin
  319. if OpTop > 0 then
  320. begin
  321. _Operator:=OpStack[OpTop];
  322. Dec(OpTop);
  323. end
  324. else
  325. Message(asmr_e_expr_illegal);
  326. end;
  327. Function TExprParse.Priority(_Operator : Char) : longint;
  328. { Return priority of operator }
  329. { The greater the priority, the higher the precedence }
  330. begin
  331. Case _Operator OF
  332. '(' :
  333. Priority:=0;
  334. '+', '-' :
  335. Priority:=1;
  336. '*', '/','%','<','>' :
  337. Priority:=2;
  338. '|','&','^','~' :
  339. Priority:=0;
  340. else
  341. Message(asmr_e_expr_illegal);
  342. end;
  343. end;
  344. Function TExprParse.Evaluate(Expr : String):longint;
  345. Var
  346. I : LongInt;
  347. Token : String15;
  348. opr : TExprOperator;
  349. begin
  350. Evaluate:=0;
  351. { Reset stacks }
  352. OpTop :=0;
  353. RPNTop:=0;
  354. Token :='';
  355. { nothing to do ? }
  356. if Expr='' then
  357. exit;
  358. For I:=1 to Length(Expr) DO
  359. begin
  360. if Expr[I] in ['0'..'9'] then
  361. begin { Build multi-digit numbers }
  362. Token:=Token + Expr[I];
  363. if I = Length(Expr) then { Send last one to calculator }
  364. RPNCalc(Token,false);
  365. end
  366. else
  367. if Expr[I] in ['+', '-', '*', '/', '(', ')','^','&','|','%','~','<','>'] then
  368. begin
  369. if Token <> '' then
  370. begin { Send last built number to calc. }
  371. RPNCalc(Token,false);
  372. Token:='';
  373. end;
  374. Case Expr[I] OF
  375. '(' : OpPush('(',false);
  376. ')' : begin
  377. While OpStack[OpTop].ch <> '(' DO
  378. Begin
  379. OpPop(opr);
  380. RPNCalc(opr.ch,opr.is_prefix);
  381. end;
  382. OpPop(opr); { Pop off and ignore the '(' }
  383. end;
  384. '+','-','~' : Begin
  385. { workaround for -2147483648 }
  386. if (expr[I]='-') and (expr[i+1] in ['0'..'9']) then
  387. begin
  388. token:='-';
  389. expr[i]:='+';
  390. end;
  391. { if start of expression then surely a prefix }
  392. { or if previous char was also an operator }
  393. if (I = 1) or (not (Expr[I-1] in ['0'..'9','(',')'])) then
  394. OpPush(Expr[I],true)
  395. else
  396. Begin
  397. { Evaluate all higher priority operators }
  398. While (OpTop > 0) AND (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
  399. Begin
  400. OpPop(opr);
  401. RPNCalc(opr.ch,opr.is_prefix);
  402. end;
  403. OpPush(Expr[I],false);
  404. End;
  405. end;
  406. '*', '/',
  407. '^','|','&',
  408. '%','<','>' : begin
  409. While (OpTop > 0) and (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
  410. Begin
  411. OpPop(opr);
  412. RPNCalc(opr.ch,opr.is_prefix);
  413. end;
  414. OpPush(Expr[I],false);
  415. end;
  416. end; { Case }
  417. end
  418. else
  419. Message(asmr_e_expr_illegal); { Handle bad input error }
  420. end;
  421. { Pop off the remaining operators }
  422. While OpTop > 0 do
  423. Begin
  424. OpPop(opr);
  425. RPNCalc(opr.ch,opr.is_prefix);
  426. end;
  427. { The result is stored on the top of the stack }
  428. Evaluate:=RPNPop;
  429. end;
  430. Destructor TExprParse.Destroy;
  431. Begin
  432. end;
  433. Function CalculateExpression(const expression: string): longint;
  434. var
  435. expr: TExprParse;
  436. Begin
  437. expr:=TExprParse.create;
  438. CalculateExpression:=expr.Evaluate(expression);
  439. expr.Free;
  440. end;
  441. {*************************************************************************}
  442. { String conversions/utils }
  443. {*************************************************************************}
  444. Function EscapeToPascal(const s:string): string;
  445. { converts a C styled string - which contains escape }
  446. { characters to a pascal style string. }
  447. var
  448. i,len : longint;
  449. hs : string;
  450. temp : string;
  451. c : char;
  452. Begin
  453. hs:='';
  454. len:=0;
  455. i:=0;
  456. while (i<length(s)) and (len<255) do
  457. begin
  458. Inc(i);
  459. if (s[i]='\') and (i<length(s)) then
  460. Begin
  461. inc(i);
  462. case s[i] of
  463. '\' :
  464. c:='\';
  465. 'b':
  466. c:=#8;
  467. 'f':
  468. c:=#12;
  469. 'n':
  470. c:=#10;
  471. 'r':
  472. c:=#13;
  473. 't':
  474. c:=#9;
  475. '"':
  476. c:='"';
  477. '0'..'7':
  478. Begin
  479. temp:=s[i];
  480. temp:=temp+s[i+1];
  481. temp:=temp+s[i+2];
  482. inc(i,2);
  483. c:=chr(ValOctal(temp));
  484. end;
  485. 'x':
  486. Begin
  487. temp:=s[i+1];
  488. temp:=temp+s[i+2];
  489. inc(i,2);
  490. c:=chr(ValHexaDecimal(temp));
  491. end;
  492. else
  493. Begin
  494. Message1(asmr_e_escape_seq_ignored,s[i]);
  495. c:=s[i];
  496. end;
  497. end;
  498. end
  499. else
  500. c:=s[i];
  501. inc(len);
  502. hs[len]:=c;
  503. end;
  504. hs[0]:=chr(len);
  505. EscapeToPascal:=hs;
  506. end;
  507. Function ValDecimal(const S:String):longint;
  508. { Converts a decimal string to longint }
  509. var
  510. vs,c : longint;
  511. Begin
  512. vs:=0;
  513. for c:=1 to length(s) do
  514. begin
  515. vs:=vs*10;
  516. if s[c] in ['0'..'9'] then
  517. inc(vs,ord(s[c])-ord('0'))
  518. else
  519. begin
  520. Message1(asmr_e_error_converting_decimal,s);
  521. ValDecimal:=0;
  522. exit;
  523. end;
  524. end;
  525. ValDecimal:=vs;
  526. end;
  527. Function ValOctal(const S:String):longint;
  528. { Converts an octal string to longint }
  529. var
  530. vs,c : longint;
  531. Begin
  532. vs:=0;
  533. for c:=1 to length(s) do
  534. begin
  535. vs:=vs shl 3;
  536. if s[c] in ['0'..'7'] then
  537. inc(vs,ord(s[c])-ord('0'))
  538. else
  539. begin
  540. Message1(asmr_e_error_converting_octal,s);
  541. ValOctal:=0;
  542. exit;
  543. end;
  544. end;
  545. ValOctal:=vs;
  546. end;
  547. Function ValBinary(const S:String):longint;
  548. { Converts a binary string to longint }
  549. var
  550. vs,c : longint;
  551. Begin
  552. vs:=0;
  553. for c:=1 to length(s) do
  554. begin
  555. vs:=vs shl 1;
  556. if s[c] in ['0'..'1'] then
  557. inc(vs,ord(s[c])-ord('0'))
  558. else
  559. begin
  560. Message1(asmr_e_error_converting_binary,s);
  561. ValBinary:=0;
  562. exit;
  563. end;
  564. end;
  565. ValBinary:=vs;
  566. end;
  567. Function ValHexadecimal(const S:String):longint;
  568. { Converts a binary string to longint }
  569. var
  570. vs,c : longint;
  571. Begin
  572. vs:=0;
  573. for c:=1 to length(s) do
  574. begin
  575. vs:=vs shl 4;
  576. case s[c] of
  577. '0'..'9' :
  578. inc(vs,ord(s[c])-ord('0'));
  579. 'A'..'F' :
  580. inc(vs,ord(s[c])-ord('A')+10);
  581. 'a'..'f' :
  582. inc(vs,ord(s[c])-ord('a')+10);
  583. else
  584. begin
  585. Message1(asmr_e_error_converting_hexadecimal,s);
  586. ValHexadecimal:=0;
  587. exit;
  588. end;
  589. end;
  590. end;
  591. ValHexadecimal:=vs;
  592. end;
  593. Function PadZero(Var s: String; n: byte): Boolean;
  594. Begin
  595. PadZero:=TRUE;
  596. { Do some error checking first }
  597. if Length(s) = n then
  598. exit
  599. else
  600. if Length(s) > n then
  601. Begin
  602. PadZero:=FALSE;
  603. delete(s,n+1,length(s));
  604. exit;
  605. end
  606. else
  607. PadZero:=TRUE;
  608. { Fill it up with the specified character }
  609. fillchar(s[length(s)+1],n-1,#0);
  610. s[0]:=chr(n);
  611. end;
  612. {****************************************************************************
  613. TOperand
  614. ****************************************************************************}
  615. constructor TOperand.Create;
  616. begin
  617. size:=S_NO;
  618. hastype:=false;
  619. hasvar:=false;
  620. FillChar(Opr,sizeof(Opr),0);
  621. end;
  622. destructor TOperand.destroy;
  623. begin
  624. end;
  625. Procedure TOperand.SetCorrectSize(opcode:tasmop);
  626. begin
  627. end;
  628. Procedure TOperand.SetSize(_size:longint;force:boolean);
  629. begin
  630. if force or
  631. ((size = S_NO) and (_size<=extended_size)) then
  632. Begin
  633. case _size of
  634. 1 : size:=S_B;
  635. 2 : size:=S_W{ could be S_IS};
  636. 4 : size:=S_L{ could be S_IL or S_FS};
  637. 8 : size:=S_IQ{ could be S_D or S_FL};
  638. else
  639. begin
  640. { extended_size can also be 8, resulting in a
  641. duplicate label }
  642. if _size=extended_size then
  643. size:=S_FX;
  644. end;
  645. end;
  646. end;
  647. end;
  648. Function TOperand.SetupResult:boolean;
  649. Begin
  650. SetupResult:=false;
  651. { replace by correct offset. }
  652. if (not is_void(aktprocdef.rettype.def)) then
  653. begin
  654. if (m_tp7 in aktmodeswitches) and
  655. paramanager.ret_in_acc(aktprocdef.rettype.def) then
  656. begin
  657. Message(asmr_e_cannot_use_RESULT_here);
  658. exit;
  659. end;
  660. opr.ref.offset:=procinfo^.return_offset;
  661. opr.ref.base:= procinfo^.framepointer;
  662. opr.ref.options:=ref_parafixup;
  663. { always assume that the result is valid. }
  664. tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
  665. { increase reference count, this is also used to check
  666. if the result variable is actually used or not }
  667. inc(tfuncretsym(aktprocdef.funcretsym).refcount);
  668. SetupResult:=true;
  669. end
  670. else
  671. Message(asmr_e_void_function);
  672. end;
  673. Function TOperand.SetupSelf:boolean;
  674. Begin
  675. SetupSelf:=false;
  676. if assigned(procinfo^._class) then
  677. Begin
  678. opr.typ:=OPR_REFERENCE;
  679. opr.ref.offset:=procinfo^.selfpointer_offset;
  680. opr.ref.base:=procinfo^.framepointer;
  681. opr.ref.options:=ref_selffixup;
  682. SetupSelf:=true;
  683. end
  684. else
  685. Message(asmr_e_cannot_use_SELF_outside_a_method);
  686. end;
  687. Function TOperand.SetupOldEBP:boolean;
  688. Begin
  689. SetupOldEBP:=false;
  690. if lexlevel>normal_function_level then
  691. Begin
  692. opr.typ:=OPR_REFERENCE;
  693. opr.ref.offset:=procinfo^.framepointer_offset;
  694. opr.ref.base:=procinfo^.framepointer;
  695. opr.ref.options:=ref_parafixup;
  696. SetupOldEBP:=true;
  697. end
  698. else
  699. Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
  700. end;
  701. Function TOperand.SetupVar(const s:string;GetOffset : boolean): Boolean;
  702. { search and sets up the correct fields in the Instr record }
  703. { for the NON-constant identifier passed to the routine. }
  704. { if not found returns FALSE. }
  705. var
  706. sym : tsym;
  707. srsymtable : tsymtable;
  708. harrdef : tarraydef;
  709. l : longint;
  710. Begin
  711. SetupVar:=false;
  712. asmsearchsym(s,sym,srsymtable);
  713. if sym = nil then
  714. exit;
  715. case sym.typ of
  716. varsym :
  717. begin
  718. { we always assume in asm statements that }
  719. { that the variable is valid. }
  720. tvarsym(sym).varstate:=vs_used;
  721. inc(tvarsym(sym).refs);
  722. case tvarsym(sym).owner.symtabletype of
  723. objectsymtable :
  724. begin
  725. { this is not allowed, because we don't know if the self
  726. register is still free, and loading it first is also
  727. not possible, because this could break code }
  728. { Be TP/Delphi compatible in Delphi or TP modes }
  729. if (m_tp7 in aktmodeswitches) or
  730. (m_delphi in aktmodeswitches) then
  731. begin
  732. opr.typ:=OPR_CONSTANT;
  733. opr.val:=tvarsym(sym).address;
  734. end
  735. { I do not agree here people using method vars should ensure
  736. that %esi is valid there }
  737. else
  738. begin
  739. opr.ref.base:=SELF_POINTER_REG;
  740. opr.ref.offset:=tvarsym(sym).address;
  741. end;
  742. hasvar:=true;
  743. SetupVar:=true;
  744. Exit;
  745. end;
  746. globalsymtable,
  747. staticsymtable :
  748. opr.ref.symbol:=objectlibrary.newasmsymbol(tvarsym(sym).mangledname);
  749. parasymtable :
  750. begin
  751. { if we only want the offset we don't have to care
  752. the base will be zeroed after ! }
  753. if (lexlevel=tvarsym(sym).owner.symtablelevel) or
  754. { this below is wrong because there are two parast
  755. for global functions one of interface the second of
  756. implementation
  757. if (tvarsym(sym).owner=procinfo^.def.parast) or }
  758. GetOffset then
  759. begin
  760. opr.ref.base:=procinfo^.framepointer;
  761. end
  762. else
  763. begin
  764. if (aktprocdef.localst.datasize=0) and
  765. assigned(procinfo^.parent) and
  766. (lexlevel=tvarsym(sym).owner.symtablelevel+1) and
  767. { same problem as above !!
  768. (procinfo^.parent^.sym.definition.parast=tvarsym(sym).owner) and }
  769. (lexlevel>normal_function_level) then
  770. opr.ref.base:=procinfo^.parent^.framepointer
  771. else
  772. message1(asmr_e_local_para_unreachable,s);
  773. end;
  774. opr.ref.offset:=tvarsym(sym).address;
  775. if (lexlevel=tvarsym(sym).owner.symtablelevel) then
  776. begin
  777. opr.ref.offsetfixup:=aktprocdef.parast.address_fixup;
  778. opr.ref.options:=ref_parafixup;
  779. end
  780. else
  781. begin
  782. opr.ref.offsetfixup:=0;
  783. opr.ref.options:=ref_none;
  784. end;
  785. if (tvarsym(sym).varspez=vs_var) or
  786. ((tvarsym(sym).varspez=vs_const) and
  787. paramanager.push_addr_param(tvarsym(sym).vartype.def)) then
  788. SetSize(pointer_size,false);
  789. end;
  790. localsymtable :
  791. begin
  792. if (vo_is_external in tvarsym(sym).varoptions) then
  793. opr.ref.symbol:=objectlibrary.newasmsymbol(tvarsym(sym).mangledname)
  794. else
  795. begin
  796. { if we only want the offset we don't have to care
  797. the base will be zeroed after ! }
  798. if (lexlevel=tvarsym(sym).owner.symtablelevel) or
  799. {if (tvarsym(sym).owner=procinfo^.def.localst) or}
  800. GetOffset then
  801. opr.ref.base:=procinfo^.framepointer
  802. else
  803. begin
  804. if (aktprocdef.localst.datasize=0) and
  805. assigned(procinfo^.parent) and
  806. (lexlevel=tvarsym(sym).owner.symtablelevel+1) and
  807. {(procinfo^.parent^.sym.definition.localst=tvarsym(sym).owner) and}
  808. (lexlevel>normal_function_level) then
  809. opr.ref.base:=procinfo^.parent^.framepointer
  810. else
  811. message1(asmr_e_local_para_unreachable,s);
  812. end;
  813. opr.ref.offset:=-(tvarsym(sym).address);
  814. if (lexlevel=tvarsym(sym).owner.symtablelevel) then
  815. begin
  816. opr.ref.offsetfixup:=aktprocdef.localst.address_fixup;
  817. opr.ref.options:=ref_localfixup;
  818. end
  819. else
  820. begin
  821. opr.ref.offsetfixup:=0;
  822. opr.ref.options:=ref_none;
  823. end;
  824. end;
  825. if (tvarsym(sym).varspez in [vs_var,vs_out]) or
  826. ((tvarsym(sym).varspez=vs_const) and
  827. paramanager.push_addr_param(tvarsym(sym).vartype.def)) then
  828. SetSize(pointer_size,false);
  829. end;
  830. end;
  831. case tvarsym(sym).vartype.def.deftype of
  832. orddef,
  833. enumdef,
  834. pointerdef,
  835. floatdef :
  836. SetSize(tvarsym(sym).getsize,false);
  837. arraydef :
  838. begin
  839. { for arrays try to get the element size, take care of
  840. multiple indexes }
  841. harrdef:=tarraydef(tvarsym(sym).vartype.def);
  842. while assigned(harrdef.elementtype.def) and
  843. (harrdef.elementtype.def.deftype=arraydef) do
  844. harrdef:=tarraydef(harrdef.elementtype.def);
  845. SetSize(harrdef.elesize,false);
  846. end;
  847. end;
  848. hasvar:=true;
  849. SetupVar:=true;
  850. Exit;
  851. end;
  852. typedconstsym :
  853. begin
  854. opr.ref.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(sym).mangledname);
  855. case ttypedconstsym(sym).typedconsttype.def.deftype of
  856. orddef,
  857. enumdef,
  858. pointerdef,
  859. floatdef :
  860. SetSize(ttypedconstsym(sym).getsize,false);
  861. arraydef :
  862. begin
  863. { for arrays try to get the element size, take care of
  864. multiple indexes }
  865. harrdef:=tarraydef(ttypedconstsym(sym).typedconsttype.def);
  866. while assigned(harrdef.elementtype.def) and
  867. (harrdef.elementtype.def.deftype=arraydef) do
  868. harrdef:=tarraydef(harrdef.elementtype.def);
  869. SetSize(harrdef.elesize,false);
  870. end;
  871. end;
  872. hasvar:=true;
  873. SetupVar:=true;
  874. Exit;
  875. end;
  876. constsym :
  877. begin
  878. if tconstsym(sym).consttyp in [constint,constchar,constbool] then
  879. begin
  880. opr.typ:=OPR_CONSTANT;
  881. opr.val:=tconstsym(sym).valueord;
  882. SetupVar:=true;
  883. Exit;
  884. end;
  885. end;
  886. typesym :
  887. begin
  888. if ttypesym(sym).restype.def.deftype in [recorddef,objectdef] then
  889. begin
  890. opr.typ:=OPR_CONSTANT;
  891. opr.val:=0;
  892. SetupVar:=TRUE;
  893. Exit;
  894. end;
  895. end;
  896. procsym :
  897. begin
  898. if assigned(tprocsym(sym).defs^.next) then
  899. Message(asmr_w_calling_overload_func);
  900. l:=opr.ref.offset;
  901. opr.typ:=OPR_SYMBOL;
  902. opr.symbol:=objectlibrary.newasmsymbol(tprocsym(sym).defs^.def.mangledname);
  903. opr.symofs:=l;
  904. hasvar:=true;
  905. SetupVar:=TRUE;
  906. Exit;
  907. end;
  908. else
  909. begin
  910. Message(asmr_e_unsupported_symbol_type);
  911. exit;
  912. end;
  913. end;
  914. end;
  915. { looks for internal names of variables and routines }
  916. Function TOperand.SetupDirectVar(const hs:string): Boolean;
  917. var
  918. p : tasmsymbol;
  919. begin
  920. SetupDirectVar:=false;
  921. p:=objectlibrary.getasmsymbol(hs);
  922. if assigned(p) then
  923. begin
  924. opr.ref.symbol:=p;
  925. hasvar:=true;
  926. SetupDirectVar:=true;
  927. end;
  928. end;
  929. procedure TOperand.InitRef;
  930. {*********************************************************************}
  931. { Description: This routine first check if the opcode is of }
  932. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  933. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  934. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  935. { to point to the default segment. }
  936. {*********************************************************************}
  937. Begin
  938. case opr.typ of
  939. OPR_REFERENCE:
  940. exit;
  941. OPR_NONE: ;
  942. else
  943. Message(asmr_e_invalid_operand_type);
  944. end;
  945. opr.typ := OPR_REFERENCE;
  946. Fillchar(opr.ref,sizeof(treference),0);
  947. end;
  948. procedure TOperand.BuildOperand;
  949. begin
  950. abstract;
  951. end;
  952. {****************************************************************************
  953. TInstruction
  954. ****************************************************************************}
  955. constructor TInstruction.create;
  956. Begin
  957. Opcode:=A_NONE;
  958. Opsize:=S_NO;
  959. Condition:=C_NONE;
  960. Ops:=0;
  961. InitOperands;
  962. Labeled:=false;
  963. end;
  964. destructor TInstruction.destroy;
  965. var
  966. i : longint;
  967. Begin
  968. for i:=1 to 3 do
  969. Operands[i].free;
  970. end;
  971. procedure TInstruction.InitOperands;
  972. var
  973. i : longint;
  974. begin
  975. for i:=1 to 3 do
  976. Operands[i].create;
  977. end;
  978. Procedure TInstruction.Swapoperands;
  979. Var
  980. p : toperand;
  981. Begin
  982. case Ops of
  983. 2 :
  984. begin
  985. p:=Operands[1];
  986. Operands[1]:=Operands[2];
  987. Operands[2]:=p;
  988. end;
  989. 3 :
  990. begin
  991. p:=Operands[1];
  992. Operands[1]:=Operands[3];
  993. Operands[3]:=p;
  994. end;
  995. end;
  996. end;
  997. procedure TInstruction.ConcatInstruction(p:TAAsmOutput);
  998. begin
  999. abstract;
  1000. end;
  1001. procedure TInstruction.BuildOpcode;
  1002. begin
  1003. abstract;
  1004. end;
  1005. {***************************************************************************
  1006. TLocalLabel
  1007. ***************************************************************************}
  1008. constructor TLocalLabel.create(const n:string);
  1009. begin
  1010. inherited CreateName(n);
  1011. lab:=nil;
  1012. emitted:=false;
  1013. end;
  1014. function TLocalLabel.Gettasmlabel:tasmlabel;
  1015. begin
  1016. if not assigned(lab) then
  1017. begin
  1018. objectlibrary.getlabel(lab);
  1019. { this label is forced to be used so it's always written }
  1020. inc(lab.refs);
  1021. end;
  1022. Gettasmlabel:=lab;
  1023. end;
  1024. {***************************************************************************
  1025. TLocalLabelList
  1026. ***************************************************************************}
  1027. procedure LocalLabelEmitted(p:tnamedindexitem;arg:pointer);
  1028. begin
  1029. if not TLocalLabel(p).emitted then
  1030. Message1(asmr_e_unknown_label_identifier,p.name);
  1031. end;
  1032. procedure TLocalLabelList.CheckEmitted;
  1033. begin
  1034. ForEach_Static({$ifdef FPCPROCVAR}@{$endif}LocalLabelEmitted,nil)
  1035. end;
  1036. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  1037. var
  1038. lab : TLocalLabel;
  1039. Begin
  1040. CreateLocalLabel:=true;
  1041. { Check if it already is defined }
  1042. lab:=TLocalLabel(LocalLabellist.Search(s));
  1043. if not assigned(lab) then
  1044. begin
  1045. lab:=TLocalLabel.Create(s);
  1046. LocalLabellist.Insert(lab);
  1047. end;
  1048. { set emitted flag and check for dup syms }
  1049. if emit then
  1050. begin
  1051. if lab.Emitted then
  1052. begin
  1053. Message1(asmr_e_dup_local_sym,lab.Name);
  1054. CreateLocalLabel:=false;
  1055. end;
  1056. lab.Emitted:=true;
  1057. end;
  1058. hl:=lab.Gettasmlabel;
  1059. end;
  1060. {****************************************************************************
  1061. Symbol table helper routines
  1062. ****************************************************************************}
  1063. procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:tsymtable);
  1064. var
  1065. i : integer;
  1066. begin
  1067. i:=pos('.',s);
  1068. { allow unit.identifier }
  1069. if i>0 then
  1070. begin
  1071. searchsym(Copy(s,1,i-1),srsym,srsymtable);
  1072. if assigned(srsym) then
  1073. begin
  1074. if (srsym.typ=unitsym) and
  1075. (srsym.owner.unitid=0) then
  1076. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,Copy(s,i+1,255))
  1077. else
  1078. srsym:=nil;
  1079. end;
  1080. end
  1081. else
  1082. searchsym(s,srsym,srsymtable);
  1083. end;
  1084. Function SearchType(const hs:string): Boolean;
  1085. var
  1086. srsym : tsym;
  1087. srsymtable : tsymtable;
  1088. begin
  1089. asmsearchsym(hs,srsym,srsymtable);
  1090. SearchType:=assigned(srsym) and
  1091. (srsym.typ=typesym);
  1092. end;
  1093. Function SearchRecordType(const s:string): boolean;
  1094. var
  1095. srsym : tsym;
  1096. srsymtable : tsymtable;
  1097. Begin
  1098. SearchRecordType:=false;
  1099. { Check the constants in symtable }
  1100. asmsearchsym(s,srsym,srsymtable);
  1101. if srsym <> nil then
  1102. Begin
  1103. case srsym.typ of
  1104. typesym :
  1105. begin
  1106. if ttypesym(srsym).restype.def.deftype in [recorddef,objectdef] then
  1107. begin
  1108. SearchRecordType:=true;
  1109. exit;
  1110. end;
  1111. end;
  1112. end;
  1113. end;
  1114. end;
  1115. Function SearchIConstant(const s:string; var l:longint): boolean;
  1116. {**********************************************************************}
  1117. { Description: Searches for a CONSTANT of name s in either the local }
  1118. { symbol list, then in the global symbol list, and returns the value }
  1119. { of that constant in l. Returns TRUE if successfull, if not found, }
  1120. { or if the constant is not of correct type, then returns FALSE }
  1121. { Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
  1122. { respectively. }
  1123. {**********************************************************************}
  1124. var
  1125. srsym : tsym;
  1126. srsymtable : tsymtable;
  1127. Begin
  1128. SearchIConstant:=false;
  1129. { check for TRUE or FALSE reserved words first }
  1130. if s = 'TRUE' then
  1131. Begin
  1132. SearchIConstant:=TRUE;
  1133. l:=1;
  1134. exit;
  1135. end;
  1136. if s = 'FALSE' then
  1137. Begin
  1138. SearchIConstant:=TRUE;
  1139. l:=0;
  1140. exit;
  1141. end;
  1142. { Check the constants in symtable }
  1143. asmsearchsym(s,srsym,srsymtable);
  1144. if srsym <> nil then
  1145. Begin
  1146. case srsym.typ of
  1147. constsym :
  1148. begin
  1149. if (tconstsym(srsym).consttyp in [constord,constint,constchar,constbool]) then
  1150. Begin
  1151. l:=tconstsym(srsym).valueord;
  1152. SearchIConstant:=TRUE;
  1153. exit;
  1154. end;
  1155. end;
  1156. enumsym:
  1157. Begin
  1158. l:=tenumsym(srsym).value;
  1159. SearchIConstant:=TRUE;
  1160. exit;
  1161. end;
  1162. end;
  1163. end;
  1164. end;
  1165. Function GetRecordOffsetSize(s:string;Var Offset: longint;var Size:longint):boolean;
  1166. { search and returns the offset and size of records/objects of the base }
  1167. { with field name setup in field. }
  1168. { returns FALSE if not found. }
  1169. { used when base is a variable or a typed constant name. }
  1170. var
  1171. st : tsymtable;
  1172. harrdef : tarraydef;
  1173. sym : tsym;
  1174. srsymtable : tsymtable;
  1175. i : longint;
  1176. base : string;
  1177. Begin
  1178. GetRecordOffsetSize:=FALSE;
  1179. Offset:=0;
  1180. Size:=0;
  1181. i:=pos('.',s);
  1182. if i=0 then
  1183. i:=255;
  1184. base:=Copy(s,1,i-1);
  1185. delete(s,1,i);
  1186. if base='SELF' then
  1187. st:=procinfo^._class.symtable
  1188. else
  1189. begin
  1190. asmsearchsym(base,sym,srsymtable);
  1191. st:=nil;
  1192. { we can start with a var,type,typedconst }
  1193. case sym.typ of
  1194. varsym :
  1195. begin
  1196. case tvarsym(sym).vartype.def.deftype of
  1197. recorddef :
  1198. st:=trecorddef(tvarsym(sym).vartype.def).symtable;
  1199. objectdef :
  1200. st:=tobjectdef(tvarsym(sym).vartype.def).symtable;
  1201. end;
  1202. end;
  1203. typesym :
  1204. begin
  1205. case ttypesym(sym).restype.def.deftype of
  1206. recorddef :
  1207. st:=trecorddef(ttypesym(sym).restype.def).symtable;
  1208. objectdef :
  1209. st:=tobjectdef(ttypesym(sym).restype.def).symtable;
  1210. end;
  1211. end;
  1212. typedconstsym :
  1213. begin
  1214. case ttypedconstsym(sym).typedconsttype.def.deftype of
  1215. recorddef :
  1216. st:=trecorddef(ttypedconstsym(sym).typedconsttype.def).symtable;
  1217. objectdef :
  1218. st:=tobjectdef(ttypedconstsym(sym).typedconsttype.def).symtable;
  1219. end;
  1220. end;
  1221. end;
  1222. end;
  1223. { now walk all recordsymtables }
  1224. while assigned(st) and (s<>'') do
  1225. begin
  1226. { load next field in base }
  1227. i:=pos('.',s);
  1228. if i=0 then
  1229. i:=255;
  1230. base:=Copy(s,1,i-1);
  1231. delete(s,1,i);
  1232. if st.symtabletype=objectsymtable then
  1233. sym:=search_class_member(tobjectdef(st.defowner),base)
  1234. else
  1235. sym:=tsym(st.search(base));
  1236. if not assigned(sym) then
  1237. begin
  1238. GetRecordOffsetSize:=false;
  1239. exit;
  1240. end;
  1241. st:=nil;
  1242. case sym.typ of
  1243. varsym :
  1244. begin
  1245. inc(Offset,tvarsym(sym).address);
  1246. Size:=tvarsym(sym).getsize;
  1247. case tvarsym(sym).vartype.def.deftype of
  1248. arraydef :
  1249. begin
  1250. { for arrays try to get the element size, take care of
  1251. multiple indexes }
  1252. harrdef:=tarraydef(tvarsym(sym).vartype.def);
  1253. while assigned(harrdef.elementtype.def) and
  1254. (harrdef.elementtype.def.deftype=arraydef) do
  1255. harrdef:=tarraydef(harrdef.elementtype.def);
  1256. size:=harrdef.elesize;
  1257. end;
  1258. recorddef :
  1259. st:=trecorddef(tvarsym(sym).vartype.def).symtable;
  1260. objectdef :
  1261. st:=tobjectdef(tvarsym(sym).vartype.def).symtable;
  1262. end;
  1263. end;
  1264. end;
  1265. end;
  1266. GetRecordOffsetSize:=(s='');
  1267. end;
  1268. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  1269. var
  1270. sym : tsym;
  1271. srsymtable : tsymtable;
  1272. hs : string;
  1273. Begin
  1274. hl:=nil;
  1275. SearchLabel:=false;
  1276. { Check for pascal labels, which are case insensetive }
  1277. hs:=upper(s);
  1278. asmsearchsym(hs,sym,srsymtable);
  1279. if sym=nil then
  1280. exit;
  1281. case sym.typ of
  1282. labelsym :
  1283. begin
  1284. hl:=tlabelsym(sym).lab;
  1285. if emit then
  1286. tlabelsym(sym).defined:=true
  1287. else
  1288. tlabelsym(sym).used:=true;
  1289. SearchLabel:=true;
  1290. exit;
  1291. end;
  1292. end;
  1293. end;
  1294. {*************************************************************************}
  1295. { Instruction Generation Utilities }
  1296. {*************************************************************************}
  1297. Procedure ConcatString(p : TAAsmoutput;s:string);
  1298. {*********************************************************************}
  1299. { PROCEDURE ConcatString(s:string); }
  1300. { Description: This routine adds the character chain pointed to in }
  1301. { s to the instruction linked list. }
  1302. {*********************************************************************}
  1303. Var
  1304. pc: PChar;
  1305. Begin
  1306. getmem(pc,length(s)+1);
  1307. p.concat(Tai_string.Create_length_pchar(strpcopy(pc,s),length(s)));
  1308. end;
  1309. Procedure ConcatPasString(p : TAAsmoutput;s:string);
  1310. {*********************************************************************}
  1311. { PROCEDURE ConcatPasString(s:string); }
  1312. { Description: This routine adds the character chain pointed to in }
  1313. { s to the instruction linked list, contrary to ConcatString it }
  1314. { uses a pascal style string, so it conserves null characters. }
  1315. {*********************************************************************}
  1316. Begin
  1317. p.concat(Tai_string.Create(s));
  1318. end;
  1319. Procedure ConcatDirect(p : TAAsmoutput;s:string);
  1320. {*********************************************************************}
  1321. { PROCEDURE ConcatDirect(s:string) }
  1322. { Description: This routine output the string directly to the asm }
  1323. { output, it is only sed when writing special labels in AT&T mode, }
  1324. { and should not be used without due consideration, since it may }
  1325. { cause problems. }
  1326. {*********************************************************************}
  1327. Var
  1328. pc: PChar;
  1329. Begin
  1330. getmem(pc,length(s)+1);
  1331. p.concat(Tai_direct.Create(strpcopy(pc,s)));
  1332. end;
  1333. Procedure ConcatConstant(p: TAAsmoutput; value: longint; maxvalue: longint);
  1334. {*********************************************************************}
  1335. { PROCEDURE ConcatConstant(value: longint; maxvalue: longint); }
  1336. { Description: This routine adds the value constant to the current }
  1337. { instruction linked list. }
  1338. { maxvalue -> indicates the size of the data to initialize: }
  1339. { $ff -> create a byte node. }
  1340. { $ffff -> create a word node. }
  1341. { $ffffffff -> create a dword node. }
  1342. {*********************************************************************}
  1343. Begin
  1344. if (maxvalue <> longint($ffffffff)) and (value > maxvalue) then
  1345. Begin
  1346. Message(asmr_e_constant_out_of_bounds);
  1347. { assuming a value of maxvalue }
  1348. value:=maxvalue;
  1349. end;
  1350. if maxvalue = $ff then
  1351. p.concat(Tai_const.Create_8bit(byte(value)))
  1352. else
  1353. if maxvalue = $ffff then
  1354. p.concat(Tai_const.Create_16bit(word(value)))
  1355. else
  1356. if maxvalue = longint($ffffffff) then
  1357. p.concat(Tai_const.Create_32bit(longint(value)));
  1358. end;
  1359. Procedure ConcatConstSymbol(p : TAAsmoutput;const sym:string;l:longint);
  1360. begin
  1361. p.concat(Tai_const_symbol.Createname_offset(sym,l));
  1362. end;
  1363. Procedure ConcatRealConstant(p : TAAsmoutput;value: bestreal; real_typ : tfloattype);
  1364. {***********************************************************************}
  1365. { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
  1366. { Description: This routine adds the value constant to the current }
  1367. { instruction linked list. }
  1368. { real_typ -> indicates the type of the real data to initialize: }
  1369. { s32real -> create a single node. }
  1370. { s64real -> create a double node. }
  1371. { s80real -> create an extended node. }
  1372. { s64bit -> create a comp node. }
  1373. { f32bit -> create a fixed node. (not used normally) }
  1374. {***********************************************************************}
  1375. Begin
  1376. case real_typ of
  1377. s32real : p.concat(Tai_real_32bit.Create(value));
  1378. s64real : p.concat(Tai_real_64bit.Create(value));
  1379. s80real : p.concat(Tai_real_80bit.Create(value));
  1380. s64comp : p.concat(Tai_comp_64bit.Create(value));
  1381. end;
  1382. end;
  1383. Procedure ConcatLabel(p: TAAsmoutput;var l : tasmlabel);
  1384. {*********************************************************************}
  1385. { PROCEDURE ConcatLabel }
  1386. { Description: This routine either emits a label or a labeled }
  1387. { instruction to the linked list of instructions. }
  1388. {*********************************************************************}
  1389. begin
  1390. p.concat(Tai_label.Create(l));
  1391. end;
  1392. procedure ConcatAlign(p:TAAsmoutput;l:longint);
  1393. {*********************************************************************}
  1394. { PROCEDURE ConcatPublic }
  1395. { Description: This routine emits an global definition to the }
  1396. { linked list of instructions.(used by AT&T styled asm) }
  1397. {*********************************************************************}
  1398. begin
  1399. p.concat(Tai_align.Create(l));
  1400. end;
  1401. procedure ConcatPublic(p:TAAsmoutput;const s : string);
  1402. {*********************************************************************}
  1403. { PROCEDURE ConcatPublic }
  1404. { Description: This routine emits an global definition to the }
  1405. { linked list of instructions.(used by AT&T styled asm) }
  1406. {*********************************************************************}
  1407. begin
  1408. p.concat(Tai_symbol.Createname_global(s,0));
  1409. end;
  1410. procedure ConcatLocal(p:TAAsmoutput;const s : string);
  1411. {*********************************************************************}
  1412. { PROCEDURE ConcatLocal }
  1413. { Description: This routine emits an local definition to the }
  1414. { linked list of instructions. }
  1415. {*********************************************************************}
  1416. begin
  1417. p.concat(Tai_symbol.Createname(s,0));
  1418. end;
  1419. Procedure ConcatGlobalBss(const s : string;size : longint);
  1420. {*********************************************************************}
  1421. { PROCEDURE ConcatGlobalBss }
  1422. { Description: This routine emits an global datablock to the }
  1423. { linked list of instructions. }
  1424. {*********************************************************************}
  1425. begin
  1426. bssSegment.concat(Tai_datablock.Create_global(s,size));
  1427. end;
  1428. Procedure ConcatLocalBss(const s : string;size : longint);
  1429. {*********************************************************************}
  1430. { PROCEDURE ConcatLocalBss }
  1431. { Description: This routine emits a local datablcok to the }
  1432. { linked list of instructions. }
  1433. {*********************************************************************}
  1434. begin
  1435. bssSegment.concat(Tai_datablock.Create(s,size));
  1436. end;
  1437. end.
  1438. {
  1439. $Log$
  1440. Revision 1.42 2002-08-13 18:01:52 carl
  1441. * rename swatoperands to swapoperands
  1442. + m68k first compilable version (still needs a lot of testing):
  1443. assembler generator, system information , inline
  1444. assembler reader.
  1445. Revision 1.41 2002/08/12 15:08:40 carl
  1446. + stab register indexes for powerpc (moved from gdb to cpubase)
  1447. + tprocessor enumeration moved to cpuinfo
  1448. + linker in target_info is now a class
  1449. * many many updates for m68k (will soon start to compile)
  1450. - removed some ifdef or correct them for correct cpu
  1451. Revision 1.40 2002/08/11 14:32:27 peter
  1452. * renamed current_library to objectlibrary
  1453. Revision 1.39 2002/08/11 13:24:13 peter
  1454. * saving of asmsymbols in ppu supported
  1455. * asmsymbollist global is removed and moved into a new class
  1456. tasmlibrarydata that will hold the info of a .a file which
  1457. corresponds with a single module. Added librarydata to tmodule
  1458. to keep the library info stored for the module. In the future the
  1459. objectfiles will also be stored to the tasmlibrarydata class
  1460. * all getlabel/newasmsymbol and friends are moved to the new class
  1461. Revision 1.38 2002/07/20 11:57:57 florian
  1462. * types.pas renamed to defbase.pas because D6 contains a types
  1463. unit so this would conflicts if D6 programms are compiled
  1464. + Willamette/SSE2 instructions to assembler added
  1465. Revision 1.37 2002/07/11 14:41:28 florian
  1466. * start of the new generic parameter handling
  1467. Revision 1.36 2002/07/01 18:46:25 peter
  1468. * internal linker
  1469. * reorganized aasm layer
  1470. Revision 1.35 2002/05/18 13:34:17 peter
  1471. * readded missing revisions
  1472. Revision 1.34 2002/05/16 19:46:44 carl
  1473. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1474. + try to fix temp allocation (still in ifdef)
  1475. + generic constructor calls
  1476. + start of tassembler / tmodulebase class cleanup
  1477. Revision 1.31 2002/05/12 16:53:10 peter
  1478. * moved entry and exitcode to ncgutil and cgobj
  1479. * foreach gets extra argument for passing local data to the
  1480. iterator function
  1481. * -CR checks also class typecasts at runtime by changing them
  1482. into as
  1483. * fixed compiler to cycle with the -CR option
  1484. * fixed stabs with elf writer, finally the global variables can
  1485. be watched
  1486. * removed a lot of routines from cga unit and replaced them by
  1487. calls to cgobj
  1488. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1489. u32bit then the other is typecasted also to u32bit without giving
  1490. a rangecheck warning/error.
  1491. * fixed pascal calling method with reversing also the high tree in
  1492. the parast, detected by tcalcst3 test
  1493. Revision 1.30 2002/04/20 21:32:24 carl
  1494. + generic FPC_CHECKPOINTER
  1495. + first parameter offset in stack now portable
  1496. * rename some constants
  1497. + move some cpu stuff to other units
  1498. - remove unused constents
  1499. * fix stacksize for some targets
  1500. * fix generic size problems which depend now on EXTEND_SIZE constant
  1501. Revision 1.29 2002/04/15 19:02:35 carl
  1502. + target_info.size_of_pointer -> pointer_Size
  1503. Revision 1.28 2002/04/02 17:11:29 peter
  1504. * tlocation,treference update
  1505. * LOC_CONSTANT added for better constant handling
  1506. * secondadd splitted in multiple routines
  1507. * location_force_reg added for loading a location to a register
  1508. of a specified size
  1509. * secondassignment parses now first the right and then the left node
  1510. (this is compatible with Kylix). This saves a lot of push/pop especially
  1511. with string operations
  1512. * adapted some routines to use the new cg methods
  1513. Revision 1.27 2002/01/29 21:32:03 peter
  1514. * allow accessing locals in other lexlevel when the current assembler
  1515. routine doesn't have locals.
  1516. Revision 1.26 2002/01/24 18:25:50 peter
  1517. * implicit result variable generation for assembler routines
  1518. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1519. }