cgcpu.pas 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712
  1. {
  2. Copyright (c) 2003 by Florian Klaempfl
  3. Member of the Free Pascal development team
  4. This unit implements the code generator for the ARM
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,symtype,symdef,
  23. cgbase,cgutils,cgobj,
  24. aasmbase,aasmcpu,aasmtai,
  25. parabase,
  26. cpubase,cpuinfo,node,cg64f32,rgcpu;
  27. type
  28. tcgarm = class(tcg)
  29. { true, if the next arithmetic operation should modify the flags }
  30. cgsetflags : boolean;
  31. procedure init_register_allocators;override;
  32. procedure done_register_allocators;override;
  33. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);override;
  34. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
  35. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);override;
  36. procedure a_call_name(list : taasmoutput;const s : string);override;
  37. procedure a_call_reg(list : taasmoutput;reg: tregister); override;
  38. procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
  39. procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  40. procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  41. size: tcgsize; a: aint; src, dst: tregister); override;
  42. procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  43. size: tcgsize; src1, src2, dst: tregister); override;
  44. procedure a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
  45. procedure a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
  46. { move instructions }
  47. procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);override;
  48. procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  49. procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  50. procedure a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  51. { fpu move instructions }
  52. procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
  53. procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
  54. procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
  55. procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
  56. { comparison operations }
  57. procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  58. l : tasmlabel);override;
  59. procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  60. procedure a_jmp_name(list : taasmoutput;const s : string); override;
  61. procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
  62. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  63. procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  64. procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
  65. procedure g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean); override;
  66. procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
  67. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
  68. procedure g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);override;
  69. procedure g_concatcopy_move(list : taasmoutput;const source,dest : treference;len : aint);
  70. procedure g_concatcopy_internal(list : taasmoutput;const source,dest : treference;len : aint;aligned : boolean);
  71. procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override;
  72. procedure g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
  73. procedure g_save_standard_registers(list : taasmoutput);override;
  74. procedure g_restore_standard_registers(list : taasmoutput);override;
  75. procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  76. procedure fixref(list : taasmoutput;var ref : treference);
  77. procedure handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  78. procedure g_intf_wrapper(list: taasmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  79. end;
  80. tcg64farm = class(tcg64f32)
  81. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  82. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  83. procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
  84. procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
  85. procedure a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  86. procedure a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  87. end;
  88. const
  89. OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
  90. C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
  91. function get_fpu_postfix(def : tdef) : toppostfix;
  92. implementation
  93. uses
  94. globals,verbose,systems,cutils,
  95. fmodule,
  96. symconst,symsym,
  97. tgobj,
  98. procinfo,cpupi,
  99. paramgr;
  100. function get_fpu_postfix(def : tdef) : toppostfix;
  101. begin
  102. if def.deftype=floatdef then
  103. begin
  104. case tfloatdef(def).typ of
  105. s32real:
  106. result:=PF_S;
  107. s64real:
  108. result:=PF_D;
  109. s80real:
  110. result:=PF_E;
  111. else
  112. internalerror(200401272);
  113. end;
  114. end
  115. else
  116. internalerror(200401271);
  117. end;
  118. procedure tcgarm.init_register_allocators;
  119. begin
  120. inherited init_register_allocators;
  121. { currently, we save R14 always, so we can use it }
  122. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  123. [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
  124. RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
  125. rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  126. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
  127. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  128. [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
  129. end;
  130. procedure tcgarm.done_register_allocators;
  131. begin
  132. rg[R_INTREGISTER].free;
  133. rg[R_FPUREGISTER].free;
  134. rg[R_MMREGISTER].free;
  135. inherited done_register_allocators;
  136. end;
  137. procedure tcgarm.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);
  138. var
  139. ref: treference;
  140. begin
  141. paraloc.check_simple_location;
  142. case paraloc.location^.loc of
  143. LOC_REGISTER,LOC_CREGISTER:
  144. a_load_const_reg(list,size,a,paraloc.location^.register);
  145. LOC_REFERENCE:
  146. begin
  147. reference_reset(ref);
  148. ref.base:=paraloc.location^.reference.index;
  149. ref.offset:=paraloc.location^.reference.offset;
  150. a_load_const_ref(list,size,a,ref);
  151. end;
  152. else
  153. internalerror(2002081101);
  154. end;
  155. end;
  156. procedure tcgarm.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);
  157. var
  158. tmpref, ref: treference;
  159. location: pcgparalocation;
  160. sizeleft: aint;
  161. begin
  162. location := paraloc.location;
  163. tmpref := r;
  164. sizeleft := paraloc.intsize;
  165. while assigned(location) do
  166. begin
  167. case location^.loc of
  168. LOC_REGISTER,LOC_CREGISTER:
  169. a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  170. LOC_REFERENCE:
  171. begin
  172. reference_reset_base(ref,location^.reference.index,location^.reference.offset);
  173. g_concatcopy(list,tmpref,ref,sizeleft);
  174. if assigned(location^.next) then
  175. internalerror(2005010710);
  176. end;
  177. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  178. case location^.size of
  179. OS_F32, OS_F64:
  180. a_loadfpu_ref_reg(list,location^.size,tmpref,location^.register);
  181. else
  182. internalerror(2002072801);
  183. end;
  184. LOC_VOID:
  185. begin
  186. // nothing to do
  187. end;
  188. else
  189. internalerror(2002081103);
  190. end;
  191. inc(tmpref.offset,tcgsize2size[location^.size]);
  192. dec(sizeleft,tcgsize2size[location^.size]);
  193. location := location^.next;
  194. end;
  195. end;
  196. procedure tcgarm.a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);
  197. var
  198. ref: treference;
  199. tmpreg: tregister;
  200. begin
  201. paraloc.check_simple_location;
  202. case paraloc.location^.loc of
  203. LOC_REGISTER,LOC_CREGISTER:
  204. a_loadaddr_ref_reg(list,r,paraloc.location^.register);
  205. LOC_REFERENCE:
  206. begin
  207. reference_reset(ref);
  208. ref.base := paraloc.location^.reference.index;
  209. ref.offset := paraloc.location^.reference.offset;
  210. tmpreg := getintregister(list,OS_ADDR);
  211. a_loadaddr_ref_reg(list,r,tmpreg);
  212. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  213. end;
  214. else
  215. internalerror(2002080701);
  216. end;
  217. end;
  218. procedure tcgarm.a_call_name(list : taasmoutput;const s : string);
  219. begin
  220. list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
  221. {
  222. the compiler does not properly set this flag anymore in pass 1, and
  223. for now we only need it after pass 2 (I hope) (JM)
  224. if not(pi_do_call in current_procinfo.flags) then
  225. internalerror(2003060703);
  226. }
  227. include(current_procinfo.flags,pi_do_call);
  228. end;
  229. procedure tcgarm.a_call_reg(list : taasmoutput;reg: tregister);
  230. var
  231. r : tregister;
  232. begin
  233. list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
  234. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
  235. {
  236. the compiler does not properly set this flag anymore in pass 1, and
  237. for now we only need it after pass 2 (I hope) (JM)
  238. if not(pi_do_call in current_procinfo.flags) then
  239. internalerror(2003060703);
  240. }
  241. include(current_procinfo.flags,pi_do_call);
  242. end;
  243. procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
  244. begin
  245. a_op_const_reg_reg(list,op,size,a,reg,reg);
  246. end;
  247. procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  248. begin
  249. case op of
  250. OP_NEG:
  251. list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
  252. OP_NOT:
  253. begin
  254. list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
  255. case size of
  256. OS_8 :
  257. a_op_const_reg_reg(list,OP_AND,OS_INT,$ff,dst,dst);
  258. OS_16 :
  259. a_op_const_reg_reg(list,OP_AND,OS_INT,$ffff,dst,dst);
  260. end;
  261. end
  262. else
  263. a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
  264. end;
  265. end;
  266. const
  267. op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
  268. (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
  269. A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
  270. procedure tcgarm.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  271. size: tcgsize; a: aint; src, dst: tregister);
  272. var
  273. ovloc : tlocation;
  274. begin
  275. a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,ovloc);
  276. end;
  277. procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  278. size: tcgsize; src1, src2, dst: tregister);
  279. var
  280. ovloc : tlocation;
  281. begin
  282. a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
  283. end;
  284. procedure tcgarm.a_op_const_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
  285. var
  286. shift : byte;
  287. tmpreg : tregister;
  288. so : tshifterop;
  289. l1 : longint;
  290. begin
  291. ovloc.loc:=LOC_VOID;
  292. if is_shifter_const(-a,shift) then
  293. case op of
  294. OP_ADD:
  295. begin
  296. op:=OP_SUB;
  297. a:=dword(-a);
  298. end;
  299. OP_SUB:
  300. begin
  301. op:=OP_ADD;
  302. a:=dword(-a);
  303. end
  304. end;
  305. if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
  306. case op of
  307. OP_NEG,OP_NOT,
  308. OP_DIV,OP_IDIV:
  309. internalerror(200308281);
  310. OP_SHL:
  311. begin
  312. if a>32 then
  313. internalerror(200308291);
  314. if a<>0 then
  315. begin
  316. shifterop_reset(so);
  317. so.shiftmode:=SM_LSL;
  318. so.shiftimm:=a;
  319. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  320. end
  321. else
  322. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  323. end;
  324. OP_SHR:
  325. begin
  326. if a>32 then
  327. internalerror(200308292);
  328. shifterop_reset(so);
  329. if a<>0 then
  330. begin
  331. so.shiftmode:=SM_LSR;
  332. so.shiftimm:=a;
  333. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  334. end
  335. else
  336. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  337. end;
  338. OP_SAR:
  339. begin
  340. if a>32 then
  341. internalerror(200308291);
  342. if a<>0 then
  343. begin
  344. shifterop_reset(so);
  345. so.shiftmode:=SM_ASR;
  346. so.shiftimm:=a;
  347. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  348. end
  349. else
  350. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  351. end;
  352. else
  353. list.concat(setoppostfix(
  354. taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
  355. ));
  356. if (cgsetflags or setflags) and (size in [OS_8,OS_16,OS_32]) then
  357. begin
  358. ovloc.loc:=LOC_FLAGS;
  359. case op of
  360. OP_ADD:
  361. ovloc.resflags:=F_CS;
  362. OP_SUB:
  363. ovloc.resflags:=F_CC;
  364. end;
  365. end;
  366. end
  367. else
  368. begin
  369. { there could be added some more sophisticated optimizations }
  370. if (op in [OP_MUL,OP_IMUL]) and (a=1) then
  371. a_load_reg_reg(list,size,size,src,dst)
  372. else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
  373. a_load_const_reg(list,size,0,dst)
  374. else if (op in [OP_IMUL]) and (a=-1) then
  375. a_op_reg_reg(list,OP_NEG,size,src,dst)
  376. { we do this here instead in the peephole optimizer because
  377. it saves us a register }
  378. else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) and not(cgsetflags or setflags) then
  379. a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
  380. else
  381. begin
  382. tmpreg:=getintregister(list,size);
  383. a_load_const_reg(list,size,a,tmpreg);
  384. a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
  385. end;
  386. end;
  387. end;
  388. procedure tcgarm.a_op_reg_reg_reg_checkoverflow(list: taasmoutput; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
  389. var
  390. so : tshifterop;
  391. tmpreg,overflowreg : tregister;
  392. asmop : tasmop;
  393. begin
  394. ovloc.loc:=LOC_VOID;
  395. case op of
  396. OP_NEG,OP_NOT,
  397. OP_DIV,OP_IDIV:
  398. internalerror(200308281);
  399. OP_SHL:
  400. begin
  401. shifterop_reset(so);
  402. so.rs:=src1;
  403. so.shiftmode:=SM_LSL;
  404. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  405. end;
  406. OP_SHR:
  407. begin
  408. shifterop_reset(so);
  409. so.rs:=src1;
  410. so.shiftmode:=SM_LSR;
  411. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  412. end;
  413. OP_SAR:
  414. begin
  415. shifterop_reset(so);
  416. so.rs:=src1;
  417. so.shiftmode:=SM_ASR;
  418. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  419. end;
  420. OP_IMUL,
  421. OP_MUL:
  422. begin
  423. if cgsetflags or setflags then
  424. begin
  425. overflowreg:=getintregister(list,size);
  426. if op=OP_IMUL then
  427. asmop:=A_SMULL
  428. else
  429. asmop:=A_UMULL;
  430. { the arm doesn't allow that rd and rm are the same }
  431. if dst=src2 then
  432. begin
  433. if dst<>src1 then
  434. list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src1,src2))
  435. else
  436. begin
  437. tmpreg:=getintregister(list,size);
  438. a_load_reg_reg(list,size,size,src2,dst);
  439. list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,tmpreg,src1));
  440. end;
  441. end
  442. else
  443. list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src2,src1));
  444. if op=OP_IMUL then
  445. begin
  446. shifterop_reset(so);
  447. so.shiftmode:=SM_ASR;
  448. so.shiftimm:=31;
  449. list.concat(taicpu.op_reg_reg_shifterop(A_CMP,overflowreg,dst,so));
  450. end
  451. else
  452. list.concat(taicpu.op_reg_const(A_CMP,overflowreg,0));
  453. ovloc.loc:=LOC_FLAGS;
  454. ovloc.resflags:=F_NE;
  455. end
  456. else
  457. begin
  458. { the arm doesn't allow that rd and rm are the same }
  459. if dst=src2 then
  460. begin
  461. if dst<>src1 then
  462. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
  463. else
  464. begin
  465. tmpreg:=getintregister(list,size);
  466. a_load_reg_reg(list,size,size,src2,dst);
  467. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
  468. end;
  469. end
  470. else
  471. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
  472. end;
  473. end;
  474. else
  475. list.concat(setoppostfix(
  476. taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
  477. ));
  478. end;
  479. end;
  480. procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);
  481. var
  482. imm_shift : byte;
  483. l : tasmlabel;
  484. hr : treference;
  485. begin
  486. if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
  487. internalerror(2002090902);
  488. if is_shifter_const(a,imm_shift) then
  489. list.concat(taicpu.op_reg_const(A_MOV,reg,a))
  490. else if is_shifter_const(not(a),imm_shift) then
  491. list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
  492. else
  493. begin
  494. reference_reset(hr);
  495. objectlibrary.getjumplabel(l);
  496. cg.a_label(current_procinfo.aktlocaldata,l);
  497. hr.symboldata:=current_procinfo.aktlocaldata.last;
  498. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
  499. hr.symbol:=l;
  500. list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
  501. end;
  502. end;
  503. procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  504. var
  505. tmpreg : tregister;
  506. tmpref : treference;
  507. l : tasmlabel;
  508. begin
  509. tmpreg:=NR_NO;
  510. { Be sure to have a base register }
  511. if (ref.base=NR_NO) then
  512. begin
  513. if ref.shiftmode<>SM_None then
  514. internalerror(200308294);
  515. ref.base:=ref.index;
  516. ref.index:=NR_NO;
  517. end;
  518. { absolute symbols can't be handled directly, we've to store the symbol reference
  519. in the text segment and access it pc relative
  520. For now, we assume that references where base or index equals to PC are already
  521. relative, all other references are assumed to be absolute and thus they need
  522. to be handled extra.
  523. A proper solution would be to change refoptions to a set and store the information
  524. if the symbol is absolute or relative there.
  525. }
  526. if (assigned(ref.symbol) and
  527. not(is_pc(ref.base)) and
  528. not(is_pc(ref.index))
  529. ) or
  530. { [#xxx] isn't a valid address operand }
  531. ((ref.base=NR_NO) and (ref.index=NR_NO)) or
  532. (ref.offset<-4095) or
  533. (ref.offset>4095) or
  534. ((oppostfix in [PF_SB,PF_H,PF_SH]) and
  535. ((ref.offset<-255) or
  536. (ref.offset>255)
  537. )
  538. ) or
  539. ((op in [A_LDF,A_STF]) and
  540. ((ref.offset<-1020) or
  541. (ref.offset>1020)
  542. )
  543. ) then
  544. begin
  545. reference_reset(tmpref);
  546. { load symbol }
  547. tmpreg:=getintregister(list,OS_INT);
  548. if assigned(ref.symbol) then
  549. begin
  550. objectlibrary.getjumplabel(l);
  551. cg.a_label(current_procinfo.aktlocaldata,l);
  552. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  553. current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
  554. { load consts entry }
  555. tmpref.symbol:=l;
  556. tmpref.base:=NR_R15;
  557. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  558. end
  559. else
  560. a_load_const_reg(list,OS_ADDR,ref.offset,tmpreg);
  561. if (ref.base<>NR_NO) then
  562. begin
  563. if ref.index<>NR_NO then
  564. begin
  565. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  566. ref.base:=tmpreg;
  567. end
  568. else
  569. begin
  570. ref.index:=tmpreg;
  571. ref.shiftimm:=0;
  572. ref.signindex:=1;
  573. ref.shiftmode:=SM_None;
  574. end;
  575. end
  576. else
  577. ref.base:=tmpreg;
  578. ref.offset:=0;
  579. ref.symbol:=nil;
  580. end;
  581. if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
  582. begin
  583. if tmpreg<>NR_NO then
  584. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
  585. else
  586. begin
  587. tmpreg:=getintregister(list,OS_ADDR);
  588. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
  589. ref.base:=tmpreg;
  590. end;
  591. ref.offset:=0;
  592. end;
  593. { floating point operations have only limited references
  594. we expect here, that a base is already set }
  595. if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
  596. begin
  597. if ref.shiftmode<>SM_none then
  598. internalerror(200309121);
  599. if tmpreg<>NR_NO then
  600. begin
  601. if ref.base=tmpreg then
  602. begin
  603. if ref.signindex<0 then
  604. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
  605. else
  606. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
  607. ref.index:=NR_NO;
  608. end
  609. else
  610. begin
  611. if ref.index<>tmpreg then
  612. internalerror(200403161);
  613. if ref.signindex<0 then
  614. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
  615. else
  616. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  617. ref.base:=tmpreg;
  618. ref.index:=NR_NO;
  619. end;
  620. end
  621. else
  622. begin
  623. tmpreg:=getintregister(list,OS_ADDR);
  624. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  625. ref.base:=tmpreg;
  626. ref.index:=NR_NO;
  627. end;
  628. end;
  629. list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
  630. end;
  631. procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  632. var
  633. oppostfix:toppostfix;
  634. begin
  635. case ToSize of
  636. { signed integer registers }
  637. OS_8,
  638. OS_S8:
  639. oppostfix:=PF_B;
  640. OS_16,
  641. OS_S16:
  642. oppostfix:=PF_H;
  643. OS_32,
  644. OS_S32:
  645. oppostfix:=PF_None;
  646. else
  647. InternalError(200308295);
  648. end;
  649. handle_load_store(list,A_STR,oppostfix,reg,ref);
  650. end;
  651. procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
  652. var
  653. oppostfix:toppostfix;
  654. begin
  655. case FromSize of
  656. { signed integer registers }
  657. OS_8:
  658. oppostfix:=PF_B;
  659. OS_S8:
  660. oppostfix:=PF_SB;
  661. OS_16:
  662. oppostfix:=PF_H;
  663. OS_S16:
  664. oppostfix:=PF_SH;
  665. OS_32,
  666. OS_S32:
  667. oppostfix:=PF_None;
  668. else
  669. InternalError(200308291);
  670. end;
  671. handle_load_store(list,A_LDR,oppostfix,reg,ref);
  672. end;
  673. procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  674. var
  675. instr: taicpu;
  676. so : tshifterop;
  677. begin
  678. shifterop_reset(so);
  679. if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  680. (
  681. (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  682. (tosize <> fromsize) and
  683. not(fromsize in [OS_32,OS_S32])
  684. ) then
  685. begin
  686. case tosize of
  687. OS_8:
  688. list.concat(taicpu.op_reg_reg_const(A_AND,
  689. reg2,reg1,$ff));
  690. OS_S8:
  691. begin
  692. so.shiftmode:=SM_LSL;
  693. so.shiftimm:=24;
  694. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  695. so.shiftmode:=SM_ASR;
  696. so.shiftimm:=24;
  697. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  698. end;
  699. OS_16:
  700. begin
  701. so.shiftmode:=SM_LSL;
  702. so.shiftimm:=16;
  703. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  704. so.shiftmode:=SM_LSR;
  705. so.shiftimm:=16;
  706. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  707. end;
  708. OS_S16:
  709. begin
  710. so.shiftmode:=SM_LSL;
  711. so.shiftimm:=16;
  712. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  713. so.shiftmode:=SM_ASR;
  714. so.shiftimm:=16;
  715. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  716. end;
  717. OS_32,OS_S32:
  718. begin
  719. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  720. list.concat(instr);
  721. add_move_instruction(instr);
  722. end;
  723. else internalerror(2002090901);
  724. end;
  725. end
  726. else
  727. begin
  728. if reg1<>reg2 then
  729. begin
  730. { same size, only a register mov required }
  731. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  732. list.Concat(instr);
  733. { Notify the register allocator that we have written a move instruction so
  734. it can try to eliminate it. }
  735. add_move_instruction(instr);
  736. end;
  737. end;
  738. end;
  739. procedure tcgarm.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);
  740. var
  741. href,href2 : treference;
  742. hloc : pcgparalocation;
  743. begin
  744. href:=ref;
  745. hloc:=paraloc.location;
  746. while assigned(hloc) do
  747. begin
  748. case hloc^.loc of
  749. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  750. a_loadfpu_ref_reg(list,size,ref,hloc^.register);
  751. LOC_REGISTER :
  752. a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
  753. LOC_REFERENCE :
  754. begin
  755. reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset);
  756. a_load_ref_ref(list,hloc^.size,hloc^.size,href,href2);
  757. end;
  758. else
  759. internalerror(200408241);
  760. end;
  761. inc(href.offset,tcgsize2size[hloc^.size]);
  762. hloc:=hloc^.next;
  763. end;
  764. end;
  765. procedure tcgarm.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
  766. begin
  767. list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
  768. end;
  769. procedure tcgarm.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  770. var
  771. oppostfix:toppostfix;
  772. begin
  773. case size of
  774. OS_F32:
  775. oppostfix:=PF_S;
  776. OS_F64:
  777. oppostfix:=PF_D;
  778. OS_F80:
  779. oppostfix:=PF_E;
  780. else
  781. InternalError(200309021);
  782. end;
  783. handle_load_store(list,A_LDF,oppostfix,reg,ref);
  784. end;
  785. procedure tcgarm.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  786. var
  787. oppostfix:toppostfix;
  788. begin
  789. case size of
  790. OS_F32:
  791. oppostfix:=PF_S;
  792. OS_F64:
  793. oppostfix:=PF_D;
  794. OS_F80:
  795. oppostfix:=PF_E;
  796. else
  797. InternalError(200309022);
  798. end;
  799. handle_load_store(list,A_STF,oppostfix,reg,ref);
  800. end;
  801. { comparison operations }
  802. procedure tcgarm.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  803. l : tasmlabel);
  804. var
  805. tmpreg : tregister;
  806. b : byte;
  807. begin
  808. if is_shifter_const(a,b) then
  809. list.concat(taicpu.op_reg_const(A_CMP,reg,a))
  810. { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
  811. and CMP reg,$7fffffff regarding the flags according to the ARM manual }
  812. else if (a<>$7fffffff) and (a<>-1) and is_shifter_const(-a,b) then
  813. list.concat(taicpu.op_reg_const(A_CMN,reg,-a))
  814. else
  815. begin
  816. tmpreg:=getintregister(list,size);
  817. a_load_const_reg(list,size,a,tmpreg);
  818. list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
  819. end;
  820. a_jmp_cond(list,cmp_op,l);
  821. end;
  822. procedure tcgarm.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  823. begin
  824. list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
  825. a_jmp_cond(list,cmp_op,l);
  826. end;
  827. procedure tcgarm.a_jmp_name(list : taasmoutput;const s : string);
  828. begin
  829. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
  830. end;
  831. procedure tcgarm.a_jmp_always(list : taasmoutput;l: tasmlabel);
  832. begin
  833. list.concat(taicpu.op_sym(A_B,l));
  834. end;
  835. procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  836. var
  837. ai : taicpu;
  838. begin
  839. ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
  840. ai.is_jmp:=true;
  841. list.concat(ai);
  842. end;
  843. procedure tcgarm.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
  844. var
  845. ai : taicpu;
  846. begin
  847. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
  848. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond(flags_to_cond(f))));
  849. end;
  850. procedure tcgarm.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
  851. var
  852. ref : treference;
  853. shift : byte;
  854. firstfloatreg,lastfloatreg,
  855. r : byte;
  856. begin
  857. LocalSize:=align(LocalSize,4);
  858. if not(nostackframe) then
  859. begin
  860. firstfloatreg:=RS_NO;
  861. { save floating point registers? }
  862. for r:=RS_F0 to RS_F7 do
  863. if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
  864. begin
  865. if firstfloatreg=RS_NO then
  866. firstfloatreg:=r;
  867. lastfloatreg:=r;
  868. end;
  869. a_reg_alloc(list,NR_STACK_POINTER_REG);
  870. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  871. a_reg_alloc(list,NR_R12);
  872. list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
  873. { save int registers }
  874. reference_reset(ref);
  875. ref.index:=NR_STACK_POINTER_REG;
  876. ref.addressmode:=AM_PREINDEXED;
  877. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,
  878. rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R12,RS_R14,RS_R15]),
  879. PF_FD));
  880. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
  881. { allocate necessary stack size }
  882. { don't use a_op_const_reg_reg here because we don't allow register allocations
  883. in the entry/exit code }
  884. if not(is_shifter_const(localsize,shift)) then
  885. begin
  886. a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
  887. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
  888. a_reg_dealloc(list,NR_R12);
  889. end
  890. else
  891. begin
  892. a_reg_dealloc(list,NR_R12);
  893. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
  894. end;
  895. if firstfloatreg<>RS_NO then
  896. begin
  897. reference_reset(ref);
  898. if not(is_shifter_const(-tarmprocinfo(current_procinfo).floatregstart,shift)) then
  899. begin
  900. a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
  901. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,NR_FRAME_POINTER_REG,NR_R12));
  902. ref.base:=NR_R12;
  903. end
  904. else
  905. begin
  906. ref.base:=NR_FRAME_POINTER_REG;
  907. ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
  908. end;
  909. list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
  910. lastfloatreg-firstfloatreg+1,ref));
  911. end;
  912. end;
  913. end;
  914. procedure tcgarm.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean);
  915. var
  916. ref : treference;
  917. firstfloatreg,lastfloatreg,
  918. r : byte;
  919. shift : byte;
  920. begin
  921. if not(nostackframe) then
  922. begin
  923. { restore floating point register }
  924. firstfloatreg:=RS_NO;
  925. { save floating point registers? }
  926. for r:=RS_F0 to RS_F7 do
  927. if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
  928. begin
  929. if firstfloatreg=RS_NO then
  930. firstfloatreg:=r;
  931. lastfloatreg:=r;
  932. end;
  933. if firstfloatreg<>RS_NO then
  934. begin
  935. reference_reset(ref);
  936. if not(is_shifter_const(-tarmprocinfo(current_procinfo).floatregstart,shift)) then
  937. begin
  938. a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
  939. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,NR_FRAME_POINTER_REG,NR_R12));
  940. ref.base:=NR_R12;
  941. end
  942. else
  943. begin
  944. ref.base:=NR_FRAME_POINTER_REG;
  945. ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
  946. end;
  947. list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
  948. lastfloatreg-firstfloatreg+1,ref));
  949. end;
  950. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  951. list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
  952. else
  953. begin
  954. { restore int registers and return }
  955. reference_reset(ref);
  956. ref.index:=NR_FRAME_POINTER_REG;
  957. list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R13,RS_R15]),PF_EA));
  958. end;
  959. end
  960. else
  961. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
  962. end;
  963. procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  964. var
  965. b : byte;
  966. tmpref : treference;
  967. instr : taicpu;
  968. begin
  969. if ref.addressmode<>AM_OFFSET then
  970. internalerror(200309071);
  971. tmpref:=ref;
  972. { Be sure to have a base register }
  973. if (tmpref.base=NR_NO) then
  974. begin
  975. if tmpref.shiftmode<>SM_None then
  976. internalerror(200308294);
  977. if tmpref.signindex<0 then
  978. internalerror(200312023);
  979. tmpref.base:=tmpref.index;
  980. tmpref.index:=NR_NO;
  981. end;
  982. if assigned(tmpref.symbol) or
  983. not((is_shifter_const(tmpref.offset,b)) or
  984. (is_shifter_const(-tmpref.offset,b))
  985. ) then
  986. fixref(list,tmpref);
  987. { expect a base here if there is an index }
  988. if (tmpref.base=NR_NO) and (tmpref.index<>NR_NO) then
  989. internalerror(200312022);
  990. if tmpref.index<>NR_NO then
  991. begin
  992. if tmpref.shiftmode<>SM_None then
  993. internalerror(200312021);
  994. if tmpref.signindex<0 then
  995. a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
  996. else
  997. a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
  998. if tmpref.offset<>0 then
  999. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
  1000. end
  1001. else
  1002. begin
  1003. if tmpref.offset<>0 then
  1004. begin
  1005. if tmpref.base<>NR_NO then
  1006. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
  1007. else
  1008. a_load_const_reg(list,OS_ADDR,tmpref.offset,r);
  1009. end
  1010. else
  1011. begin
  1012. instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
  1013. list.concat(instr);
  1014. add_move_instruction(instr);
  1015. end;
  1016. end;
  1017. end;
  1018. procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
  1019. var
  1020. tmpreg : tregister;
  1021. tmpref : treference;
  1022. l : tasmlabel;
  1023. begin
  1024. { absolute symbols can't be handled directly, we've to store the symbol reference
  1025. in the text segment and access it pc relative
  1026. For now, we assume that references where base or index equals to PC are already
  1027. relative, all other references are assumed to be absolute and thus they need
  1028. to be handled extra.
  1029. A proper solution would be to change refoptions to a set and store the information
  1030. if the symbol is absolute or relative there.
  1031. }
  1032. { create consts entry }
  1033. reference_reset(tmpref);
  1034. objectlibrary.getjumplabel(l);
  1035. cg.a_label(current_procinfo.aktlocaldata,l);
  1036. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  1037. if assigned(ref.symbol) then
  1038. current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
  1039. else
  1040. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  1041. { load consts entry }
  1042. tmpreg:=getintregister(list,OS_INT);
  1043. tmpref.symbol:=l;
  1044. tmpref.base:=NR_PC;
  1045. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  1046. if (ref.base<>NR_NO) then
  1047. begin
  1048. if ref.index<>NR_NO then
  1049. begin
  1050. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  1051. ref.base:=tmpreg;
  1052. end
  1053. else
  1054. begin
  1055. ref.index:=tmpreg;
  1056. ref.shiftimm:=0;
  1057. ref.signindex:=1;
  1058. ref.shiftmode:=SM_None;
  1059. end;
  1060. end
  1061. else
  1062. ref.base:=tmpreg;
  1063. ref.offset:=0;
  1064. ref.symbol:=nil;
  1065. end;
  1066. procedure tcgarm.g_concatcopy_move(list : taasmoutput;const source,dest : treference;len : aint);
  1067. var
  1068. paraloc1,paraloc2,paraloc3 : TCGPara;
  1069. begin
  1070. paraloc1.init;
  1071. paraloc2.init;
  1072. paraloc3.init;
  1073. paramanager.getintparaloc(pocall_default,1,paraloc1);
  1074. paramanager.getintparaloc(pocall_default,2,paraloc2);
  1075. paramanager.getintparaloc(pocall_default,3,paraloc3);
  1076. paramanager.allocparaloc(list,paraloc3);
  1077. a_param_const(list,OS_INT,len,paraloc3);
  1078. paramanager.allocparaloc(list,paraloc2);
  1079. a_paramaddr_ref(list,dest,paraloc2);
  1080. paramanager.allocparaloc(list,paraloc2);
  1081. a_paramaddr_ref(list,source,paraloc1);
  1082. paramanager.freeparaloc(list,paraloc3);
  1083. paramanager.freeparaloc(list,paraloc2);
  1084. paramanager.freeparaloc(list,paraloc1);
  1085. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1086. alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
  1087. a_call_name(list,'FPC_MOVE');
  1088. dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
  1089. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1090. paraloc3.done;
  1091. paraloc2.done;
  1092. paraloc1.done;
  1093. end;
  1094. procedure tcgarm.g_concatcopy_internal(list : taasmoutput;const source,dest : treference;len : aint;aligned : boolean);
  1095. var
  1096. srcref,dstref:treference;
  1097. srcreg,destreg,countreg,r:tregister;
  1098. helpsize:aword;
  1099. copysize:byte;
  1100. cgsize:Tcgsize;
  1101. procedure genloop(count : aword;size : byte);
  1102. const
  1103. size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
  1104. var
  1105. l : tasmlabel;
  1106. begin
  1107. objectlibrary.getjumplabel(l);
  1108. a_load_const_reg(list,OS_INT,count,countreg);
  1109. cg.a_label(list,l);
  1110. srcref.addressmode:=AM_POSTINDEXED;
  1111. dstref.addressmode:=AM_POSTINDEXED;
  1112. srcref.offset:=size;
  1113. dstref.offset:=size;
  1114. r:=getintregister(list,size2opsize[size]);
  1115. a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
  1116. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
  1117. a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
  1118. list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
  1119. { keep the registers alive }
  1120. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  1121. list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
  1122. list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
  1123. end;
  1124. begin
  1125. if len=0 then
  1126. exit;
  1127. helpsize:=12;
  1128. dstref:=dest;
  1129. srcref:=source;
  1130. if cs_littlesize in aktglobalswitches then
  1131. helpsize:=8;
  1132. if (len<=helpsize) and aligned then
  1133. begin
  1134. copysize:=4;
  1135. cgsize:=OS_32;
  1136. while len<>0 do
  1137. begin
  1138. if len<2 then
  1139. begin
  1140. copysize:=1;
  1141. cgsize:=OS_8;
  1142. end
  1143. else if len<4 then
  1144. begin
  1145. copysize:=2;
  1146. cgsize:=OS_16;
  1147. end;
  1148. dec(len,copysize);
  1149. r:=getintregister(list,cgsize);
  1150. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  1151. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  1152. inc(srcref.offset,copysize);
  1153. inc(dstref.offset,copysize);
  1154. end;
  1155. end
  1156. else
  1157. begin
  1158. destreg:=getintregister(list,OS_ADDR);
  1159. a_loadaddr_ref_reg(list,dest,destreg);
  1160. reference_reset_base(dstref,destreg,0);
  1161. srcreg:=getintregister(list,OS_ADDR);
  1162. a_loadaddr_ref_reg(list,source,srcreg);
  1163. reference_reset_base(srcref,srcreg,0);
  1164. countreg:=getintregister(list,OS_32);
  1165. // if cs_littlesize in aktglobalswitches then
  1166. genloop(len,1);
  1167. {
  1168. else
  1169. begin
  1170. helpsize:=len shr 2;
  1171. len:=len and 3;
  1172. if helpsize>1 then
  1173. begin
  1174. a_load_const_reg(list,OS_INT,helpsize,countreg);
  1175. list.concat(Taicpu.op_none(A_REP,S_NO));
  1176. end;
  1177. if helpsize>0 then
  1178. list.concat(Taicpu.op_none(A_MOVSD,S_NO));
  1179. if len>1 then
  1180. begin
  1181. dec(len,2);
  1182. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  1183. end;
  1184. if len=1 then
  1185. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  1186. end;
  1187. }
  1188. end;
  1189. end;
  1190. procedure tcgarm.g_concatcopy_unaligned(list : taasmoutput;const source,dest : treference;len : aint);
  1191. begin
  1192. g_concatcopy_internal(list,source,dest,len,false);
  1193. end;
  1194. procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);
  1195. begin
  1196. g_concatcopy_internal(list,source,dest,len,true);
  1197. end;
  1198. procedure tcgarm.g_overflowCheck(list : taasmoutput;const l : tlocation;def : tdef);
  1199. var
  1200. ovloc : tlocation;
  1201. begin
  1202. ovloc.loc:=LOC_VOID;
  1203. g_overflowCheck_loc(list,l,def,ovloc);
  1204. end;
  1205. procedure tcgarm.g_overflowCheck_loc(List:TAasmOutput;const Loc:TLocation;def:TDef;ovloc : tlocation);
  1206. var
  1207. hl : tasmlabel;
  1208. ai:TAiCpu;
  1209. hflags : tresflags;
  1210. begin
  1211. if not(cs_check_overflow in aktlocalswitches) then
  1212. exit;
  1213. objectlibrary.getjumplabel(hl);
  1214. case ovloc.loc of
  1215. LOC_VOID:
  1216. begin
  1217. ai:=taicpu.op_sym(A_B,hl);
  1218. ai.is_jmp:=true;
  1219. if not((def.deftype=pointerdef) or
  1220. ((def.deftype=orddef) and
  1221. (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,bool8bit,bool16bit,bool32bit]))) then
  1222. ai.SetCondition(C_VC)
  1223. else
  1224. ai.SetCondition(C_CC);
  1225. list.concat(ai);
  1226. end;
  1227. LOC_FLAGS:
  1228. begin
  1229. hflags:=ovloc.resflags;
  1230. inverse_flags(hflags);
  1231. cg.a_jmp_flags(list,hflags,hl);
  1232. end;
  1233. else
  1234. internalerror(200409281);
  1235. end;
  1236. a_call_name(list,'FPC_OVERFLOW');
  1237. a_label(list,hl);
  1238. end;
  1239. procedure tcgarm.g_save_standard_registers(list : taasmoutput);
  1240. begin
  1241. { this work is done in g_proc_entry }
  1242. end;
  1243. procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
  1244. begin
  1245. { this work is done in g_proc_exit }
  1246. end;
  1247. procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  1248. var
  1249. ai : taicpu;
  1250. begin
  1251. ai:=Taicpu.Op_sym(A_B,l);
  1252. ai.SetCondition(OpCmp2AsmCond[cond]);
  1253. ai.is_jmp:=true;
  1254. list.concat(ai);
  1255. end;
  1256. procedure tcgarm.g_intf_wrapper(list: taasmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);
  1257. procedure loadvmttor12;
  1258. var
  1259. href : treference;
  1260. begin
  1261. reference_reset_base(href,NR_R0,0);
  1262. cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
  1263. end;
  1264. procedure op_onr12methodaddr;
  1265. var
  1266. href : treference;
  1267. begin
  1268. if (procdef.extnumber=$ffff) then
  1269. Internalerror(200006139);
  1270. { call/jmp vmtoffs(%eax) ; method offs }
  1271. reference_reset_base(href,NR_R12,procdef._class.vmtmethodoffset(procdef.extnumber));
  1272. cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
  1273. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
  1274. end;
  1275. var
  1276. lab : tasmsymbol;
  1277. make_global : boolean;
  1278. href : treference;
  1279. begin
  1280. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  1281. Internalerror(200006137);
  1282. if not assigned(procdef._class) or
  1283. (procdef.procoptions*[po_classmethod, po_staticmethod,
  1284. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  1285. Internalerror(200006138);
  1286. if procdef.owner.symtabletype<>objectsymtable then
  1287. Internalerror(200109191);
  1288. make_global:=false;
  1289. if (not current_module.is_unit) or
  1290. (cs_create_smart in aktmoduleswitches) or
  1291. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  1292. make_global:=true;
  1293. if make_global then
  1294. list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
  1295. else
  1296. list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
  1297. { set param1 interface to self }
  1298. g_adjust_self_value(list,procdef,ioffset);
  1299. { case 4 }
  1300. if po_virtualmethod in procdef.procoptions then
  1301. begin
  1302. loadvmttor12;
  1303. op_onr12methodaddr;
  1304. end
  1305. { case 0 }
  1306. else
  1307. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
  1308. list.concat(Tai_symbol_end.Createname(labelname));
  1309. end;
  1310. procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  1311. var
  1312. tmpreg : tregister;
  1313. begin
  1314. case op of
  1315. OP_NEG:
  1316. begin
  1317. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
  1318. list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
  1319. end;
  1320. OP_NOT:
  1321. begin
  1322. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
  1323. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
  1324. end;
  1325. else
  1326. a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
  1327. end;
  1328. end;
  1329. procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  1330. begin
  1331. a_op64_const_reg_reg(list,op,size,value,reg,reg);
  1332. end;
  1333. procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
  1334. var
  1335. ovloc : tlocation;
  1336. begin
  1337. a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc);
  1338. end;
  1339. procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
  1340. var
  1341. ovloc : tlocation;
  1342. begin
  1343. a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc);
  1344. end;
  1345. procedure tcg64farm.a_op64_const_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  1346. var
  1347. tmpreg : tregister;
  1348. b : byte;
  1349. begin
  1350. ovloc.loc:=LOC_VOID;
  1351. case op of
  1352. OP_NEG,
  1353. OP_NOT :
  1354. internalerror(200306017);
  1355. end;
  1356. if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
  1357. begin
  1358. case op of
  1359. OP_ADD:
  1360. begin
  1361. if is_shifter_const(lo(value),b) then
  1362. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1363. else
  1364. begin
  1365. tmpreg:=cg.getintregister(list,OS_32);
  1366. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1367. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1368. end;
  1369. if is_shifter_const(hi(value),b) then
  1370. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)),PF_S))
  1371. else
  1372. begin
  1373. tmpreg:=cg.getintregister(list,OS_32);
  1374. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1375. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
  1376. end;
  1377. end;
  1378. OP_SUB:
  1379. begin
  1380. if is_shifter_const(lo(value),b) then
  1381. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1382. else
  1383. begin
  1384. tmpreg:=cg.getintregister(list,OS_32);
  1385. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1386. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1387. end;
  1388. if is_shifter_const(hi(value),b) then
  1389. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)),PF_S))
  1390. else
  1391. begin
  1392. tmpreg:=cg.getintregister(list,OS_32);
  1393. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1394. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
  1395. end;
  1396. end;
  1397. else
  1398. internalerror(200502131);
  1399. end;
  1400. if size=OS_64 then
  1401. begin
  1402. { the arm has an weired opinion how flags for SUB/ADD are handled }
  1403. ovloc.loc:=LOC_FLAGS;
  1404. case op of
  1405. OP_ADD:
  1406. ovloc.resflags:=F_CS;
  1407. OP_SUB:
  1408. ovloc.resflags:=F_CC;
  1409. end;
  1410. end;
  1411. end
  1412. else
  1413. begin
  1414. case op of
  1415. OP_AND,OP_OR,OP_XOR:
  1416. begin
  1417. cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
  1418. cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
  1419. end;
  1420. OP_ADD:
  1421. begin
  1422. if is_shifter_const(lo(value),b) then
  1423. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1424. else
  1425. begin
  1426. tmpreg:=cg.getintregister(list,OS_32);
  1427. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1428. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1429. end;
  1430. if is_shifter_const(hi(value),b) then
  1431. list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
  1432. else
  1433. begin
  1434. tmpreg:=cg.getintregister(list,OS_32);
  1435. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1436. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
  1437. end;
  1438. end;
  1439. OP_SUB:
  1440. begin
  1441. if is_shifter_const(lo(value),b) then
  1442. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1443. else
  1444. begin
  1445. tmpreg:=cg.getintregister(list,OS_32);
  1446. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1447. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1448. end;
  1449. if is_shifter_const(hi(value),b) then
  1450. list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
  1451. else
  1452. begin
  1453. tmpreg:=cg.getintregister(list,OS_32);
  1454. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1455. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
  1456. end;
  1457. end;
  1458. else
  1459. internalerror(2003083101);
  1460. end;
  1461. end;
  1462. end;
  1463. procedure tcg64farm.a_op64_reg_reg_reg_checkoverflow(list: taasmoutput;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  1464. var
  1465. op1,op2:TAsmOp;
  1466. begin
  1467. ovloc.loc:=LOC_VOID;
  1468. case op of
  1469. OP_NEG,
  1470. OP_NOT :
  1471. internalerror(200306017);
  1472. end;
  1473. if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
  1474. begin
  1475. case op of
  1476. OP_ADD:
  1477. begin
  1478. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1479. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi),PF_S));
  1480. end;
  1481. OP_SUB:
  1482. begin
  1483. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1484. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi),PF_S));
  1485. end;
  1486. else
  1487. internalerror(2003083101);
  1488. end;
  1489. if size=OS_64 then
  1490. begin
  1491. { the arm has an weired opinion how flags for SUB/ADD are handled }
  1492. ovloc.loc:=LOC_FLAGS;
  1493. case op of
  1494. OP_ADD:
  1495. ovloc.resflags:=F_CC;
  1496. OP_SUB:
  1497. ovloc.resflags:=F_CS;
  1498. end;
  1499. end;
  1500. end
  1501. else
  1502. begin
  1503. case op of
  1504. OP_AND,OP_OR,OP_XOR:
  1505. begin
  1506. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
  1507. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
  1508. end;
  1509. OP_ADD:
  1510. begin
  1511. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1512. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
  1513. end;
  1514. OP_SUB:
  1515. begin
  1516. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1517. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
  1518. end;
  1519. else
  1520. internalerror(2003083101);
  1521. end;
  1522. end;
  1523. end;
  1524. begin
  1525. cg:=tcgarm.create;
  1526. cg64:=tcg64farm.create;
  1527. end.