rautils.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640
  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 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. 0,1:
  932. ;
  933. 2 : begin
  934. { 0,1 -> 1,0 }
  935. p:=Operands[1];
  936. Operands[1]:=Operands[2];
  937. Operands[2]:=p;
  938. end;
  939. {$ifndef MAX_OPER_2}
  940. 3 : begin
  941. { 0,1,2 -> 2,1,0 }
  942. p:=Operands[1];
  943. Operands[1]:=Operands[3];
  944. Operands[3]:=p;
  945. end;
  946. {$ifndef MAX_OPER_3}
  947. 4 : begin
  948. { 0,1,2,3 -> 3,2,1,0 }
  949. p:=Operands[1];
  950. Operands[1]:=Operands[4];
  951. Operands[4]:=p;
  952. p:=Operands[2];
  953. Operands[2]:=Operands[3];
  954. Operands[3]:=p;
  955. end;
  956. {$endif}
  957. {$endif}
  958. else
  959. internalerror(201108142);
  960. end;
  961. end;
  962. function TInstruction.ConcatInstruction(p:TAsmList) : tai;
  963. var
  964. ai : taicpu;
  965. i : longint;
  966. begin
  967. for i:=1 to Ops do
  968. operands[i].CheckOperand;
  969. ai:=taicpu.op_none(opcode);
  970. ai.Ops:=Ops;
  971. ai.Allocate_oper(Ops);
  972. for i:=1 to Ops do
  973. with operands[i].opr do
  974. begin
  975. case typ of
  976. OPR_CONSTANT :
  977. ai.loadconst(i-1,val);
  978. OPR_REGISTER:
  979. ai.loadreg(i-1,reg);
  980. OPR_SYMBOL:
  981. ai.loadsymbol(i-1,symbol,symofs);
  982. OPR_LOCAL :
  983. ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
  984. localscale,localgetoffset,localforceref);
  985. OPR_REFERENCE:
  986. ai.loadref(i-1,ref);
  987. {$ifdef ARM}
  988. OPR_REGSET:
  989. ai.loadregset(i-1,regtype,subreg,regset);
  990. OPR_SHIFTEROP:
  991. ai.loadshifterop(i-1,shifterop);
  992. OPR_COND:
  993. ai.loadconditioncode(i-1,cc);
  994. OPR_MODEFLAGS:
  995. ai.loadmodeflags(i-1,flags);
  996. {$endif ARM}
  997. { ignore wrong operand }
  998. OPR_NONE:
  999. ;
  1000. else
  1001. internalerror(200501051);
  1002. end;
  1003. end;
  1004. ai.SetCondition(condition);
  1005. { Concat the opcode or give an error }
  1006. if assigned(ai) then
  1007. p.concat(ai)
  1008. else
  1009. Message(asmr_e_invalid_opcode_and_operand);
  1010. result:=ai;
  1011. end;
  1012. {***************************************************************************
  1013. TLocalLabel
  1014. ***************************************************************************}
  1015. constructor TLocalLabel.create(AList:TFPHashObjectList;const n:string);
  1016. begin
  1017. inherited Create(AList,n);
  1018. lab:=nil;
  1019. emitted:=false;
  1020. end;
  1021. function TLocalLabel.Gettasmlabel:tasmlabel;
  1022. begin
  1023. if not assigned(lab) then
  1024. begin
  1025. current_asmdata.getjumplabel(lab);
  1026. { this label is forced to be used so it's always written }
  1027. lab.increfs;
  1028. end;
  1029. Gettasmlabel:=lab;
  1030. end;
  1031. {***************************************************************************
  1032. TLocalLabelList
  1033. ***************************************************************************}
  1034. procedure TLocalLabelList.CheckEmitted;
  1035. var
  1036. i : longint;
  1037. lab : TLocalLabel;
  1038. begin
  1039. for i:=0 to LocalLabelList.Count-1 do
  1040. begin
  1041. lab:=TLocalLabel(LocalLabelList[i]);
  1042. if not lab.emitted then
  1043. Message1(asmr_e_unknown_label_identifier,lab.name);
  1044. end;
  1045. end;
  1046. function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
  1047. var
  1048. lab : TLocalLabel;
  1049. Begin
  1050. CreateLocalLabel:=true;
  1051. { Check if it already is defined }
  1052. lab:=TLocalLabel(LocalLabellist.Find(s));
  1053. if not assigned(lab) then
  1054. lab:=TLocalLabel.Create(LocalLabellist,s);
  1055. { set emitted flag and check for dup syms }
  1056. if emit then
  1057. begin
  1058. if lab.Emitted then
  1059. begin
  1060. Message1(asmr_e_dup_local_sym,lab.Name);
  1061. CreateLocalLabel:=false;
  1062. end;
  1063. lab.Emitted:=true;
  1064. end;
  1065. hl:=lab.Gettasmlabel;
  1066. end;
  1067. {****************************************************************************
  1068. Symbol table helper routines
  1069. ****************************************************************************}
  1070. procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:TSymtable);
  1071. var
  1072. i : integer;
  1073. begin
  1074. i:=pos('.',s);
  1075. { allow unit.identifier }
  1076. if i>0 then
  1077. begin
  1078. searchsym(Copy(s,1,i-1),srsym,srsymtable);
  1079. if assigned(srsym) then
  1080. begin
  1081. if (srsym.typ=unitsym) and
  1082. (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
  1083. srsym.owner.iscurrentunit then
  1084. searchsym_in_module(tunitsym(srsym).module,Copy(s,i+1,255),srsym,srsymtable)
  1085. else
  1086. begin
  1087. srsym:=nil;
  1088. srsymtable:=nil;
  1089. end;
  1090. end;
  1091. end
  1092. else
  1093. searchsym(s,srsym,srsymtable);
  1094. end;
  1095. Function SearchType(const hs:string;var size:aint): Boolean;
  1096. var
  1097. srsym : tsym;
  1098. srsymtable : TSymtable;
  1099. begin
  1100. result:=false;
  1101. size:=0;
  1102. asmsearchsym(hs,srsym,srsymtable);
  1103. if assigned(srsym) and
  1104. (srsym.typ=typesym) then
  1105. begin
  1106. size:=ttypesym(srsym).typedef.size;
  1107. result:=true;
  1108. end;
  1109. end;
  1110. Function SearchRecordType(const s:string): boolean;
  1111. var
  1112. srsym : tsym;
  1113. srsymtable : TSymtable;
  1114. Begin
  1115. SearchRecordType:=false;
  1116. { Check the constants in symtable }
  1117. asmsearchsym(s,srsym,srsymtable);
  1118. if srsym <> nil then
  1119. Begin
  1120. case srsym.typ of
  1121. typesym :
  1122. begin
  1123. if ttypesym(srsym).typedef.typ in [recorddef,objectdef] then
  1124. begin
  1125. SearchRecordType:=true;
  1126. exit;
  1127. end;
  1128. end;
  1129. fieldvarsym :
  1130. begin
  1131. if (tfieldvarsym(srsym).vardef.typ in [recorddef,objectdef]) then
  1132. begin
  1133. SearchRecordType:=true;
  1134. exit;
  1135. end;
  1136. end;
  1137. end;
  1138. end;
  1139. end;
  1140. Function SearchIConstant(const s:string; var l:aint): boolean;
  1141. {**********************************************************************}
  1142. { Description: Searches for a CONSTANT of name s in either the local }
  1143. { symbol list, then in the global symbol list, and returns the value }
  1144. { of that constant in l. Returns TRUE if successfull, if not found, }
  1145. { or if the constant is not of correct type, then returns FALSE }
  1146. { Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
  1147. { respectively. }
  1148. {**********************************************************************}
  1149. var
  1150. srsym : tsym;
  1151. srsymtable : TSymtable;
  1152. Begin
  1153. SearchIConstant:=false;
  1154. { check for TRUE or FALSE reserved words first }
  1155. if s = 'TRUE' then
  1156. Begin
  1157. SearchIConstant:=TRUE;
  1158. l:=1;
  1159. exit;
  1160. end;
  1161. if s = 'FALSE' then
  1162. Begin
  1163. SearchIConstant:=TRUE;
  1164. l:=0;
  1165. exit;
  1166. end;
  1167. { Check the constants in symtable }
  1168. asmsearchsym(s,srsym,srsymtable);
  1169. if srsym <> nil then
  1170. Begin
  1171. case srsym.typ of
  1172. constsym :
  1173. begin
  1174. if tconstsym(srsym).consttyp=constord then
  1175. Begin
  1176. l:=tconstsym(srsym).value.valueord.svalue;
  1177. SearchIConstant:=TRUE;
  1178. exit;
  1179. end;
  1180. end;
  1181. enumsym:
  1182. Begin
  1183. l:=tenumsym(srsym).value;
  1184. SearchIConstant:=TRUE;
  1185. exit;
  1186. end;
  1187. end;
  1188. end;
  1189. end;
  1190. Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean;
  1191. { search and returns the offset and size of records/objects of the base }
  1192. { with field name setup in field. }
  1193. { returns FALSE if not found. }
  1194. { used when base is a variable or a typed constant name. }
  1195. var
  1196. st : TSymtable;
  1197. harrdef : tarraydef;
  1198. sym : tsym;
  1199. srsymtable : TSymtable;
  1200. i : longint;
  1201. base : string;
  1202. procdef: tprocdef;
  1203. Begin
  1204. GetRecordOffsetSize:=FALSE;
  1205. Offset:=0;
  1206. Size:=0;
  1207. mangledname:='';
  1208. i:=pos('.',s);
  1209. if i=0 then
  1210. i:=255;
  1211. base:=Copy(s,1,i-1);
  1212. delete(s,1,i);
  1213. if base='SELF' then
  1214. st:=current_structdef.symtable
  1215. else
  1216. begin
  1217. asmsearchsym(base,sym,srsymtable);
  1218. st:=nil;
  1219. { we can start with a var,type,typedconst }
  1220. if assigned(sym) then
  1221. case sym.typ of
  1222. staticvarsym,
  1223. localvarsym,
  1224. paravarsym :
  1225. st:=Tabstractvarsym(sym).vardef.GetSymtable(gs_record);
  1226. typesym :
  1227. st:=Ttypesym(sym).typedef.GetSymtable(gs_record);
  1228. end
  1229. else
  1230. s:='';
  1231. end;
  1232. { now walk all recordsymtables }
  1233. while assigned(st) and (s<>'') do
  1234. begin
  1235. { load next field in base }
  1236. i:=pos('.',s);
  1237. if i=0 then
  1238. i:=255;
  1239. base:=Copy(s,1,i-1);
  1240. delete(s,1,i);
  1241. sym:=search_struct_member(tabstractrecorddef(st.defowner),base);
  1242. if not assigned(sym) then
  1243. begin
  1244. GetRecordOffsetSize:=false;
  1245. exit;
  1246. end;
  1247. st:=nil;
  1248. case sym.typ of
  1249. fieldvarsym :
  1250. with Tfieldvarsym(sym) do
  1251. begin
  1252. if not tabstractrecordsymtable(sym.owner).is_packed then
  1253. inc(Offset,fieldoffset)
  1254. else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
  1255. inc(Offset,fieldoffset div 8)
  1256. else
  1257. Message(asmr_e_packed_element);
  1258. size:=getsize;
  1259. case vardef.typ of
  1260. arraydef :
  1261. begin
  1262. { for arrays try to get the element size, take care of
  1263. multiple indexes }
  1264. harrdef:=tarraydef(vardef);
  1265. while assigned(harrdef.elementdef) and
  1266. (harrdef.elementdef.typ=arraydef) do
  1267. harrdef:=tarraydef(harrdef.elementdef);
  1268. if not is_packed_array(harrdef) then
  1269. size:=harrdef.elesize
  1270. else
  1271. begin
  1272. if (harrdef.elepackedbitsize mod 8) <> 0 then
  1273. Message(asmr_e_packed_element);
  1274. size := (harrdef.elepackedbitsize + 7) div 8;
  1275. end;
  1276. end;
  1277. recorddef :
  1278. st:=trecorddef(vardef).symtable;
  1279. objectdef :
  1280. st:=tobjectdef(vardef).symtable;
  1281. end;
  1282. end;
  1283. procsym:
  1284. begin
  1285. st:=nil;
  1286. if Tprocsym(sym).ProcdefList.Count>1 then
  1287. Message(asmr_w_calling_overload_func);
  1288. procdef:=tprocdef(tprocsym(sym).ProcdefList[0]);
  1289. if (not needvmtofs) then
  1290. begin
  1291. mangledname:=procdef.mangledname;
  1292. end
  1293. else
  1294. begin
  1295. { can only get the vmtoffset of virtual methods }
  1296. if not(po_virtualmethod in procdef.procoptions) or
  1297. is_objectpascal_helper(procdef.struct) then
  1298. Message1(asmr_e_no_vmtoffset_possible,FullTypeName(procdef,nil))
  1299. else
  1300. begin
  1301. { size = sizeof(target_system_pointer) }
  1302. size:=sizeof(pint);
  1303. offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)
  1304. end;
  1305. end;
  1306. { if something comes after the procsym, it's invalid assembler syntax }
  1307. GetRecordOffsetSize:=(s='');
  1308. exit;
  1309. end;
  1310. end;
  1311. end;
  1312. { Support Field.Type as typecasting }
  1313. if (st=nil) and (s<>'') then
  1314. begin
  1315. asmsearchsym(s,sym,srsymtable);
  1316. if assigned(sym) and (sym.typ=typesym) then
  1317. begin
  1318. size:=ttypesym(sym).typedef.size;
  1319. s:=''
  1320. end;
  1321. end;
  1322. GetRecordOffsetSize:=(s='');
  1323. end;
  1324. Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
  1325. var
  1326. sym : tsym;
  1327. srsymtable : TSymtable;
  1328. hs : string;
  1329. Begin
  1330. hl:=nil;
  1331. SearchLabel:=false;
  1332. { Check for pascal labels, which are case insensetive }
  1333. hs:=upper(s);
  1334. asmsearchsym(hs,sym,srsymtable);
  1335. if sym=nil then
  1336. exit;
  1337. case sym.typ of
  1338. labelsym :
  1339. begin
  1340. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1341. begin
  1342. Tlabelsym(sym).nonlocal:=true;
  1343. if emit then
  1344. exclude(current_procinfo.procdef.procoptions,po_inline);
  1345. end;
  1346. if not(assigned(tlabelsym(sym).asmblocklabel)) then
  1347. if Tlabelsym(sym).nonlocal then
  1348. current_asmdata.getglobaljumplabel(tlabelsym(sym).asmblocklabel)
  1349. else
  1350. current_asmdata.getjumplabel(tlabelsym(sym).asmblocklabel);
  1351. hl:=tlabelsym(sym).asmblocklabel;
  1352. if emit then
  1353. tlabelsym(sym).defined:=true
  1354. else
  1355. tlabelsym(sym).used:=true;
  1356. SearchLabel:=true;
  1357. end;
  1358. end;
  1359. end;
  1360. {*************************************************************************}
  1361. { Instruction Generation Utilities }
  1362. {*************************************************************************}
  1363. Procedure ConcatString(p : TAsmList;s:string);
  1364. {*********************************************************************}
  1365. { PROCEDURE ConcatString(s:string); }
  1366. { Description: This routine adds the character chain pointed to in }
  1367. { s to the instruction linked list. }
  1368. {*********************************************************************}
  1369. Var
  1370. pc: PChar;
  1371. Begin
  1372. getmem(pc,length(s)+1);
  1373. p.concat(Tai_string.Create_pchar(strpcopy(pc,s),length(s)));
  1374. end;
  1375. Procedure ConcatPasString(p : TAsmList;s:string);
  1376. {*********************************************************************}
  1377. { PROCEDURE ConcatPasString(s:string); }
  1378. { Description: This routine adds the character chain pointed to in }
  1379. { s to the instruction linked list, contrary to ConcatString it }
  1380. { uses a pascal style string, so it conserves null characters. }
  1381. {*********************************************************************}
  1382. Begin
  1383. p.concat(Tai_string.Create(s));
  1384. end;
  1385. Procedure ConcatConstant(p: TAsmList; value: aint; constsize:byte);
  1386. {*********************************************************************}
  1387. { PROCEDURE ConcatConstant(value: aint; maxvalue: aint); }
  1388. { Description: This routine adds the value constant to the current }
  1389. { instruction linked list. }
  1390. { maxvalue -> indicates the size of the data to initialize: }
  1391. { $ff -> create a byte node. }
  1392. { $ffff -> create a word node. }
  1393. { $ffffffff -> create a dword node. }
  1394. {*********************************************************************}
  1395. var
  1396. rangelo,rangehi : int64;
  1397. Begin
  1398. case constsize of
  1399. 1 :
  1400. begin
  1401. p.concat(Tai_const.Create_8bit(byte(value)));
  1402. rangelo:=low(shortint);
  1403. rangehi:=high(byte);
  1404. end;
  1405. 2 :
  1406. begin
  1407. p.concat(Tai_const.Create_16bit(word(value)));
  1408. rangelo:=low(smallint);
  1409. rangehi:=high(word);
  1410. end;
  1411. 4 :
  1412. begin
  1413. p.concat(Tai_const.Create_32bit(longint(value)));
  1414. rangelo:=low(longint);
  1415. rangehi:=high(cardinal);
  1416. end;
  1417. 8 :
  1418. begin
  1419. p.concat(Tai_const.Create_64bit(int64(value)));
  1420. rangelo:=0;
  1421. rangehi:=0;
  1422. end;
  1423. else
  1424. internalerror(200405011);
  1425. end;
  1426. { check for out of bounds }
  1427. if (rangelo<>0) and
  1428. ((value>rangehi) or (value<rangelo)) then
  1429. Message(asmr_e_constant_out_of_bounds);
  1430. end;
  1431. Procedure ConcatConstSymbol(p : TAsmList;const sym:string;symtyp:tasmsymtype;l:aint);
  1432. begin
  1433. p.concat(Tai_const.Createname(sym,l));
  1434. end;
  1435. Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
  1436. {***********************************************************************}
  1437. { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
  1438. { Description: This routine adds the value constant to the current }
  1439. { instruction linked list. }
  1440. { real_typ -> indicates the type of the real data to initialize: }
  1441. { s32real -> create a single node. }
  1442. { s64real -> create a double node. }
  1443. { s80real -> create an extended node. }
  1444. { s64bit -> create a comp node. }
  1445. { f32bit -> create a fixed node. (not used normally) }
  1446. {***********************************************************************}
  1447. Begin
  1448. case real_typ of
  1449. s32real : p.concat(Tai_real_32bit.Create(value));
  1450. s64real :
  1451. {$ifdef ARM}
  1452. if is_double_hilo_swapped then
  1453. p.concat(Tai_real_64bit.Create_hiloswapped(value))
  1454. else
  1455. {$endif ARM}
  1456. p.concat(Tai_real_64bit.Create(value));
  1457. s80real : p.concat(Tai_real_80bit.Create(value,s80floattype.size));
  1458. sc80real : p.concat(Tai_real_80bit.Create(value,sc80floattype.size));
  1459. s64comp : p.concat(Tai_comp_64bit.Create(trunc(value)));
  1460. end;
  1461. end;
  1462. Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
  1463. {*********************************************************************}
  1464. { PROCEDURE ConcatLabel }
  1465. { Description: This routine either emits a label or a labeled }
  1466. { instruction to the linked list of instructions. }
  1467. {*********************************************************************}
  1468. begin
  1469. p.concat(Tai_label.Create(l));
  1470. end;
  1471. procedure ConcatAlign(p:TAsmList;l:aint);
  1472. {*********************************************************************}
  1473. { PROCEDURE ConcatPublic }
  1474. { Description: This routine emits an global definition to the }
  1475. { linked list of instructions.(used by AT&T styled asm) }
  1476. {*********************************************************************}
  1477. begin
  1478. p.concat(Tai_align.Create(l));
  1479. end;
  1480. procedure ConcatPublic(p:TAsmList;const s : string);
  1481. {*********************************************************************}
  1482. { PROCEDURE ConcatPublic }
  1483. { Description: This routine emits an global definition to the }
  1484. { linked list of instructions.(used by AT&T styled asm) }
  1485. {*********************************************************************}
  1486. begin
  1487. p.concat(Tai_symbol.Createname_global(s,AT_LABEL,0));
  1488. end;
  1489. procedure ConcatLocal(p:TAsmList;const s : string);
  1490. {*********************************************************************}
  1491. { PROCEDURE ConcatLocal }
  1492. { Description: This routine emits an local definition to the }
  1493. { linked list of instructions. }
  1494. {*********************************************************************}
  1495. begin
  1496. p.concat(Tai_symbol.Createname(s,AT_LABEL,0));
  1497. end;
  1498. end.