rautils.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. This unit implements some support routines for assembler parsing
  4. independent of the processor
  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. Unit RAUtils;
  18. {$i fpcdefs.inc}
  19. Interface
  20. Uses
  21. cutils,cclasses,
  22. globtype,aasmbase,aasmtai,aasmdata,cpubase,cpuinfo,cgbase,cgutils,
  23. symconst,symbase,symtype,symdef,symsym;
  24. Const
  25. RPNMax = 10; { I think you only need 4, but just to be safe }
  26. OpMax = 25;
  27. {$if max_operands = 2}
  28. {$define MAX_OPER_2}
  29. {$endif}
  30. {$if max_operands = 3}
  31. {$define MAX_OPER_3}
  32. {$endif}
  33. {---------------------------------------------------------------------
  34. Local Label Management
  35. ---------------------------------------------------------------------}
  36. Type
  37. { Each local label has this structure associated with it }
  38. TLocalLabel = class(TFPHashObject)
  39. Emitted : boolean;
  40. constructor Create(AList:TFPHashObjectList;const n:string);
  41. function Gettasmlabel:tasmlabel;
  42. private
  43. lab : tasmlabel;
  44. end;
  45. TLocalLabelList = class(TFPHashObjectList)
  46. procedure CheckEmitted;
  47. end;
  48. var
  49. LocalLabelList : TLocalLabelList;
  50. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  51. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  52. {---------------------------------------------------------------------
  53. Instruction management
  54. ---------------------------------------------------------------------}
  55. type
  56. TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
  57. OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS);
  58. TOprRec = record
  59. case typ:TOprType of
  60. OPR_NONE : ();
  61. OPR_CONSTANT : (val:aint);
  62. OPR_SYMBOL : (symbol:tasmsymbol;symofs:aint);
  63. OPR_REFERENCE : (ref:treference);
  64. OPR_LOCAL : (localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
  65. OPR_REGISTER : (reg:tregister);
  66. {$ifdef m68k}
  67. OPR_REGLIST : (regset : tcpuregisterset);
  68. {$endif m68k}
  69. {$ifdef powerpc}
  70. OPR_COND : (cond : tasmcond);
  71. {$endif powerpc}
  72. {$ifdef POWERPC64}
  73. OPR_COND : (cond : tasmcond);
  74. {$endif POWERPC64}
  75. {$ifdef arm}
  76. OPR_REGSET : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister);
  77. OPR_SHIFTEROP : (shifterop : tshifterop);
  78. OPR_COND : (cc : tasmcond);
  79. OPR_MODEFLAGS : (flags : tcpumodeflags);
  80. {$endif arm}
  81. end;
  82. TOperand = class
  83. opr : TOprRec;
  84. typesize : byte;
  85. hastype, { if the operand has typecasted variable }
  86. hasvar : boolean; { if the operand is loaded with a variable }
  87. size : TCGSize;
  88. constructor create;virtual;
  89. destructor destroy;override;
  90. Procedure SetSize(_size:longint;force:boolean);virtual;
  91. Procedure SetCorrectSize(opcode:tasmop);virtual;
  92. Function SetupResult:boolean;virtual;
  93. Function SetupSelf:boolean;
  94. Function SetupOldEBP:boolean;
  95. Function SetupVar(const s:string;GetOffset : boolean): Boolean;
  96. Function CheckOperand: boolean; virtual;
  97. Procedure InitRef;
  98. end;
  99. TCOperand = class of TOperand;
  100. TInstruction = class
  101. operands : array[1..max_operands] of toperand;
  102. opcode : tasmop;
  103. condition : tasmcond;
  104. ops : byte;
  105. labeled : boolean;
  106. constructor create(optype : tcoperand);virtual;
  107. destructor destroy;override;
  108. { converts the instruction to an instruction how it's used by the assembler writer
  109. and concats it to the passed list. The newly created item is returned if the
  110. instruction was valid, otherwise nil is returned }
  111. function ConcatInstruction(p:TAsmList) : tai;virtual;
  112. Procedure Swapoperands;
  113. end;
  114. {---------------------------------------------------------------------}
  115. { Expression parser types }
  116. {---------------------------------------------------------------------}
  117. TExprOperator = record
  118. ch: char; { operator }
  119. is_prefix: boolean; { was it a prefix, possible prefixes are +,- and not }
  120. end;
  121. {**********************************************************************}
  122. { The following operators are supported: }
  123. { '+' : addition }
  124. { '-' : subtraction }
  125. { '*' : multiplication }
  126. { '/' : modulo division }
  127. { '^' : exclusive or }
  128. { '<' : shift left }
  129. { '>' : shift right }
  130. { '&' : bitwise and }
  131. { '|' : bitwise or }
  132. { '~' : bitwise complement }
  133. { '%' : modulo division }
  134. { nnn: longint numbers }
  135. { ( and ) parenthesis }
  136. {**********************************************************************}
  137. TExprParse = class
  138. public
  139. Constructor create;
  140. Destructor Destroy;override;
  141. Function Evaluate(Expr: String): aint;
  142. Function Priority(_Operator: Char): aint;
  143. private
  144. RPNStack : Array[1..RPNMax] of aint; { Stack For RPN calculator }
  145. RPNTop : aint;
  146. OpStack : Array[1..OpMax] of TExprOperator; { Operator stack For conversion }
  147. OpTop : aint;
  148. Procedure RPNPush(Num: aint);
  149. Function RPNPop: aint;
  150. Procedure RPNCalc(const token: String; prefix: boolean);
  151. Procedure OpPush(_Operator: char; prefix: boolean);
  152. { In reality returns TExprOperaotr }
  153. Procedure OpPop(var _Operator:TExprOperator);
  154. end;
  155. { Evaluate an expression string to a aint }
  156. Function CalculateExpression(const expression: string): aint;
  157. {---------------------------------------------------------------------}
  158. { String routines }
  159. {---------------------------------------------------------------------}
  160. Function ParseVal(const S:String;base:byte):aint;
  161. Function PadZero(Var s: String; n: byte): Boolean;
  162. Function EscapeToPascal(const s:string): string;
  163. {---------------------------------------------------------------------
  164. Symbol helper routines
  165. ---------------------------------------------------------------------}
  166. procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:TSymtable);
  167. Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean;
  168. Function SearchType(const hs:string;var size:aint): Boolean;
  169. Function SearchRecordType(const s:string): boolean;
  170. Function SearchIConstant(const s:string; var l:aint): boolean;
  171. {---------------------------------------------------------------------
  172. Instruction generation routines
  173. ---------------------------------------------------------------------}
  174. Procedure ConcatPasString(p : TAsmList;s:string);
  175. Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
  176. Procedure ConcatConstant(p : TAsmList;value: aint; constsize:byte);
  177. Procedure ConcatConstSymbol(p : TAsmList;const sym:string;symtyp:tasmsymtype;l:aint);
  178. Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
  179. Procedure ConcatString(p : TAsmList;s:string);
  180. procedure ConcatAlign(p:TAsmList;l:aint);
  181. Procedure ConcatPublic(p:TAsmList;const s : string);
  182. Procedure ConcatLocal(p:TAsmList;const s : string);
  183. Implementation
  184. uses
  185. SysUtils,
  186. defutil,systems,verbose,globals,
  187. symtable,paramgr,
  188. aasmcpu,
  189. procinfo;
  190. {*************************************************************************
  191. TExprParse
  192. *************************************************************************}
  193. Constructor TExprParse.create;
  194. Begin
  195. end;
  196. Procedure TExprParse.RPNPush(Num : aint);
  197. { Add an operand to the top of the RPN stack }
  198. begin
  199. if RPNTop < RPNMax then
  200. begin
  201. Inc(RPNTop);
  202. RPNStack[RPNTop]:=Num;
  203. end
  204. else
  205. Message(asmr_e_expr_illegal);
  206. end;
  207. Function TExprParse.RPNPop : aint;
  208. { Get the operand at the top of the RPN stack }
  209. begin
  210. if RPNTop > 0 then
  211. begin
  212. RPNPop:=RPNStack[RPNTop];
  213. Dec(RPNTop);
  214. end
  215. else
  216. Message(asmr_e_expr_illegal);
  217. end;
  218. Procedure TExprParse.RPNCalc(const Token : String; prefix:boolean); { RPN Calculator }
  219. Var
  220. Temp : aint;
  221. n1,n2 : aint;
  222. LocalError : Integer;
  223. begin
  224. { Handle operators }
  225. if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/','&','|','%','^','~','<','>']) then
  226. Case Token[1] of
  227. '+' :
  228. Begin
  229. if not prefix then
  230. RPNPush(RPNPop + RPNPop);
  231. end;
  232. '-' :
  233. Begin
  234. if prefix then
  235. RPNPush(-(RPNPop))
  236. else
  237. begin
  238. n1:=RPNPop;
  239. n2:=RPNPop;
  240. RPNPush(n2 - n1);
  241. end;
  242. end;
  243. '*' : RPNPush(RPNPop * RPNPop);
  244. '&' :
  245. begin
  246. n1:=RPNPop;
  247. n2:=RPNPop;
  248. RPNPush(n2 and n1);
  249. end;
  250. '|' :
  251. begin
  252. n1:=RPNPop;
  253. n2:=RPNPop;
  254. RPNPush(n2 or n1);
  255. end;
  256. '~' : RPNPush(NOT RPNPop);
  257. '<' :
  258. begin
  259. n1:=RPNPop;
  260. n2:=RPNPop;
  261. RPNPush(n2 SHL n1);
  262. end;
  263. '>' :
  264. begin
  265. n1:=RPNPop;
  266. n2:=RPNPop;
  267. RPNPush(n2 SHR n1);
  268. end;
  269. '%' :
  270. begin
  271. Temp:=RPNPop;
  272. if Temp <> 0 then
  273. RPNPush(RPNPop mod Temp)
  274. else
  275. begin
  276. Message(asmr_e_expr_zero_divide);
  277. { push 1 for error recovery }
  278. RPNPush(1);
  279. end;
  280. end;
  281. '^' : RPNPush(RPNPop XOR RPNPop);
  282. '/' :
  283. begin
  284. Temp:=RPNPop;
  285. if Temp <> 0 then
  286. RPNPush(RPNPop div Temp)
  287. else
  288. begin
  289. Message(asmr_e_expr_zero_divide);
  290. { push 1 for error recovery }
  291. RPNPush(1);
  292. end;
  293. end;
  294. end
  295. else
  296. begin
  297. { Convert String to number and add to stack }
  298. Val(Token, Temp, LocalError);
  299. if LocalError = 0 then
  300. RPNPush(Temp)
  301. else
  302. begin
  303. Message(asmr_e_expr_illegal);
  304. { push 1 for error recovery }
  305. RPNPush(1);
  306. end;
  307. end;
  308. end;
  309. Procedure TExprParse.OpPush(_Operator : char;prefix: boolean);
  310. { Add an operator onto top of the stack }
  311. begin
  312. if OpTop < OpMax then
  313. begin
  314. Inc(OpTop);
  315. OpStack[OpTop].ch:=_Operator;
  316. OpStack[OpTop].is_prefix:=prefix;
  317. end
  318. else
  319. Message(asmr_e_expr_illegal);
  320. end;
  321. Procedure TExprParse.OpPop(var _Operator:TExprOperator);
  322. { Get operator at the top of the stack }
  323. begin
  324. if OpTop > 0 then
  325. begin
  326. _Operator:=OpStack[OpTop];
  327. Dec(OpTop);
  328. end
  329. else
  330. Message(asmr_e_expr_illegal);
  331. end;
  332. Function TExprParse.Priority(_Operator : Char) : aint;
  333. { Return priority of operator }
  334. { The greater the priority, the higher the precedence }
  335. begin
  336. Case _Operator OF
  337. '(' :
  338. Priority:=0;
  339. '|','^','~' : // the lowest priority: OR, XOR, NOT
  340. Priority:=0;
  341. '&' : // bigger priority: AND
  342. Priority:=1;
  343. '+', '-' : // bigger priority: +, -
  344. Priority:=2;
  345. '*', '/','%','<','>' : // the highest priority: *, /, MOD, SHL, SHR
  346. Priority:=3;
  347. else
  348. Message(asmr_e_expr_illegal);
  349. end;
  350. end;
  351. Function TExprParse.Evaluate(Expr : String):aint;
  352. Var
  353. I : longint;
  354. Token : String;
  355. opr : TExprOperator;
  356. begin
  357. Evaluate:=0;
  358. { Reset stacks }
  359. OpTop :=0;
  360. RPNTop:=0;
  361. Token :='';
  362. { nothing to do ? }
  363. if Expr='' then
  364. exit;
  365. For I:=1 to Length(Expr) DO
  366. begin
  367. if Expr[I] in ['0'..'9'] then
  368. begin { Build multi-digit numbers }
  369. Token:=Token + Expr[I];
  370. if I = Length(Expr) then { Send last one to calculator }
  371. RPNCalc(Token,false);
  372. end
  373. else
  374. if Expr[I] in ['+', '-', '*', '/', '(', ')','^','&','|','%','~','<','>'] then
  375. begin
  376. if Token <> '' then
  377. begin { Send last built number to calc. }
  378. RPNCalc(Token,false);
  379. Token:='';
  380. end;
  381. Case Expr[I] OF
  382. '(' : OpPush('(',false);
  383. ')' : begin
  384. While (OpTop>0) and (OpStack[OpTop].ch <> '(') DO
  385. Begin
  386. OpPop(opr);
  387. RPNCalc(opr.ch,opr.is_prefix);
  388. end;
  389. OpPop(opr); { Pop off and ignore the '(' }
  390. end;
  391. '+','-','~' : Begin
  392. { workaround for -2147483648 }
  393. if (expr[I]='-') and (expr[i+1] in ['0'..'9']) then
  394. begin
  395. token:='-';
  396. expr[i]:='+';
  397. end;
  398. { if start of expression then surely a prefix }
  399. { or if previous char was also an operator }
  400. if (I = 1) or (not (Expr[I-1] in ['0'..'9',')'])) then
  401. OpPush(Expr[I],true)
  402. else
  403. Begin
  404. { Evaluate all higher priority operators }
  405. While (OpTop > 0) AND (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
  406. Begin
  407. OpPop(opr);
  408. RPNCalc(opr.ch,opr.is_prefix);
  409. end;
  410. OpPush(Expr[I],false);
  411. End;
  412. end;
  413. '*', '/',
  414. '^','|','&',
  415. '%','<','>' : begin
  416. While (OpTop > 0) and (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
  417. Begin
  418. OpPop(opr);
  419. RPNCalc(opr.ch,opr.is_prefix);
  420. end;
  421. OpPush(Expr[I],false);
  422. end;
  423. end; { Case }
  424. end
  425. else
  426. Message(asmr_e_expr_illegal); { Handle bad input error }
  427. end;
  428. { Pop off the remaining operators }
  429. While OpTop > 0 do
  430. Begin
  431. OpPop(opr);
  432. RPNCalc(opr.ch,opr.is_prefix);
  433. end;
  434. { The result is stored on the top of the stack }
  435. Evaluate:=RPNPop;
  436. end;
  437. Destructor TExprParse.Destroy;
  438. Begin
  439. end;
  440. Function CalculateExpression(const expression: string): aint;
  441. var
  442. expr: TExprParse;
  443. Begin
  444. expr:=TExprParse.create;
  445. CalculateExpression:=expr.Evaluate(expression);
  446. expr.Free;
  447. end;
  448. {*************************************************************************}
  449. { String conversions/utils }
  450. {*************************************************************************}
  451. Function EscapeToPascal(const s:string): string;
  452. { converts a C styled string - which contains escape }
  453. { characters to a pascal style string. }
  454. var
  455. i,len : aint;
  456. hs : string;
  457. temp : string;
  458. c : char;
  459. Begin
  460. hs:='';
  461. len:=0;
  462. i:=0;
  463. while (i<length(s)) and (len<255) do
  464. begin
  465. Inc(i);
  466. if (s[i]='\') and (i<length(s)) then
  467. Begin
  468. inc(i);
  469. case s[i] of
  470. '\' :
  471. c:='\';
  472. 'b':
  473. c:=#8;
  474. 'f':
  475. c:=#12;
  476. 'n':
  477. c:=#10;
  478. 'r':
  479. c:=#13;
  480. 't':
  481. c:=#9;
  482. '"':
  483. c:='"';
  484. '0'..'7':
  485. Begin
  486. temp:=s[i];
  487. temp:=temp+s[i+1];
  488. temp:=temp+s[i+2];
  489. inc(i,2);
  490. c:=chr(ParseVal(temp,8));
  491. end;
  492. 'x':
  493. Begin
  494. temp:=s[i+1];
  495. temp:=temp+s[i+2];
  496. inc(i,2);
  497. c:=chr(ParseVal(temp,16));
  498. end;
  499. else
  500. Begin
  501. Message1(asmr_e_escape_seq_ignored,s[i]);
  502. c:=s[i];
  503. end;
  504. end;
  505. end
  506. else
  507. c:=s[i];
  508. inc(len);
  509. hs[len]:=c;
  510. end;
  511. hs[0]:=chr(len);
  512. EscapeToPascal:=hs;
  513. end;
  514. Function ParseVal(const S:String;base:byte):aint;
  515. { Converts a decimal string to aint }
  516. var
  517. code : integer;
  518. errmsg : word;
  519. prefix : string[2];
  520. Begin
  521. case base of
  522. 2 :
  523. begin
  524. errmsg:=asmr_e_error_converting_binary;
  525. prefix:='%';
  526. end;
  527. 8 :
  528. begin
  529. errmsg:=asmr_e_error_converting_octal;
  530. prefix:='&';
  531. end;
  532. 10 :
  533. begin
  534. errmsg:=asmr_e_error_converting_decimal;
  535. prefix:='';
  536. end;
  537. 16 :
  538. begin
  539. errmsg:=asmr_e_error_converting_hexadecimal;
  540. prefix:='$';
  541. end;
  542. else
  543. internalerror(200501202);
  544. end;
  545. val(prefix+s,result,code);
  546. if code<>0 then
  547. begin
  548. val(prefix+s,aword(result),code);
  549. if code<>0 then
  550. begin
  551. Message1(errmsg,s);
  552. result:=0;
  553. end;
  554. end;
  555. end;
  556. Function PadZero(Var s: String; n: byte): Boolean;
  557. Begin
  558. PadZero:=TRUE;
  559. { Do some error checking first }
  560. if Length(s) = n then
  561. exit
  562. else
  563. if Length(s) > n then
  564. Begin
  565. PadZero:=FALSE;
  566. delete(s,n+1,length(s));
  567. exit;
  568. end
  569. else
  570. PadZero:=TRUE;
  571. { Fill it up with the specified character }
  572. fillchar(s[length(s)+1],n-1,#0);
  573. s[0]:=chr(n);
  574. end;
  575. {****************************************************************************
  576. TOperand
  577. ****************************************************************************}
  578. constructor TOperand.Create;
  579. begin
  580. size:=OS_NO;
  581. hastype:=false;
  582. hasvar:=false;
  583. FillChar(Opr,sizeof(Opr),0);
  584. end;
  585. destructor TOperand.destroy;
  586. begin
  587. end;
  588. Procedure TOperand.SetSize(_size:longint;force:boolean);
  589. begin
  590. if force or
  591. ((size = OS_NO) and (_size<=16)) then
  592. Begin
  593. case _size of
  594. 1 : size:=OS_8;
  595. 2 : size:=OS_16{ could be S_IS};
  596. 4 : size:=OS_32{ could be S_IL or S_FS};
  597. 8 : size:=OS_64{ could be S_D or S_FL};
  598. 10 : size:=OS_F80;
  599. 16 : size:=OS_128;
  600. end;
  601. end;
  602. end;
  603. Procedure TOperand.SetCorrectSize(opcode:tasmop);
  604. begin
  605. end;
  606. function TOperand.SetupResult:boolean;
  607. begin
  608. SetupResult:=false;
  609. { replace by correct offset. }
  610. with current_procinfo.procdef do
  611. if (not is_void(returndef)) then
  612. begin
  613. if (m_tp7 in current_settings.modeswitches) and
  614. not (df_generic in defoptions) and
  615. (not paramanager.ret_in_param(returndef,proccalloption)) then
  616. begin
  617. message(asmr_e_cannot_use_RESULT_here);
  618. exit;
  619. end;
  620. SetupResult:=setupvar('result',false)
  621. end
  622. else
  623. message(asmr_e_void_function);
  624. end;
  625. Function TOperand.SetupSelf:boolean;
  626. Begin
  627. SetupSelf:=false;
  628. if assigned(current_structdef) then
  629. SetupSelf:=setupvar('self',false)
  630. else
  631. Message(asmr_e_cannot_use_SELF_outside_a_method);
  632. end;
  633. Function TOperand.SetupOldEBP:boolean;
  634. Begin
  635. SetupOldEBP:=false;
  636. if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
  637. SetupOldEBP:=setupvar('parentframe',false)
  638. else
  639. Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
  640. end;
  641. Function TOperand.SetupVar(const s:string;GetOffset : boolean): Boolean;
  642. function symtable_has_localvarsyms(st:TSymtable):boolean;
  643. var
  644. sym : tsym;
  645. i : longint;
  646. begin
  647. result:=false;
  648. for i:=0 to st.SymList.Count-1 do
  649. begin
  650. sym:=tsym(st.SymList[i]);
  651. if sym.typ=localvarsym then
  652. begin
  653. result:=true;
  654. exit;
  655. end;
  656. end;
  657. end;
  658. procedure setconst(l:aint);
  659. begin
  660. { We return the address of the field, just like Delphi/TP }
  661. case opr.typ of
  662. OPR_NONE :
  663. begin
  664. opr.typ:=OPR_CONSTANT;
  665. opr.val:=l;
  666. end;
  667. OPR_CONSTANT :
  668. inc(opr.val,l);
  669. OPR_REFERENCE :
  670. inc(opr.ref.offset,l);
  671. OPR_LOCAL :
  672. inc(opr.localsymofs,l);
  673. else
  674. Message(asmr_e_invalid_operand_type);
  675. end;
  676. end;
  677. { search and sets up the correct fields in the Instr record }
  678. { for the NON-constant identifier passed to the routine. }
  679. { if not found returns FALSE. }
  680. var
  681. sym : tsym;
  682. srsymtable : TSymtable;
  683. harrdef : tarraydef;
  684. indexreg : tregister;
  685. l : aint;
  686. plist : ppropaccesslistitem;
  687. Begin
  688. SetupVar:=false;
  689. asmsearchsym(s,sym,srsymtable);
  690. if sym = nil then
  691. exit;
  692. if sym.typ=absolutevarsym then
  693. begin
  694. if (tabsolutevarsym(sym).abstyp=tovar) then
  695. begin
  696. { Only support simple loads }
  697. plist:=tabsolutevarsym(sym).ref.firstsym;
  698. if assigned(plist) and
  699. (plist^.sltype=sl_load) then
  700. sym:=plist^.sym
  701. else
  702. begin
  703. Message(asmr_e_unsupported_symbol_type);
  704. exit;
  705. end;
  706. end
  707. else
  708. begin
  709. Message(asmr_e_unsupported_symbol_type);
  710. exit;
  711. end;
  712. end;
  713. case sym.typ of
  714. fieldvarsym :
  715. begin
  716. if not tabstractrecordsymtable(sym.owner).is_packed then
  717. setconst(tfieldvarsym(sym).fieldoffset)
  718. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  719. setconst(tfieldvarsym(sym).fieldoffset div 8)
  720. else
  721. Message(asmr_e_packed_element);
  722. hasvar:=true;
  723. SetupVar:=true;
  724. end;
  725. staticvarsym,
  726. localvarsym,
  727. paravarsym :
  728. begin
  729. { we always assume in asm statements that }
  730. { that the variable is valid. }
  731. tabstractvarsym(sym).varstate:=vs_readwritten;
  732. inc(tabstractvarsym(sym).refs);
  733. { variable can't be placed in a register }
  734. tabstractvarsym(sym).varregable:=vr_none;
  735. { and anything may happen with its address }
  736. tabstractvarsym(sym).addr_taken:=true;
  737. case sym.typ of
  738. staticvarsym :
  739. begin
  740. initref;
  741. opr.ref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(sym).mangledname);
  742. end;
  743. paravarsym,
  744. localvarsym :
  745. begin
  746. if opr.typ=OPR_REFERENCE then
  747. begin
  748. indexreg:=opr.ref.base;
  749. if opr.ref.index<>NR_NO then
  750. begin
  751. if indexreg=NR_NO then
  752. indexreg:=opr.ref.index
  753. else
  754. Message(asmr_e_multiple_index);
  755. end;
  756. end
  757. else
  758. indexreg:=NR_NO;
  759. opr.typ:=OPR_LOCAL;
  760. if assigned(current_procinfo.parent) and
  761. not(po_inline in current_procinfo.procdef.procoptions) and
  762. (sym.owner<>current_procinfo.procdef.localst) and
  763. (sym.owner<>current_procinfo.procdef.parast) and
  764. (current_procinfo.procdef.localst.symtablelevel>normal_function_level) and
  765. symtable_has_localvarsyms(current_procinfo.procdef.localst) then
  766. message1(asmr_e_local_para_unreachable,s);
  767. opr.localsym:=tabstractnormalvarsym(sym);
  768. opr.localsymofs:=0;
  769. opr.localindexreg:=indexreg;
  770. opr.localscale:=0;
  771. opr.localgetoffset:=GetOffset;
  772. if paramanager.push_addr_param(tabstractvarsym(sym).varspez,tabstractvarsym(sym).vardef,current_procinfo.procdef.proccalloption) then
  773. SetSize(sizeof(pint),false);
  774. end;
  775. end;
  776. case tabstractvarsym(sym).vardef.typ of
  777. orddef,
  778. enumdef,
  779. pointerdef,
  780. floatdef :
  781. SetSize(tabstractvarsym(sym).getsize,false);
  782. arraydef :
  783. begin
  784. { for arrays try to get the element size, take care of
  785. multiple indexes }
  786. harrdef:=tarraydef(tabstractvarsym(sym).vardef);
  787. while assigned(harrdef.elementdef) and
  788. (harrdef.elementdef.typ=arraydef) do
  789. harrdef:=tarraydef(harrdef.elementdef);
  790. if not is_packed_array(harrdef) then
  791. SetSize(harrdef.elesize,false)
  792. else
  793. begin
  794. if (harrdef.elepackedbitsize mod 8) = 0 then
  795. SetSize(harrdef.elepackedbitsize div 8,false)
  796. end;
  797. end;
  798. end;
  799. hasvar:=true;
  800. SetupVar:=true;
  801. Exit;
  802. end;
  803. constsym :
  804. begin
  805. if tconstsym(sym).consttyp=constord then
  806. begin
  807. setconst(tconstsym(sym).value.valueord.svalue);
  808. SetupVar:=true;
  809. Exit;
  810. end;
  811. end;
  812. typesym :
  813. begin
  814. if ttypesym(sym).typedef.typ in [recorddef,objectdef] then
  815. begin
  816. setconst(0);
  817. SetupVar:=TRUE;
  818. Exit;
  819. end;
  820. end;
  821. procsym :
  822. begin
  823. if opr.typ<>OPR_NONE then
  824. Message(asmr_e_invalid_operand_type);
  825. if Tprocsym(sym).ProcdefList.Count>1 then
  826. Message(asmr_w_calling_overload_func);
  827. l:=opr.ref.offset;
  828. opr.typ:=OPR_SYMBOL;
  829. opr.symbol:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname);
  830. opr.symofs:=l;
  831. hasvar:=true;
  832. SetupVar:=TRUE;
  833. Exit;
  834. end;
  835. else
  836. begin
  837. Message(asmr_e_unsupported_symbol_type);
  838. exit;
  839. end;
  840. end;
  841. end;
  842. procedure TOperand.InitRef;
  843. {*********************************************************************}
  844. { Description: This routine first check if the opcode is of }
  845. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  846. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  847. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  848. { to point to the default segment. }
  849. {*********************************************************************}
  850. var
  851. l : aint;
  852. hsymofs : aint;
  853. hsymbol : tasmsymbol;
  854. reg : tregister;
  855. Begin
  856. case opr.typ of
  857. OPR_REFERENCE :
  858. exit;
  859. OPR_CONSTANT :
  860. begin
  861. l:=opr.val;
  862. opr.typ:=OPR_REFERENCE;
  863. Fillchar(opr.ref,sizeof(treference),0);
  864. opr.Ref.Offset:=l;
  865. end;
  866. OPR_NONE :
  867. begin
  868. opr.typ:=OPR_REFERENCE;
  869. Fillchar(opr.ref,sizeof(treference),0);
  870. end;
  871. OPR_REGISTER :
  872. begin
  873. reg:=opr.reg;
  874. opr.typ:=OPR_REFERENCE;
  875. Fillchar(opr.ref,sizeof(treference),0);
  876. opr.Ref.base:=reg;
  877. end;
  878. OPR_SYMBOL :
  879. begin
  880. hsymbol:=opr.symbol;
  881. hsymofs:=opr.symofs;
  882. opr.typ:=OPR_REFERENCE;
  883. Fillchar(opr.ref,sizeof(treference),0);
  884. opr.ref.symbol:=hsymbol;
  885. opr.ref.offset:=hsymofs;
  886. end;
  887. else
  888. begin
  889. Message(asmr_e_invalid_operand_type);
  890. { Recover }
  891. opr.typ:=OPR_REFERENCE;
  892. Fillchar(opr.ref,sizeof(treference),0);
  893. end;
  894. end;
  895. end;
  896. Function TOperand.CheckOperand: boolean;
  897. {*********************************************************************}
  898. { Description: This routine checks if the operand is of }
  899. { valid, and returns false if it isn't. Does nothing by default. }
  900. {*********************************************************************}
  901. begin
  902. result:=true;
  903. end;
  904. {****************************************************************************
  905. TInstruction
  906. ****************************************************************************}
  907. constructor TInstruction.create(optype : tcoperand);
  908. var
  909. i : longint;
  910. Begin
  911. { these field are set to 0 anyways by the constructor helper (FK)
  912. Opcode:=A_NONE;
  913. Condition:=C_NONE;
  914. Ops:=0;
  915. }
  916. for i:=1 to max_operands do
  917. Operands[i]:=optype.create;
  918. Labeled:=false;
  919. end;
  920. destructor TInstruction.destroy;
  921. var
  922. i : longint;
  923. Begin
  924. for i:=1 to max_operands do
  925. Operands[i].free;
  926. end;
  927. Procedure TInstruction.Swapoperands;
  928. Var
  929. p : toperand;
  930. Begin
  931. case ops of
  932. 0,1:
  933. ;
  934. 2 : begin
  935. { 0,1 -> 1,0 }
  936. p:=Operands[1];
  937. Operands[1]:=Operands[2];
  938. Operands[2]:=p;
  939. end;
  940. {$ifndef MAX_OPER_2}
  941. 3 : begin
  942. { 0,1,2 -> 2,1,0 }
  943. p:=Operands[1];
  944. Operands[1]:=Operands[3];
  945. Operands[3]:=p;
  946. end;
  947. {$ifndef MAX_OPER_3}
  948. 4 : begin
  949. { 0,1,2,3 -> 3,2,1,0 }
  950. p:=Operands[1];
  951. Operands[1]:=Operands[4];
  952. Operands[4]:=p;
  953. p:=Operands[2];
  954. Operands[2]:=Operands[3];
  955. Operands[3]:=p;
  956. end;
  957. {$endif}
  958. {$endif}
  959. else
  960. internalerror(201108142);
  961. end;
  962. end;
  963. function TInstruction.ConcatInstruction(p:TAsmList) : tai;
  964. var
  965. ai : taicpu;
  966. i : longint;
  967. begin
  968. for i:=1 to Ops do
  969. operands[i].CheckOperand;
  970. ai:=taicpu.op_none(opcode);
  971. ai.Ops:=Ops;
  972. ai.Allocate_oper(Ops);
  973. for i:=1 to Ops do
  974. with operands[i].opr do
  975. begin
  976. case typ of
  977. OPR_CONSTANT :
  978. ai.loadconst(i-1,val);
  979. OPR_REGISTER:
  980. ai.loadreg(i-1,reg);
  981. OPR_SYMBOL:
  982. ai.loadsymbol(i-1,symbol,symofs);
  983. OPR_LOCAL :
  984. ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
  985. localscale,localgetoffset,localforceref);
  986. OPR_REFERENCE:
  987. ai.loadref(i-1,ref);
  988. {$ifdef ARM}
  989. OPR_REGSET:
  990. ai.loadregset(i-1,regtype,subreg,regset);
  991. OPR_SHIFTEROP:
  992. ai.loadshifterop(i-1,shifterop);
  993. OPR_COND:
  994. ai.loadconditioncode(i-1,cc);
  995. OPR_MODEFLAGS:
  996. ai.loadmodeflags(i-1,flags);
  997. {$endif ARM}
  998. { ignore wrong operand }
  999. OPR_NONE:
  1000. ;
  1001. else
  1002. internalerror(200501051);
  1003. end;
  1004. end;
  1005. ai.SetCondition(condition);
  1006. { Concat the opcode or give an error }
  1007. if assigned(ai) then
  1008. p.concat(ai)
  1009. else
  1010. Message(asmr_e_invalid_opcode_and_operand);
  1011. result:=ai;
  1012. end;
  1013. {***************************************************************************
  1014. TLocalLabel
  1015. ***************************************************************************}
  1016. constructor TLocalLabel.create(AList:TFPHashObjectList;const n:string);
  1017. begin
  1018. inherited Create(AList,n);
  1019. lab:=nil;
  1020. emitted:=false;
  1021. end;
  1022. function TLocalLabel.Gettasmlabel:tasmlabel;
  1023. begin
  1024. if not assigned(lab) then
  1025. begin
  1026. current_asmdata.getjumplabel(lab);
  1027. { this label is forced to be used so it's always written }
  1028. lab.increfs;
  1029. end;
  1030. Gettasmlabel:=lab;
  1031. end;
  1032. {***************************************************************************
  1033. TLocalLabelList
  1034. ***************************************************************************}
  1035. procedure TLocalLabelList.CheckEmitted;
  1036. var
  1037. i : longint;
  1038. lab : TLocalLabel;
  1039. begin
  1040. for i:=0 to LocalLabelList.Count-1 do
  1041. begin
  1042. lab:=TLocalLabel(LocalLabelList[i]);
  1043. if not lab.emitted then
  1044. Message1(asmr_e_unknown_label_identifier,lab.name);
  1045. end;
  1046. end;
  1047. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  1048. var
  1049. lab : TLocalLabel;
  1050. Begin
  1051. CreateLocalLabel:=true;
  1052. { Check if it already is defined }
  1053. lab:=TLocalLabel(LocalLabellist.Find(s));
  1054. if not assigned(lab) then
  1055. lab:=TLocalLabel.Create(LocalLabellist,s);
  1056. { set emitted flag and check for dup syms }
  1057. if emit then
  1058. begin
  1059. if lab.Emitted then
  1060. begin
  1061. Message1(asmr_e_dup_local_sym,lab.Name);
  1062. CreateLocalLabel:=false;
  1063. end;
  1064. lab.Emitted:=true;
  1065. end;
  1066. hl:=lab.Gettasmlabel;
  1067. end;
  1068. {****************************************************************************
  1069. Symbol table helper routines
  1070. ****************************************************************************}
  1071. procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:TSymtable);
  1072. var
  1073. i : integer;
  1074. begin
  1075. i:=pos('.',s);
  1076. { allow unit.identifier }
  1077. if i>0 then
  1078. begin
  1079. searchsym(Copy(s,1,i-1),srsym,srsymtable);
  1080. if assigned(srsym) then
  1081. begin
  1082. if (srsym.typ=unitsym) and
  1083. (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
  1084. srsym.owner.iscurrentunit then
  1085. searchsym_in_module(tunitsym(srsym).module,Copy(s,i+1,255),srsym,srsymtable)
  1086. else
  1087. begin
  1088. srsym:=nil;
  1089. srsymtable:=nil;
  1090. end;
  1091. end;
  1092. end
  1093. else
  1094. searchsym(s,srsym,srsymtable);
  1095. end;
  1096. Function SearchType(const hs:string;var size:aint): Boolean;
  1097. var
  1098. srsym : tsym;
  1099. srsymtable : TSymtable;
  1100. begin
  1101. result:=false;
  1102. size:=0;
  1103. asmsearchsym(hs,srsym,srsymtable);
  1104. if assigned(srsym) and
  1105. (srsym.typ=typesym) then
  1106. begin
  1107. size:=ttypesym(srsym).typedef.size;
  1108. result:=true;
  1109. end;
  1110. end;
  1111. Function SearchRecordType(const s:string): boolean;
  1112. var
  1113. srsym : tsym;
  1114. srsymtable : TSymtable;
  1115. Begin
  1116. SearchRecordType:=false;
  1117. { Check the constants in symtable }
  1118. asmsearchsym(s,srsym,srsymtable);
  1119. if srsym <> nil then
  1120. Begin
  1121. case srsym.typ of
  1122. typesym :
  1123. begin
  1124. if ttypesym(srsym).typedef.typ in [recorddef,objectdef] then
  1125. begin
  1126. SearchRecordType:=true;
  1127. exit;
  1128. end;
  1129. end;
  1130. fieldvarsym :
  1131. begin
  1132. if (tfieldvarsym(srsym).vardef.typ in [recorddef,objectdef]) then
  1133. begin
  1134. SearchRecordType:=true;
  1135. exit;
  1136. end;
  1137. end;
  1138. end;
  1139. end;
  1140. end;
  1141. Function SearchIConstant(const s:string; var l:aint): boolean;
  1142. {**********************************************************************}
  1143. { Description: Searches for a CONSTANT of name s in either the local }
  1144. { symbol list, then in the global symbol list, and returns the value }
  1145. { of that constant in l. Returns TRUE if successfull, if not found, }
  1146. { or if the constant is not of correct type, then returns FALSE }
  1147. { Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
  1148. { respectively. }
  1149. {**********************************************************************}
  1150. var
  1151. srsym : tsym;
  1152. srsymtable : TSymtable;
  1153. Begin
  1154. SearchIConstant:=false;
  1155. { check for TRUE or FALSE reserved words first }
  1156. if s = 'TRUE' then
  1157. Begin
  1158. SearchIConstant:=TRUE;
  1159. l:=1;
  1160. exit;
  1161. end;
  1162. if s = 'FALSE' then
  1163. Begin
  1164. SearchIConstant:=TRUE;
  1165. l:=0;
  1166. exit;
  1167. end;
  1168. { Check the constants in symtable }
  1169. asmsearchsym(s,srsym,srsymtable);
  1170. if srsym <> nil then
  1171. Begin
  1172. case srsym.typ of
  1173. constsym :
  1174. begin
  1175. if tconstsym(srsym).consttyp=constord then
  1176. Begin
  1177. l:=tconstsym(srsym).value.valueord.svalue;
  1178. SearchIConstant:=TRUE;
  1179. exit;
  1180. end;
  1181. end;
  1182. enumsym:
  1183. Begin
  1184. l:=tenumsym(srsym).value;
  1185. SearchIConstant:=TRUE;
  1186. exit;
  1187. end;
  1188. end;
  1189. end;
  1190. end;
  1191. Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean;
  1192. { search and returns the offset and size of records/objects of the base }
  1193. { with field name setup in field. }
  1194. { returns FALSE if not found. }
  1195. { used when base is a variable or a typed constant name. }
  1196. var
  1197. st : TSymtable;
  1198. harrdef : tarraydef;
  1199. sym : tsym;
  1200. srsymtable : TSymtable;
  1201. i : longint;
  1202. base : string;
  1203. procdef: tprocdef;
  1204. Begin
  1205. GetRecordOffsetSize:=FALSE;
  1206. Offset:=0;
  1207. Size:=0;
  1208. mangledname:='';
  1209. i:=pos('.',s);
  1210. if i=0 then
  1211. i:=255;
  1212. base:=Copy(s,1,i-1);
  1213. delete(s,1,i);
  1214. if base='SELF' then
  1215. st:=current_structdef.symtable
  1216. else
  1217. begin
  1218. asmsearchsym(base,sym,srsymtable);
  1219. st:=nil;
  1220. { we can start with a var,type,typedconst }
  1221. if assigned(sym) then
  1222. case sym.typ of
  1223. staticvarsym,
  1224. localvarsym,
  1225. paravarsym :
  1226. st:=Tabstractvarsym(sym).vardef.GetSymtable(gs_record);
  1227. typesym :
  1228. st:=Ttypesym(sym).typedef.GetSymtable(gs_record);
  1229. end
  1230. else
  1231. s:='';
  1232. end;
  1233. { now walk all recordsymtables }
  1234. while assigned(st) and (s<>'') do
  1235. begin
  1236. { load next field in base }
  1237. i:=pos('.',s);
  1238. if i=0 then
  1239. i:=255;
  1240. base:=Copy(s,1,i-1);
  1241. delete(s,1,i);
  1242. sym:=search_struct_member(tabstractrecorddef(st.defowner),base);
  1243. if not assigned(sym) then
  1244. begin
  1245. GetRecordOffsetSize:=false;
  1246. exit;
  1247. end;
  1248. st:=nil;
  1249. case sym.typ of
  1250. fieldvarsym :
  1251. with Tfieldvarsym(sym) do
  1252. begin
  1253. if not tabstractrecordsymtable(sym.owner).is_packed then
  1254. inc(Offset,fieldoffset)
  1255. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  1256. inc(Offset,fieldoffset div 8)
  1257. else
  1258. Message(asmr_e_packed_element);
  1259. size:=getsize;
  1260. case vardef.typ of
  1261. arraydef :
  1262. begin
  1263. { for arrays try to get the element size, take care of
  1264. multiple indexes }
  1265. harrdef:=tarraydef(vardef);
  1266. while assigned(harrdef.elementdef) and
  1267. (harrdef.elementdef.typ=arraydef) do
  1268. harrdef:=tarraydef(harrdef.elementdef);
  1269. if not is_packed_array(harrdef) then
  1270. size:=harrdef.elesize
  1271. else
  1272. begin
  1273. if (harrdef.elepackedbitsize mod 8) <> 0 then
  1274. Message(asmr_e_packed_element);
  1275. size := (harrdef.elepackedbitsize + 7) div 8;
  1276. end;
  1277. end;
  1278. recorddef :
  1279. st:=trecorddef(vardef).symtable;
  1280. objectdef :
  1281. st:=tobjectdef(vardef).symtable;
  1282. end;
  1283. end;
  1284. procsym:
  1285. begin
  1286. st:=nil;
  1287. if Tprocsym(sym).ProcdefList.Count>1 then
  1288. Message(asmr_w_calling_overload_func);
  1289. procdef:=tprocdef(tprocsym(sym).ProcdefList[0]);
  1290. if (not needvmtofs) then
  1291. begin
  1292. mangledname:=procdef.mangledname;
  1293. end
  1294. else
  1295. begin
  1296. { can only get the vmtoffset of virtual methods }
  1297. if not(po_virtualmethod in procdef.procoptions) or
  1298. is_objectpascal_helper(procdef.struct) then
  1299. Message1(asmr_e_no_vmtoffset_possible,FullTypeName(procdef,nil))
  1300. else
  1301. begin
  1302. { size = sizeof(target_system_pointer) }
  1303. size:=sizeof(pint);
  1304. offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)
  1305. end;
  1306. end;
  1307. { if something comes after the procsym, it's invalid assembler syntax }
  1308. GetRecordOffsetSize:=(s='');
  1309. exit;
  1310. end;
  1311. end;
  1312. end;
  1313. { Support Field.Type as typecasting }
  1314. if (st=nil) and (s<>'') then
  1315. begin
  1316. asmsearchsym(s,sym,srsymtable);
  1317. if assigned(sym) and (sym.typ=typesym) then
  1318. begin
  1319. size:=ttypesym(sym).typedef.size;
  1320. s:=''
  1321. end;
  1322. end;
  1323. GetRecordOffsetSize:=(s='');
  1324. end;
  1325. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  1326. var
  1327. sym : tsym;
  1328. srsymtable : TSymtable;
  1329. hs : string;
  1330. Begin
  1331. hl:=nil;
  1332. SearchLabel:=false;
  1333. { Check for pascal labels, which are case insensetive }
  1334. hs:=upper(s);
  1335. asmsearchsym(hs,sym,srsymtable);
  1336. if sym=nil then
  1337. exit;
  1338. case sym.typ of
  1339. labelsym :
  1340. begin
  1341. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1342. begin
  1343. Tlabelsym(sym).nonlocal:=true;
  1344. if emit then
  1345. exclude(current_procinfo.procdef.procoptions,po_inline);
  1346. end;
  1347. if not(assigned(tlabelsym(sym).asmblocklabel)) then
  1348. if Tlabelsym(sym).nonlocal then
  1349. current_asmdata.getglobaljumplabel(tlabelsym(sym).asmblocklabel)
  1350. else
  1351. current_asmdata.getjumplabel(tlabelsym(sym).asmblocklabel);
  1352. hl:=tlabelsym(sym).asmblocklabel;
  1353. if emit then
  1354. tlabelsym(sym).defined:=true
  1355. else
  1356. tlabelsym(sym).used:=true;
  1357. SearchLabel:=true;
  1358. end;
  1359. end;
  1360. end;
  1361. {*************************************************************************}
  1362. { Instruction Generation Utilities }
  1363. {*************************************************************************}
  1364. Procedure ConcatString(p : TAsmList;s:string);
  1365. {*********************************************************************}
  1366. { PROCEDURE ConcatString(s:string); }
  1367. { Description: This routine adds the character chain pointed to in }
  1368. { s to the instruction linked list. }
  1369. {*********************************************************************}
  1370. Var
  1371. pc: PChar;
  1372. Begin
  1373. getmem(pc,length(s)+1);
  1374. p.concat(Tai_string.Create_pchar(strpcopy(pc,s),length(s)));
  1375. end;
  1376. Procedure ConcatPasString(p : TAsmList;s:string);
  1377. {*********************************************************************}
  1378. { PROCEDURE ConcatPasString(s:string); }
  1379. { Description: This routine adds the character chain pointed to in }
  1380. { s to the instruction linked list, contrary to ConcatString it }
  1381. { uses a pascal style string, so it conserves null characters. }
  1382. {*********************************************************************}
  1383. Begin
  1384. p.concat(Tai_string.Create(s));
  1385. end;
  1386. Procedure ConcatConstant(p: TAsmList; value: aint; constsize:byte);
  1387. {*********************************************************************}
  1388. { PROCEDURE ConcatConstant(value: aint; maxvalue: aint); }
  1389. { Description: This routine adds the value constant to the current }
  1390. { instruction linked list. }
  1391. { maxvalue -> indicates the size of the data to initialize: }
  1392. { $ff -> create a byte node. }
  1393. { $ffff -> create a word node. }
  1394. { $ffffffff -> create a dword node. }
  1395. {*********************************************************************}
  1396. var
  1397. rangelo,rangehi : int64;
  1398. Begin
  1399. case constsize of
  1400. 1 :
  1401. begin
  1402. p.concat(Tai_const.Create_8bit(byte(value)));
  1403. rangelo:=low(shortint);
  1404. rangehi:=high(byte);
  1405. end;
  1406. 2 :
  1407. begin
  1408. p.concat(Tai_const.Create_16bit(word(value)));
  1409. rangelo:=low(smallint);
  1410. rangehi:=high(word);
  1411. end;
  1412. 4 :
  1413. begin
  1414. p.concat(Tai_const.Create_32bit(longint(value)));
  1415. rangelo:=low(longint);
  1416. rangehi:=high(cardinal);
  1417. end;
  1418. 8 :
  1419. begin
  1420. p.concat(Tai_const.Create_64bit(int64(value)));
  1421. rangelo:=0;
  1422. rangehi:=0;
  1423. end;
  1424. else
  1425. internalerror(200405011);
  1426. end;
  1427. { check for out of bounds }
  1428. if (rangelo<>0) and
  1429. ((value>rangehi) or (value<rangelo)) then
  1430. Message(asmr_e_constant_out_of_bounds);
  1431. end;
  1432. Procedure ConcatConstSymbol(p : TAsmList;const sym:string;symtyp:tasmsymtype;l:aint);
  1433. begin
  1434. p.concat(Tai_const.Createname(sym,l));
  1435. end;
  1436. Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
  1437. {***********************************************************************}
  1438. { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
  1439. { Description: This routine adds the value constant to the current }
  1440. { instruction linked list. }
  1441. { real_typ -> indicates the type of the real data to initialize: }
  1442. { s32real -> create a single node. }
  1443. { s64real -> create a double node. }
  1444. { s80real -> create an extended node. }
  1445. { s64bit -> create a comp node. }
  1446. { f32bit -> create a fixed node. (not used normally) }
  1447. {***********************************************************************}
  1448. Begin
  1449. case real_typ of
  1450. s32real : p.concat(Tai_real_32bit.Create(value));
  1451. s64real :
  1452. {$ifdef ARM}
  1453. if is_double_hilo_swapped then
  1454. p.concat(Tai_real_64bit.Create_hiloswapped(value))
  1455. else
  1456. {$endif ARM}
  1457. p.concat(Tai_real_64bit.Create(value));
  1458. s80real : p.concat(Tai_real_80bit.Create(value,s80floattype.size));
  1459. sc80real : p.concat(Tai_real_80bit.Create(value,sc80floattype.size));
  1460. s64comp : p.concat(Tai_comp_64bit.Create(trunc(value)));
  1461. end;
  1462. end;
  1463. Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
  1464. {*********************************************************************}
  1465. { PROCEDURE ConcatLabel }
  1466. { Description: This routine either emits a label or a labeled }
  1467. { instruction to the linked list of instructions. }
  1468. {*********************************************************************}
  1469. begin
  1470. p.concat(Tai_label.Create(l));
  1471. end;
  1472. procedure ConcatAlign(p:TAsmList;l:aint);
  1473. {*********************************************************************}
  1474. { PROCEDURE ConcatPublic }
  1475. { Description: This routine emits an global definition to the }
  1476. { linked list of instructions.(used by AT&T styled asm) }
  1477. {*********************************************************************}
  1478. begin
  1479. p.concat(Tai_align.Create(l));
  1480. end;
  1481. procedure ConcatPublic(p:TAsmList;const s : string);
  1482. {*********************************************************************}
  1483. { PROCEDURE ConcatPublic }
  1484. { Description: This routine emits an global definition to the }
  1485. { linked list of instructions.(used by AT&T styled asm) }
  1486. {*********************************************************************}
  1487. begin
  1488. p.concat(Tai_symbol.Createname_global(s,AT_LABEL,0));
  1489. end;
  1490. procedure ConcatLocal(p:TAsmList;const s : string);
  1491. {*********************************************************************}
  1492. { PROCEDURE ConcatLocal }
  1493. { Description: This routine emits an local definition to the }
  1494. { linked list of instructions. }
  1495. {*********************************************************************}
  1496. begin
  1497. p.concat(Tai_symbol.Createname(s,AT_LABEL,0));
  1498. end;
  1499. end.