rautils.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  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. {---------------------------------------------------------------------
  28. Local Label Management
  29. ---------------------------------------------------------------------}
  30. Type
  31. { Each local label has this structure associated with it }
  32. TLocalLabel = class(TFPHashObject)
  33. Emitted : boolean;
  34. constructor Create(AList:TFPHashObjectList;const n:string);
  35. function Gettasmlabel:tasmlabel;
  36. private
  37. lab : tasmlabel;
  38. end;
  39. TLocalLabelList = class(TFPHashObjectList)
  40. procedure CheckEmitted;
  41. end;
  42. var
  43. LocalLabelList : TLocalLabelList;
  44. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  45. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  46. {---------------------------------------------------------------------
  47. Instruction management
  48. ---------------------------------------------------------------------}
  49. type
  50. TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
  51. OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_COH,OPR_REGISTERSELECTOR);
  52. TOprRec = record
  53. case typ:TOprType of
  54. OPR_NONE : ();
  55. OPR_CONSTANT : (val:aint);
  56. OPR_SYMBOL : (symbol:tasmsymbol;symofs:aint);
  57. OPR_REFERENCE : (ref:treference);
  58. OPR_LOCAL : (localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
  59. OPR_REGISTER : (reg:tregister);
  60. {$ifdef m68k}
  61. OPR_REGLIST : (regset : tcpuregisterset);
  62. {$endif m68k}
  63. {$ifdef powerpc}
  64. OPR_COND : (cond : tasmcond);
  65. {$endif powerpc}
  66. {$ifdef POWERPC64}
  67. OPR_COND : (cond : tasmcond);
  68. {$endif POWERPC64}
  69. {$ifdef arm}
  70. OPR_REGSET : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister);
  71. OPR_SHIFTEROP : (shifterop : tshifterop);
  72. OPR_COND : (cc : tasmcond);
  73. OPR_MODEFLAGS : (flags : tcpumodeflags);
  74. {$endif arm}
  75. {$ifdef avr32}
  76. OPR_REGSET : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister);
  77. OPR_SHIFTEROP : (shifterop : tshifterop);
  78. OPR_COH : ();
  79. OPR_REGISTERSELECTOR : (topreg : tregister; selector : tregisterselector);
  80. {$endif avr32}
  81. end;
  82. TOperand = class
  83. typesize : aint;
  84. hastype, { if the operand has typecasted variable }
  85. hasvar : boolean; { if the operand is loaded with a variable }
  86. size : TCGSize;
  87. opr : TOprRec;
  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. opcode : tasmop;
  102. condition : tasmcond;
  103. ops : byte;
  104. labeled : boolean;
  105. operands : array[1..max_operands] of toperand;
  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 paramanager.ret_in_param(returndef,proccalloption)) then
  615. begin
  616. message(asmr_e_cannot_use_RESULT_here);
  617. exit;
  618. end;
  619. SetupResult:=setupvar('result',false)
  620. end
  621. else
  622. message(asmr_e_void_function);
  623. end;
  624. Function TOperand.SetupSelf:boolean;
  625. Begin
  626. SetupSelf:=false;
  627. if assigned(current_structdef) then
  628. SetupSelf:=setupvar('self',false)
  629. else
  630. Message(asmr_e_cannot_use_SELF_outside_a_method);
  631. end;
  632. Function TOperand.SetupOldEBP:boolean;
  633. Begin
  634. SetupOldEBP:=false;
  635. if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
  636. SetupOldEBP:=setupvar('parentframe',false)
  637. else
  638. Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
  639. end;
  640. Function TOperand.SetupVar(const s:string;GetOffset : boolean): Boolean;
  641. function symtable_has_localvarsyms(st:TSymtable):boolean;
  642. var
  643. sym : tsym;
  644. i : longint;
  645. begin
  646. result:=false;
  647. for i:=0 to st.SymList.Count-1 do
  648. begin
  649. sym:=tsym(st.SymList[i]);
  650. if sym.typ=localvarsym then
  651. begin
  652. result:=true;
  653. exit;
  654. end;
  655. end;
  656. end;
  657. procedure setconst(l:aint);
  658. begin
  659. { We return the address of the field, just like Delphi/TP }
  660. case opr.typ of
  661. OPR_NONE :
  662. begin
  663. opr.typ:=OPR_CONSTANT;
  664. opr.val:=l;
  665. end;
  666. OPR_CONSTANT :
  667. inc(opr.val,l);
  668. OPR_REFERENCE :
  669. inc(opr.ref.offset,l);
  670. OPR_LOCAL :
  671. inc(opr.localsymofs,l);
  672. else
  673. Message(asmr_e_invalid_operand_type);
  674. end;
  675. end;
  676. { search and sets up the correct fields in the Instr record }
  677. { for the NON-constant identifier passed to the routine. }
  678. { if not found returns FALSE. }
  679. var
  680. sym : tsym;
  681. srsymtable : TSymtable;
  682. harrdef : tarraydef;
  683. indexreg : tregister;
  684. l : aint;
  685. plist : ppropaccesslistitem;
  686. Begin
  687. SetupVar:=false;
  688. asmsearchsym(s,sym,srsymtable);
  689. if sym = nil then
  690. exit;
  691. if sym.typ=absolutevarsym then
  692. begin
  693. if (tabsolutevarsym(sym).abstyp=tovar) then
  694. begin
  695. { Only support simple loads }
  696. plist:=tabsolutevarsym(sym).ref.firstsym;
  697. if assigned(plist) and
  698. (plist^.sltype=sl_load) then
  699. sym:=plist^.sym
  700. else
  701. begin
  702. Message(asmr_e_unsupported_symbol_type);
  703. exit;
  704. end;
  705. end
  706. else
  707. begin
  708. Message(asmr_e_unsupported_symbol_type);
  709. exit;
  710. end;
  711. end;
  712. case sym.typ of
  713. fieldvarsym :
  714. begin
  715. if not tabstractrecordsymtable(sym.owner).is_packed then
  716. setconst(tfieldvarsym(sym).fieldoffset)
  717. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  718. setconst(tfieldvarsym(sym).fieldoffset div 8)
  719. else
  720. Message(asmr_e_packed_element);
  721. hasvar:=true;
  722. SetupVar:=true;
  723. end;
  724. staticvarsym,
  725. localvarsym,
  726. paravarsym :
  727. begin
  728. { we always assume in asm statements that }
  729. { that the variable is valid. }
  730. tabstractvarsym(sym).varstate:=vs_readwritten;
  731. inc(tabstractvarsym(sym).refs);
  732. { variable can't be placed in a register }
  733. tabstractvarsym(sym).varregable:=vr_none;
  734. { and anything may happen with its address }
  735. tabstractvarsym(sym).addr_taken:=true;
  736. case sym.typ of
  737. staticvarsym :
  738. begin
  739. initref;
  740. opr.ref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(sym).mangledname);
  741. end;
  742. paravarsym,
  743. localvarsym :
  744. begin
  745. if opr.typ=OPR_REFERENCE then
  746. begin
  747. indexreg:=opr.ref.base;
  748. if opr.ref.index<>NR_NO then
  749. begin
  750. if indexreg=NR_NO then
  751. indexreg:=opr.ref.index
  752. else
  753. Message(asmr_e_multiple_index);
  754. end;
  755. end
  756. else
  757. indexreg:=NR_NO;
  758. opr.typ:=OPR_LOCAL;
  759. if assigned(current_procinfo.parent) and
  760. not(po_inline in current_procinfo.procdef.procoptions) and
  761. (sym.owner<>current_procinfo.procdef.localst) and
  762. (sym.owner<>current_procinfo.procdef.parast) and
  763. (current_procinfo.procdef.localst.symtablelevel>normal_function_level) and
  764. symtable_has_localvarsyms(current_procinfo.procdef.localst) then
  765. message1(asmr_e_local_para_unreachable,s);
  766. opr.localsym:=tabstractnormalvarsym(sym);
  767. opr.localsymofs:=0;
  768. opr.localindexreg:=indexreg;
  769. opr.localscale:=0;
  770. opr.localgetoffset:=GetOffset;
  771. if paramanager.push_addr_param(tabstractvarsym(sym).varspez,tabstractvarsym(sym).vardef,current_procinfo.procdef.proccalloption) then
  772. SetSize(sizeof(pint),false);
  773. end;
  774. end;
  775. case tabstractvarsym(sym).vardef.typ of
  776. orddef,
  777. enumdef,
  778. pointerdef,
  779. floatdef :
  780. SetSize(tabstractvarsym(sym).getsize,false);
  781. arraydef :
  782. begin
  783. { for arrays try to get the element size, take care of
  784. multiple indexes }
  785. harrdef:=tarraydef(tabstractvarsym(sym).vardef);
  786. while assigned(harrdef.elementdef) and
  787. (harrdef.elementdef.typ=arraydef) do
  788. harrdef:=tarraydef(harrdef.elementdef);
  789. if not is_packed_array(harrdef) then
  790. SetSize(harrdef.elesize,false)
  791. else
  792. begin
  793. if (harrdef.elepackedbitsize mod 8) = 0 then
  794. SetSize(harrdef.elepackedbitsize div 8,false)
  795. end;
  796. end;
  797. end;
  798. hasvar:=true;
  799. SetupVar:=true;
  800. Exit;
  801. end;
  802. constsym :
  803. begin
  804. if tconstsym(sym).consttyp=constord then
  805. begin
  806. setconst(tconstsym(sym).value.valueord.svalue);
  807. SetupVar:=true;
  808. Exit;
  809. end;
  810. end;
  811. typesym :
  812. begin
  813. if ttypesym(sym).typedef.typ in [recorddef,objectdef] then
  814. begin
  815. setconst(0);
  816. SetupVar:=TRUE;
  817. Exit;
  818. end;
  819. end;
  820. procsym :
  821. begin
  822. if opr.typ<>OPR_NONE then
  823. Message(asmr_e_invalid_operand_type);
  824. if Tprocsym(sym).ProcdefList.Count>1 then
  825. Message(asmr_w_calling_overload_func);
  826. l:=opr.ref.offset;
  827. opr.typ:=OPR_SYMBOL;
  828. opr.symbol:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname);
  829. opr.symofs:=l;
  830. hasvar:=true;
  831. SetupVar:=TRUE;
  832. Exit;
  833. end;
  834. else
  835. begin
  836. Message(asmr_e_unsupported_symbol_type);
  837. exit;
  838. end;
  839. end;
  840. end;
  841. procedure TOperand.InitRef;
  842. {*********************************************************************}
  843. { Description: This routine first check if the opcode is of }
  844. { type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
  845. { If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
  846. { the operand type to OPR_REFERENCE, as well as setting up the ref }
  847. { to point to the default segment. }
  848. {*********************************************************************}
  849. var
  850. l : aint;
  851. hsymofs : aint;
  852. hsymbol : tasmsymbol;
  853. reg : tregister;
  854. Begin
  855. case opr.typ of
  856. OPR_REFERENCE :
  857. exit;
  858. OPR_CONSTANT :
  859. begin
  860. l:=opr.val;
  861. opr.typ:=OPR_REFERENCE;
  862. Fillchar(opr.ref,sizeof(treference),0);
  863. opr.Ref.Offset:=l;
  864. end;
  865. OPR_NONE :
  866. begin
  867. opr.typ:=OPR_REFERENCE;
  868. Fillchar(opr.ref,sizeof(treference),0);
  869. end;
  870. OPR_REGISTER :
  871. begin
  872. reg:=opr.reg;
  873. opr.typ:=OPR_REFERENCE;
  874. Fillchar(opr.ref,sizeof(treference),0);
  875. opr.Ref.base:=reg;
  876. end;
  877. OPR_SYMBOL :
  878. begin
  879. hsymbol:=opr.symbol;
  880. hsymofs:=opr.symofs;
  881. opr.typ:=OPR_REFERENCE;
  882. Fillchar(opr.ref,sizeof(treference),0);
  883. opr.ref.symbol:=hsymbol;
  884. opr.ref.offset:=hsymofs;
  885. end;
  886. else
  887. begin
  888. Message(asmr_e_invalid_operand_type);
  889. { Recover }
  890. opr.typ:=OPR_REFERENCE;
  891. Fillchar(opr.ref,sizeof(treference),0);
  892. end;
  893. end;
  894. end;
  895. Function TOperand.CheckOperand: boolean;
  896. {*********************************************************************}
  897. { Description: This routine checks if the operand is of }
  898. { valid, and returns false if it isn't. Does nothing by default. }
  899. {*********************************************************************}
  900. begin
  901. result:=true;
  902. end;
  903. {****************************************************************************
  904. TInstruction
  905. ****************************************************************************}
  906. constructor TInstruction.create(optype : tcoperand);
  907. var
  908. i : longint;
  909. Begin
  910. { these field are set to 0 anyways by the constructor helper (FK)
  911. Opcode:=A_NONE;
  912. Condition:=C_NONE;
  913. Ops:=0;
  914. }
  915. for i:=1 to max_operands do
  916. Operands[i]:=optype.create;
  917. Labeled:=false;
  918. end;
  919. destructor TInstruction.destroy;
  920. var
  921. i : longint;
  922. Begin
  923. for i:=1 to max_operands do
  924. Operands[i].free;
  925. end;
  926. Procedure TInstruction.Swapoperands;
  927. Var
  928. p : toperand;
  929. Begin
  930. case Ops of
  931. 2 :
  932. begin
  933. p:=Operands[1];
  934. Operands[1]:=Operands[2];
  935. Operands[2]:=p;
  936. end;
  937. 3 :
  938. begin
  939. p:=Operands[1];
  940. Operands[1]:=Operands[3];
  941. Operands[3]:=p;
  942. end;
  943. end;
  944. end;
  945. function TInstruction.ConcatInstruction(p:TAsmList) : tai;
  946. var
  947. ai : taicpu;
  948. i : longint;
  949. begin
  950. for i:=1 to Ops do
  951. operands[i].CheckOperand;
  952. ai:=taicpu.op_none(opcode);
  953. ai.Ops:=Ops;
  954. ai.Allocate_oper(Ops);
  955. for i:=1 to Ops do
  956. with operands[i].opr do
  957. begin
  958. case typ of
  959. OPR_CONSTANT :
  960. ai.loadconst(i-1,val);
  961. OPR_REGISTER:
  962. ai.loadreg(i-1,reg);
  963. OPR_SYMBOL:
  964. ai.loadsymbol(i-1,symbol,symofs);
  965. OPR_LOCAL :
  966. ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
  967. localscale,localgetoffset,localforceref);
  968. OPR_REFERENCE:
  969. ai.loadref(i-1,ref);
  970. {$ifdef ARM}
  971. OPR_REGSET:
  972. ai.loadregset(i-1,regtype,subreg,regset);
  973. OPR_SHIFTEROP:
  974. ai.loadshifterop(i-1,shifterop);
  975. OPR_COND:
  976. ai.loadconditioncode(i-1,cc);
  977. OPR_MODEFLAGS:
  978. ai.loadmodeflags(i-1,flags);
  979. {$endif ARM}
  980. {$ifdef AVR32}
  981. OPR_REGSET:
  982. ai.loadregset(i-1,regtype,subreg,regset);
  983. OPR_SHIFTEROP:
  984. ai.loadshifterop(i-1,shifterop);
  985. OPR_COH:
  986. ai.loadCOH(i-1);
  987. OPR_REGISTERSELECTOR:
  988. ai.loadregisterselector(i-1,topreg,selector);
  989. {$endif AVR32}
  990. { ignore wrong operand }
  991. OPR_NONE:
  992. ;
  993. else
  994. internalerror(200501051);
  995. end;
  996. end;
  997. ai.SetCondition(condition);
  998. { Concat the opcode or give an error }
  999. if assigned(ai) then
  1000. p.concat(ai)
  1001. else
  1002. Message(asmr_e_invalid_opcode_and_operand);
  1003. result:=ai;
  1004. end;
  1005. {***************************************************************************
  1006. TLocalLabel
  1007. ***************************************************************************}
  1008. constructor TLocalLabel.create(AList:TFPHashObjectList;const n:string);
  1009. begin
  1010. inherited Create(AList,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. current_asmdata.getjumplabel(lab);
  1019. { this label is forced to be used so it's always written }
  1020. lab.increfs;
  1021. end;
  1022. Gettasmlabel:=lab;
  1023. end;
  1024. {***************************************************************************
  1025. TLocalLabelList
  1026. ***************************************************************************}
  1027. procedure TLocalLabelList.CheckEmitted;
  1028. var
  1029. i : longint;
  1030. lab : TLocalLabel;
  1031. begin
  1032. for i:=0 to LocalLabelList.Count-1 do
  1033. begin
  1034. lab:=TLocalLabel(LocalLabelList[i]);
  1035. if not lab.emitted then
  1036. Message1(asmr_e_unknown_label_identifier,lab.name);
  1037. end;
  1038. end;
  1039. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  1040. var
  1041. lab : TLocalLabel;
  1042. Begin
  1043. CreateLocalLabel:=true;
  1044. { Check if it already is defined }
  1045. lab:=TLocalLabel(LocalLabellist.Find(s));
  1046. if not assigned(lab) then
  1047. lab:=TLocalLabel.Create(LocalLabellist,s);
  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.symtabletype in [staticsymtable,globalsymtable]) and
  1076. srsym.owner.iscurrentunit then
  1077. searchsym_in_module(tunitsym(srsym).module,Copy(s,i+1,255),srsym,srsymtable)
  1078. else
  1079. begin
  1080. srsym:=nil;
  1081. srsymtable:=nil;
  1082. end;
  1083. end;
  1084. end
  1085. else
  1086. searchsym(s,srsym,srsymtable);
  1087. end;
  1088. Function SearchType(const hs:string;var size:aint): Boolean;
  1089. var
  1090. srsym : tsym;
  1091. srsymtable : TSymtable;
  1092. begin
  1093. result:=false;
  1094. size:=0;
  1095. asmsearchsym(hs,srsym,srsymtable);
  1096. if assigned(srsym) and
  1097. (srsym.typ=typesym) then
  1098. begin
  1099. size:=ttypesym(srsym).typedef.size;
  1100. result:=true;
  1101. end;
  1102. end;
  1103. Function SearchRecordType(const s:string): boolean;
  1104. var
  1105. srsym : tsym;
  1106. srsymtable : TSymtable;
  1107. Begin
  1108. SearchRecordType:=false;
  1109. { Check the constants in symtable }
  1110. asmsearchsym(s,srsym,srsymtable);
  1111. if srsym <> nil then
  1112. Begin
  1113. case srsym.typ of
  1114. typesym :
  1115. begin
  1116. if ttypesym(srsym).typedef.typ in [recorddef,objectdef] then
  1117. begin
  1118. SearchRecordType:=true;
  1119. exit;
  1120. end;
  1121. end;
  1122. fieldvarsym :
  1123. begin
  1124. if (tfieldvarsym(srsym).vardef.typ in [recorddef,objectdef]) then
  1125. begin
  1126. SearchRecordType:=true;
  1127. exit;
  1128. end;
  1129. end;
  1130. end;
  1131. end;
  1132. end;
  1133. Function SearchIConstant(const s:string; var l:aint): boolean;
  1134. {**********************************************************************}
  1135. { Description: Searches for a CONSTANT of name s in either the local }
  1136. { symbol list, then in the global symbol list, and returns the value }
  1137. { of that constant in l. Returns TRUE if successfull, if not found, }
  1138. { or if the constant is not of correct type, then returns FALSE }
  1139. { Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
  1140. { respectively. }
  1141. {**********************************************************************}
  1142. var
  1143. srsym : tsym;
  1144. srsymtable : TSymtable;
  1145. Begin
  1146. SearchIConstant:=false;
  1147. { check for TRUE or FALSE reserved words first }
  1148. if s = 'TRUE' then
  1149. Begin
  1150. SearchIConstant:=TRUE;
  1151. l:=1;
  1152. exit;
  1153. end;
  1154. if s = 'FALSE' then
  1155. Begin
  1156. SearchIConstant:=TRUE;
  1157. l:=0;
  1158. exit;
  1159. end;
  1160. { Check the constants in symtable }
  1161. asmsearchsym(s,srsym,srsymtable);
  1162. if srsym <> nil then
  1163. Begin
  1164. case srsym.typ of
  1165. constsym :
  1166. begin
  1167. if tconstsym(srsym).consttyp=constord then
  1168. Begin
  1169. l:=tconstsym(srsym).value.valueord.svalue;
  1170. SearchIConstant:=TRUE;
  1171. exit;
  1172. end;
  1173. end;
  1174. enumsym:
  1175. Begin
  1176. l:=tenumsym(srsym).value;
  1177. SearchIConstant:=TRUE;
  1178. exit;
  1179. end;
  1180. end;
  1181. end;
  1182. end;
  1183. Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean;
  1184. { search and returns the offset and size of records/objects of the base }
  1185. { with field name setup in field. }
  1186. { returns FALSE if not found. }
  1187. { used when base is a variable or a typed constant name. }
  1188. var
  1189. st : TSymtable;
  1190. harrdef : tarraydef;
  1191. sym : tsym;
  1192. srsymtable : TSymtable;
  1193. i : longint;
  1194. base : string;
  1195. procdef: tprocdef;
  1196. Begin
  1197. GetRecordOffsetSize:=FALSE;
  1198. Offset:=0;
  1199. Size:=0;
  1200. mangledname:='';
  1201. i:=pos('.',s);
  1202. if i=0 then
  1203. i:=255;
  1204. base:=Copy(s,1,i-1);
  1205. delete(s,1,i);
  1206. if base='SELF' then
  1207. st:=current_structdef.symtable
  1208. else
  1209. begin
  1210. asmsearchsym(base,sym,srsymtable);
  1211. st:=nil;
  1212. { we can start with a var,type,typedconst }
  1213. if assigned(sym) then
  1214. case sym.typ of
  1215. staticvarsym,
  1216. localvarsym,
  1217. paravarsym :
  1218. st:=Tabstractvarsym(sym).vardef.GetSymtable(gs_record);
  1219. typesym :
  1220. st:=Ttypesym(sym).typedef.GetSymtable(gs_record);
  1221. end
  1222. else
  1223. s:='';
  1224. end;
  1225. { now walk all recordsymtables }
  1226. while assigned(st) and (s<>'') do
  1227. begin
  1228. { load next field in base }
  1229. i:=pos('.',s);
  1230. if i=0 then
  1231. i:=255;
  1232. base:=Copy(s,1,i-1);
  1233. delete(s,1,i);
  1234. sym:=search_struct_member(tabstractrecorddef(st.defowner),base);
  1235. if not assigned(sym) then
  1236. begin
  1237. GetRecordOffsetSize:=false;
  1238. exit;
  1239. end;
  1240. st:=nil;
  1241. case sym.typ of
  1242. fieldvarsym :
  1243. with Tfieldvarsym(sym) do
  1244. begin
  1245. if not tabstractrecordsymtable(sym.owner).is_packed then
  1246. inc(Offset,fieldoffset)
  1247. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  1248. inc(Offset,fieldoffset div 8)
  1249. else
  1250. Message(asmr_e_packed_element);
  1251. size:=getsize;
  1252. case vardef.typ of
  1253. arraydef :
  1254. begin
  1255. { for arrays try to get the element size, take care of
  1256. multiple indexes }
  1257. harrdef:=tarraydef(vardef);
  1258. while assigned(harrdef.elementdef) and
  1259. (harrdef.elementdef.typ=arraydef) do
  1260. harrdef:=tarraydef(harrdef.elementdef);
  1261. if not is_packed_array(harrdef) then
  1262. size:=harrdef.elesize
  1263. else
  1264. begin
  1265. if (harrdef.elepackedbitsize mod 8) <> 0 then
  1266. Message(asmr_e_packed_element);
  1267. size := (harrdef.elepackedbitsize + 7) div 8;
  1268. end;
  1269. end;
  1270. recorddef :
  1271. st:=trecorddef(vardef).symtable;
  1272. objectdef :
  1273. st:=tobjectdef(vardef).symtable;
  1274. end;
  1275. end;
  1276. procsym:
  1277. begin
  1278. st:=nil;
  1279. if Tprocsym(sym).ProcdefList.Count>1 then
  1280. Message(asmr_w_calling_overload_func);
  1281. procdef:=tprocdef(tprocsym(sym).ProcdefList[0]);
  1282. if (not needvmtofs) then
  1283. begin
  1284. mangledname:=procdef.mangledname;
  1285. end
  1286. else
  1287. begin
  1288. { can only get the vmtoffset of virtual methods }
  1289. if not(po_virtualmethod in procdef.procoptions) or
  1290. is_objectpascal_helper(procdef.struct) then
  1291. Message1(asmr_e_no_vmtoffset_possible,FullTypeName(procdef,nil))
  1292. else
  1293. begin
  1294. { size = sizeof(target_system_pointer) }
  1295. size:=sizeof(pint);
  1296. offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)
  1297. end;
  1298. end;
  1299. { if something comes after the procsym, it's invalid assembler syntax }
  1300. GetRecordOffsetSize:=(s='');
  1301. exit;
  1302. end;
  1303. end;
  1304. end;
  1305. { Support Field.Type as typecasting }
  1306. if (st=nil) and (s<>'') then
  1307. begin
  1308. asmsearchsym(s,sym,srsymtable);
  1309. if assigned(sym) and (sym.typ=typesym) then
  1310. begin
  1311. size:=ttypesym(sym).typedef.size;
  1312. s:=''
  1313. end;
  1314. end;
  1315. GetRecordOffsetSize:=(s='');
  1316. end;
  1317. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  1318. var
  1319. sym : tsym;
  1320. srsymtable : TSymtable;
  1321. hs : string;
  1322. Begin
  1323. hl:=nil;
  1324. SearchLabel:=false;
  1325. { Check for pascal labels, which are case insensetive }
  1326. hs:=upper(s);
  1327. asmsearchsym(hs,sym,srsymtable);
  1328. if sym=nil then
  1329. exit;
  1330. case sym.typ of
  1331. labelsym :
  1332. begin
  1333. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1334. begin
  1335. Tlabelsym(sym).nonlocal:=true;
  1336. if emit then
  1337. exclude(current_procinfo.procdef.procoptions,po_inline);
  1338. end;
  1339. if not(assigned(tlabelsym(sym).asmblocklabel)) then
  1340. if Tlabelsym(sym).nonlocal then
  1341. current_asmdata.getglobaljumplabel(tlabelsym(sym).asmblocklabel)
  1342. else
  1343. current_asmdata.getjumplabel(tlabelsym(sym).asmblocklabel);
  1344. hl:=tlabelsym(sym).asmblocklabel;
  1345. if emit then
  1346. tlabelsym(sym).defined:=true
  1347. else
  1348. tlabelsym(sym).used:=true;
  1349. SearchLabel:=true;
  1350. end;
  1351. end;
  1352. end;
  1353. {*************************************************************************}
  1354. { Instruction Generation Utilities }
  1355. {*************************************************************************}
  1356. Procedure ConcatString(p : TAsmList;s:string);
  1357. {*********************************************************************}
  1358. { PROCEDURE ConcatString(s:string); }
  1359. { Description: This routine adds the character chain pointed to in }
  1360. { s to the instruction linked list. }
  1361. {*********************************************************************}
  1362. Var
  1363. pc: PChar;
  1364. Begin
  1365. getmem(pc,length(s)+1);
  1366. p.concat(Tai_string.Create_pchar(strpcopy(pc,s),length(s)));
  1367. end;
  1368. Procedure ConcatPasString(p : TAsmList;s:string);
  1369. {*********************************************************************}
  1370. { PROCEDURE ConcatPasString(s:string); }
  1371. { Description: This routine adds the character chain pointed to in }
  1372. { s to the instruction linked list, contrary to ConcatString it }
  1373. { uses a pascal style string, so it conserves null characters. }
  1374. {*********************************************************************}
  1375. Begin
  1376. p.concat(Tai_string.Create(s));
  1377. end;
  1378. Procedure ConcatConstant(p: TAsmList; value: aint; constsize:byte);
  1379. {*********************************************************************}
  1380. { PROCEDURE ConcatConstant(value: aint; maxvalue: aint); }
  1381. { Description: This routine adds the value constant to the current }
  1382. { instruction linked list. }
  1383. { maxvalue -> indicates the size of the data to initialize: }
  1384. { $ff -> create a byte node. }
  1385. { $ffff -> create a word node. }
  1386. { $ffffffff -> create a dword node. }
  1387. {*********************************************************************}
  1388. var
  1389. rangelo,rangehi : int64;
  1390. Begin
  1391. case constsize of
  1392. 1 :
  1393. begin
  1394. p.concat(Tai_const.Create_8bit(byte(value)));
  1395. rangelo:=low(shortint);
  1396. rangehi:=high(byte);
  1397. end;
  1398. 2 :
  1399. begin
  1400. p.concat(Tai_const.Create_16bit(word(value)));
  1401. rangelo:=low(smallint);
  1402. rangehi:=high(word);
  1403. end;
  1404. 4 :
  1405. begin
  1406. p.concat(Tai_const.Create_32bit(longint(value)));
  1407. rangelo:=low(longint);
  1408. rangehi:=high(cardinal);
  1409. end;
  1410. 8 :
  1411. begin
  1412. p.concat(Tai_const.Create_64bit(int64(value)));
  1413. rangelo:=0;
  1414. rangehi:=0;
  1415. end;
  1416. else
  1417. internalerror(200405011);
  1418. end;
  1419. { check for out of bounds }
  1420. if (rangelo<>0) and
  1421. ((value>rangehi) or (value<rangelo)) then
  1422. Message(asmr_e_constant_out_of_bounds);
  1423. end;
  1424. Procedure ConcatConstSymbol(p : TAsmList;const sym:string;symtyp:tasmsymtype;l:aint);
  1425. begin
  1426. p.concat(Tai_const.Createname(sym,l));
  1427. end;
  1428. Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
  1429. {***********************************************************************}
  1430. { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
  1431. { Description: This routine adds the value constant to the current }
  1432. { instruction linked list. }
  1433. { real_typ -> indicates the type of the real data to initialize: }
  1434. { s32real -> create a single node. }
  1435. { s64real -> create a double node. }
  1436. { s80real -> create an extended node. }
  1437. { s64bit -> create a comp node. }
  1438. { f32bit -> create a fixed node. (not used normally) }
  1439. {***********************************************************************}
  1440. Begin
  1441. case real_typ of
  1442. s32real : p.concat(Tai_real_32bit.Create(value));
  1443. s64real :
  1444. {$ifdef ARM}
  1445. if is_double_hilo_swapped then
  1446. p.concat(Tai_real_64bit.Create_hiloswapped(value))
  1447. else
  1448. {$endif ARM}
  1449. p.concat(Tai_real_64bit.Create(value));
  1450. s80real : p.concat(Tai_real_80bit.Create(value,s80floattype.size));
  1451. sc80real : p.concat(Tai_real_80bit.Create(value,sc80floattype.size));
  1452. s64comp : p.concat(Tai_comp_64bit.Create(trunc(value)));
  1453. end;
  1454. end;
  1455. Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
  1456. {*********************************************************************}
  1457. { PROCEDURE ConcatLabel }
  1458. { Description: This routine either emits a label or a labeled }
  1459. { instruction to the linked list of instructions. }
  1460. {*********************************************************************}
  1461. begin
  1462. p.concat(Tai_label.Create(l));
  1463. end;
  1464. procedure ConcatAlign(p:TAsmList;l:aint);
  1465. {*********************************************************************}
  1466. { PROCEDURE ConcatPublic }
  1467. { Description: This routine emits an global definition to the }
  1468. { linked list of instructions.(used by AT&T styled asm) }
  1469. {*********************************************************************}
  1470. begin
  1471. p.concat(Tai_align.Create(l));
  1472. end;
  1473. procedure ConcatPublic(p:TAsmList;const s : string);
  1474. {*********************************************************************}
  1475. { PROCEDURE ConcatPublic }
  1476. { Description: This routine emits an global definition to the }
  1477. { linked list of instructions.(used by AT&T styled asm) }
  1478. {*********************************************************************}
  1479. begin
  1480. p.concat(Tai_symbol.Createname_global(s,AT_LABEL,0));
  1481. end;
  1482. procedure ConcatLocal(p:TAsmList;const s : string);
  1483. {*********************************************************************}
  1484. { PROCEDURE ConcatLocal }
  1485. { Description: This routine emits an local definition to the }
  1486. { linked list of instructions. }
  1487. {*********************************************************************}
  1488. begin
  1489. p.concat(Tai_symbol.Createname(s,AT_LABEL,0));
  1490. end;
  1491. end.