cgcpu.pas 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340
  1. {
  2. $Id$
  3. Copyright (c) 2003 by Florian Klaempfl
  4. Member of the Free Pascal development team
  5. This unit implements the code generator for the ARM
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit cgcpu;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. globtype,symtype,
  24. cgbase,cgutils,cgobj,
  25. aasmbase,aasmcpu,aasmtai,
  26. parabase,
  27. cpubase,cpuinfo,node,cg64f32,rgcpu;
  28. type
  29. tcgarm = class(tcg)
  30. { true, if the next arithmetic operation should modify the flags }
  31. setflags : boolean;
  32. procedure init_register_allocators;override;
  33. procedure done_register_allocators;override;
  34. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);override;
  35. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
  36. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);override;
  37. procedure a_call_name(list : taasmoutput;const s : string);override;
  38. procedure a_call_reg(list : taasmoutput;reg: tregister); override;
  39. procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
  40. procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  41. procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  42. size: tcgsize; a: aint; src, dst: tregister); override;
  43. procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  44. size: tcgsize; src1, src2, dst: tregister); override;
  45. { move instructions }
  46. procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);override;
  47. procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  48. procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  49. procedure a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  50. { fpu move instructions }
  51. procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
  52. procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
  53. procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
  54. { comparison operations }
  55. procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  56. l : tasmlabel);override;
  57. procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  58. procedure a_jmp_name(list : taasmoutput;const s : string); override;
  59. procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
  60. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  61. procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  62. procedure g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);override;
  63. procedure g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean); override;
  64. procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
  65. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);override;
  66. procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override;
  67. procedure g_save_standard_registers(list : taasmoutput);override;
  68. procedure g_restore_standard_registers(list : taasmoutput);override;
  69. procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  70. procedure fixref(list : taasmoutput;var ref : treference);
  71. procedure handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  72. end;
  73. tcg64farm = class(tcg64f32)
  74. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
  75. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);override;
  76. procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : int64;regsrc,regdst : tregister64);override;
  77. procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);override;
  78. end;
  79. const
  80. OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
  81. C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
  82. function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
  83. function get_fpu_postfix(def : tdef) : toppostfix;
  84. implementation
  85. uses
  86. globals,verbose,systems,cutils,
  87. symconst,symdef,symsym,
  88. tgobj,
  89. procinfo,cpupi,
  90. paramgr;
  91. function get_fpu_postfix(def : tdef) : toppostfix;
  92. begin
  93. if def.deftype=floatdef then
  94. begin
  95. case tfloatdef(def).typ of
  96. s32real:
  97. result:=PF_S;
  98. s64real:
  99. result:=PF_D;
  100. s80real:
  101. result:=PF_E;
  102. else
  103. internalerror(200401272);
  104. end;
  105. end
  106. else
  107. internalerror(200401271);
  108. end;
  109. procedure tcgarm.init_register_allocators;
  110. begin
  111. inherited init_register_allocators;
  112. { currently, we save R14 always, so we can use it }
  113. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  114. [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
  115. RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
  116. rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  117. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
  118. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  119. [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
  120. end;
  121. procedure tcgarm.done_register_allocators;
  122. begin
  123. rg[R_INTREGISTER].free;
  124. rg[R_FPUREGISTER].free;
  125. rg[R_MMREGISTER].free;
  126. inherited done_register_allocators;
  127. end;
  128. procedure tcgarm.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);
  129. var
  130. ref: treference;
  131. begin
  132. paraloc.check_simple_location;
  133. case paraloc.location^.loc of
  134. LOC_REGISTER,LOC_CREGISTER:
  135. a_load_const_reg(list,size,a,paraloc.location^.register);
  136. LOC_REFERENCE:
  137. begin
  138. reference_reset(ref);
  139. ref.base:=paraloc.location^.reference.index;
  140. ref.offset:=paraloc.location^.reference.offset;
  141. a_load_const_ref(list,size,a,ref);
  142. end;
  143. else
  144. internalerror(2002081101);
  145. end;
  146. end;
  147. procedure tcgarm.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);
  148. var
  149. ref: treference;
  150. tmpreg: tregister;
  151. begin
  152. paraloc.check_simple_location;
  153. case paraloc.location^.loc of
  154. LOC_REGISTER,LOC_CREGISTER:
  155. a_load_ref_reg(list,size,size,r,paraloc.location^.register);
  156. LOC_REFERENCE:
  157. begin
  158. reference_reset(ref);
  159. ref.base:=paraloc.location^.reference.index;
  160. ref.offset:=paraloc.location^.reference.offset;
  161. tmpreg := getintregister(list,size);
  162. a_load_ref_reg(list,size,size,r,tmpreg);
  163. a_load_reg_ref(list,size,size,tmpreg,ref);
  164. end;
  165. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  166. case size of
  167. OS_F32, OS_F64:
  168. a_loadfpu_ref_reg(list,size,r,paraloc.location^.register);
  169. else
  170. internalerror(2002072801);
  171. end;
  172. else
  173. internalerror(2002081103);
  174. end;
  175. end;
  176. procedure tcgarm.a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);
  177. var
  178. ref: treference;
  179. tmpreg: tregister;
  180. begin
  181. paraloc.check_simple_location;
  182. case paraloc.location^.loc of
  183. LOC_REGISTER,LOC_CREGISTER:
  184. a_loadaddr_ref_reg(list,r,paraloc.location^.register);
  185. LOC_REFERENCE:
  186. begin
  187. reference_reset(ref);
  188. ref.base := paraloc.location^.reference.index;
  189. ref.offset := paraloc.location^.reference.offset;
  190. tmpreg := getintregister(list,OS_ADDR);
  191. a_loadaddr_ref_reg(list,r,tmpreg);
  192. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  193. end;
  194. else
  195. internalerror(2002080701);
  196. end;
  197. end;
  198. procedure tcgarm.a_call_name(list : taasmoutput;const s : string);
  199. begin
  200. list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
  201. {
  202. the compiler does not properly set this flag anymore in pass 1, and
  203. for now we only need it after pass 2 (I hope) (JM)
  204. if not(pi_do_call in current_procinfo.flags) then
  205. internalerror(2003060703);
  206. }
  207. include(current_procinfo.flags,pi_do_call);
  208. end;
  209. procedure tcgarm.a_call_reg(list : taasmoutput;reg: tregister);
  210. var
  211. r : tregister;
  212. begin
  213. list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
  214. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
  215. {
  216. the compiler does not properly set this flag anymore in pass 1, and
  217. for now we only need it after pass 2 (I hope) (JM)
  218. if not(pi_do_call in current_procinfo.flags) then
  219. internalerror(2003060703);
  220. }
  221. include(current_procinfo.flags,pi_do_call);
  222. end;
  223. procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
  224. begin
  225. a_op_const_reg_reg(list,op,size,a,reg,reg);
  226. end;
  227. procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  228. begin
  229. case op of
  230. OP_NEG:
  231. list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
  232. OP_NOT:
  233. list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
  234. else
  235. a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
  236. end;
  237. end;
  238. const
  239. op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
  240. (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
  241. A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
  242. procedure tcgarm.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  243. size: tcgsize; a: aint; src, dst: tregister);
  244. var
  245. shift : byte;
  246. tmpreg : tregister;
  247. so : tshifterop;
  248. l1 : longint;
  249. begin
  250. if is_shifter_const(-a,shift) then
  251. case op of
  252. OP_ADD:
  253. begin
  254. op:=OP_SUB;
  255. a:=dword(-a);
  256. end;
  257. OP_SUB:
  258. begin
  259. op:=OP_ADD;
  260. a:=dword(-a);
  261. end
  262. end;
  263. if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
  264. case op of
  265. OP_NEG,OP_NOT,
  266. OP_DIV,OP_IDIV:
  267. internalerror(200308281);
  268. OP_SHL:
  269. begin
  270. if a>32 then
  271. internalerror(200308291);
  272. if a<>0 then
  273. begin
  274. shifterop_reset(so);
  275. so.shiftmode:=SM_LSL;
  276. so.shiftimm:=a;
  277. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  278. end
  279. else
  280. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  281. end;
  282. OP_SHR:
  283. begin
  284. if a>32 then
  285. internalerror(200308292);
  286. shifterop_reset(so);
  287. if a<>0 then
  288. begin
  289. so.shiftmode:=SM_LSR;
  290. so.shiftimm:=a;
  291. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  292. end
  293. else
  294. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  295. end;
  296. OP_SAR:
  297. begin
  298. if a>32 then
  299. internalerror(200308291);
  300. if a<>0 then
  301. begin
  302. shifterop_reset(so);
  303. so.shiftmode:=SM_ASR;
  304. so.shiftimm:=a;
  305. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  306. end
  307. else
  308. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  309. end;
  310. else
  311. list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a));
  312. end
  313. else
  314. begin
  315. { there could be added some more sophisticated optimizations }
  316. if (op in [OP_MUL,OP_IMUL]) and (a=1) then
  317. a_load_reg_reg(list,size,size,src,dst)
  318. else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
  319. a_load_const_reg(list,size,0,dst)
  320. else if (op in [OP_IMUL]) and (a=-1) then
  321. a_op_reg_reg(list,OP_NEG,size,src,dst)
  322. { we do this here instead in the peephole optimizer because
  323. it saves us a register }
  324. else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) then
  325. a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
  326. else
  327. begin
  328. tmpreg:=getintregister(list,size);
  329. a_load_const_reg(list,size,a,tmpreg);
  330. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  331. end;
  332. end;
  333. end;
  334. procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  335. size: tcgsize; src1, src2, dst: tregister);
  336. var
  337. so : tshifterop;
  338. tmpreg : tregister;
  339. begin
  340. case op of
  341. OP_NEG,OP_NOT,
  342. OP_DIV,OP_IDIV:
  343. internalerror(200308281);
  344. OP_SHL:
  345. begin
  346. shifterop_reset(so);
  347. so.rs:=src1;
  348. so.shiftmode:=SM_LSL;
  349. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  350. end;
  351. OP_SHR:
  352. begin
  353. shifterop_reset(so);
  354. so.rs:=src1;
  355. so.shiftmode:=SM_LSR;
  356. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  357. end;
  358. OP_SAR:
  359. begin
  360. shifterop_reset(so);
  361. so.rs:=src1;
  362. so.shiftmode:=SM_ASR;
  363. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  364. end;
  365. OP_IMUL,
  366. OP_MUL:
  367. begin
  368. { the arm doesn't allow that rd and rm are the same }
  369. if dst=src2 then
  370. begin
  371. if dst<>src1 then
  372. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
  373. else
  374. begin
  375. tmpreg:=getintregister(list,size);
  376. a_load_reg_reg(list,size,size,src2,dst);
  377. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
  378. end;
  379. end
  380. else
  381. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
  382. end;
  383. else
  384. list.concat(setoppostfix(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1),toppostfix(ord(setflags)*ord(PF_S))));
  385. end;
  386. end;
  387. function rotl(d : dword;b : byte) : dword;
  388. begin
  389. result:=(d shr (32-b)) or (d shl b);
  390. end;
  391. function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
  392. var
  393. i : longint;
  394. begin
  395. for i:=0 to 15 do
  396. begin
  397. if (dword(d) and not(rotl($ff,i*2)))=0 then
  398. begin
  399. imm_shift:=i*2;
  400. result:=true;
  401. exit;
  402. end;
  403. end;
  404. result:=false;
  405. end;
  406. procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister);
  407. var
  408. imm_shift : byte;
  409. l : tasmlabel;
  410. hr : treference;
  411. begin
  412. if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
  413. internalerror(2002090902);
  414. if is_shifter_const(a,imm_shift) then
  415. list.concat(taicpu.op_reg_const(A_MOV,reg,a))
  416. else if is_shifter_const(not(a),imm_shift) then
  417. list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
  418. else
  419. begin
  420. reference_reset(hr);
  421. objectlibrary.getlabel(l);
  422. cg.a_label(current_procinfo.aktlocaldata,l);
  423. hr.symboldata:=current_procinfo.aktlocaldata.last;
  424. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
  425. hr.symbol:=l;
  426. list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
  427. end;
  428. end;
  429. procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  430. var
  431. tmpreg : tregister;
  432. tmpref : treference;
  433. l : tasmlabel;
  434. begin
  435. tmpreg:=NR_NO;
  436. { Be sure to have a base register }
  437. if (ref.base=NR_NO) then
  438. begin
  439. if ref.shiftmode<>SM_None then
  440. internalerror(200308294);
  441. ref.base:=ref.index;
  442. ref.index:=NR_NO;
  443. end;
  444. { absolute symbols can't be handled directly, we've to store the symbol reference
  445. in the text segment and access it pc relative
  446. For now, we assume that references where base or index equals to PC are already
  447. relative, all other references are assumed to be absolute and thus they need
  448. to be handled extra.
  449. A proper solution would be to change refoptions to a set and store the information
  450. if the symbol is absolute or relative there.
  451. }
  452. if (assigned(ref.symbol) and
  453. not(is_pc(ref.base)) and
  454. not(is_pc(ref.index))
  455. ) or
  456. (ref.offset<-4095) or
  457. (ref.offset>4095) or
  458. ((oppostfix in [PF_SB,PF_H,PF_SH]) and
  459. ((ref.offset<-255) or
  460. (ref.offset>255)
  461. )
  462. ) or
  463. ((op in [A_LDF,A_STF]) and
  464. ((ref.offset<-1020) or
  465. (ref.offset>1020)
  466. )
  467. ) then
  468. begin
  469. reference_reset(tmpref);
  470. { create consts entry }
  471. objectlibrary.getlabel(l);
  472. cg.a_label(current_procinfo.aktlocaldata,l);
  473. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  474. if assigned(ref.symbol) then
  475. current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
  476. else
  477. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  478. { load consts entry }
  479. tmpreg:=getintregister(list,OS_INT);
  480. tmpref.symbol:=l;
  481. tmpref.base:=NR_R15;
  482. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  483. if (ref.base<>NR_NO) then
  484. begin
  485. if ref.index<>NR_NO then
  486. begin
  487. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  488. ref.base:=tmpreg;
  489. end
  490. else
  491. begin
  492. ref.index:=tmpreg;
  493. ref.shiftimm:=0;
  494. ref.signindex:=1;
  495. ref.shiftmode:=SM_None;
  496. end;
  497. end
  498. else
  499. ref.base:=tmpreg;
  500. ref.offset:=0;
  501. ref.symbol:=nil;
  502. end;
  503. if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
  504. begin
  505. if tmpreg<>NR_NO then
  506. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
  507. else
  508. begin
  509. tmpreg:=getintregister(list,OS_ADDR);
  510. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
  511. ref.base:=tmpreg;
  512. end;
  513. ref.offset:=0;
  514. end;
  515. { floating point operations have only limited references
  516. we expect here, that a base is already set }
  517. if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
  518. begin
  519. if ref.shiftmode<>SM_none then
  520. internalerror(200309121);
  521. if tmpreg<>NR_NO then
  522. begin
  523. if ref.base=tmpreg then
  524. begin
  525. if ref.signindex<0 then
  526. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
  527. else
  528. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
  529. ref.index:=NR_NO;
  530. end
  531. else
  532. begin
  533. if ref.index<>tmpreg then
  534. internalerror(200403161);
  535. if ref.signindex<0 then
  536. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
  537. else
  538. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  539. ref.base:=tmpreg;
  540. ref.index:=NR_NO;
  541. end;
  542. end
  543. else
  544. begin
  545. tmpreg:=getintregister(list,OS_ADDR);
  546. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  547. ref.base:=tmpreg;
  548. ref.index:=NR_NO;
  549. end;
  550. end;
  551. list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
  552. end;
  553. procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  554. var
  555. oppostfix:toppostfix;
  556. begin
  557. case ToSize of
  558. { signed integer registers }
  559. OS_8,
  560. OS_S8:
  561. oppostfix:=PF_B;
  562. OS_16,
  563. OS_S16:
  564. oppostfix:=PF_H;
  565. OS_32,
  566. OS_S32:
  567. oppostfix:=PF_None;
  568. else
  569. InternalError(200308295);
  570. end;
  571. handle_load_store(list,A_STR,oppostfix,reg,ref);
  572. end;
  573. procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
  574. var
  575. oppostfix:toppostfix;
  576. begin
  577. case FromSize of
  578. { signed integer registers }
  579. OS_8:
  580. oppostfix:=PF_B;
  581. OS_S8:
  582. oppostfix:=PF_SB;
  583. OS_16:
  584. oppostfix:=PF_H;
  585. OS_S16:
  586. oppostfix:=PF_SH;
  587. OS_32,
  588. OS_S32:
  589. oppostfix:=PF_None;
  590. else
  591. InternalError(200308291);
  592. end;
  593. handle_load_store(list,A_LDR,oppostfix,reg,ref);
  594. end;
  595. procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  596. var
  597. instr: taicpu;
  598. so : tshifterop;
  599. begin
  600. shifterop_reset(so);
  601. if (reg1<>reg2) or
  602. (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  603. ((tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  604. (tosize <> fromsize) and
  605. not(fromsize in [OS_32,OS_S32])) then
  606. begin
  607. case tosize of
  608. OS_8:
  609. list.concat(taicpu.op_reg_reg_const(A_AND,
  610. reg2,reg1,$ff));
  611. OS_S8:
  612. begin
  613. so.shiftmode:=SM_LSL;
  614. so.shiftimm:=24;
  615. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  616. so.shiftmode:=SM_ASR;
  617. so.shiftimm:=24;
  618. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  619. end;
  620. OS_16:
  621. begin
  622. so.shiftmode:=SM_LSL;
  623. so.shiftimm:=16;
  624. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  625. so.shiftmode:=SM_LSR;
  626. so.shiftimm:=16;
  627. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  628. end;
  629. OS_S16:
  630. begin
  631. so.shiftmode:=SM_LSL;
  632. so.shiftimm:=16;
  633. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  634. so.shiftmode:=SM_ASR;
  635. so.shiftimm:=16;
  636. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  637. end;
  638. OS_32,OS_S32:
  639. begin
  640. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  641. list.concat(instr);
  642. add_move_instruction(instr);
  643. end;
  644. else internalerror(2002090901);
  645. end;
  646. end;
  647. end;
  648. procedure tcgarm.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
  649. begin
  650. list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
  651. end;
  652. procedure tcgarm.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  653. var
  654. oppostfix:toppostfix;
  655. begin
  656. case size of
  657. OS_F32:
  658. oppostfix:=PF_S;
  659. OS_F64:
  660. oppostfix:=PF_D;
  661. OS_F80:
  662. oppostfix:=PF_E;
  663. else
  664. InternalError(200309021);
  665. end;
  666. handle_load_store(list,A_LDF,oppostfix,reg,ref);
  667. end;
  668. procedure tcgarm.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  669. var
  670. oppostfix:toppostfix;
  671. begin
  672. case size of
  673. OS_F32:
  674. oppostfix:=PF_S;
  675. OS_F64:
  676. oppostfix:=PF_D;
  677. OS_F80:
  678. oppostfix:=PF_E;
  679. else
  680. InternalError(200309021);
  681. end;
  682. handle_load_store(list,A_STF,oppostfix,reg,ref);
  683. end;
  684. { comparison operations }
  685. procedure tcgarm.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  686. l : tasmlabel);
  687. var
  688. tmpreg : tregister;
  689. b : byte;
  690. begin
  691. if is_shifter_const(a,b) then
  692. list.concat(taicpu.op_reg_const(A_CMP,reg,a))
  693. { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
  694. and CMP reg,$7fffffff regarding the flags according to the ARM manual }
  695. else if (a<>$7fffffff) and (a<>-1) and is_shifter_const(-a,b) then
  696. list.concat(taicpu.op_reg_const(A_CMN,reg,-a))
  697. else
  698. begin
  699. tmpreg:=getintregister(list,size);
  700. a_load_const_reg(list,size,a,tmpreg);
  701. list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
  702. end;
  703. a_jmp_cond(list,cmp_op,l);
  704. end;
  705. procedure tcgarm.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  706. begin
  707. list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
  708. a_jmp_cond(list,cmp_op,l);
  709. end;
  710. procedure tcgarm.a_jmp_name(list : taasmoutput;const s : string);
  711. begin
  712. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)));
  713. end;
  714. procedure tcgarm.a_jmp_always(list : taasmoutput;l: tasmlabel);
  715. begin
  716. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(l.name,AB_EXTERNAL,AT_FUNCTION)));
  717. end;
  718. procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  719. var
  720. ai : taicpu;
  721. begin
  722. ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
  723. ai.is_jmp:=true;
  724. list.concat(ai);
  725. end;
  726. procedure tcgarm.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
  727. var
  728. ai : taicpu;
  729. begin
  730. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
  731. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond[flags_to_cond(f)]));
  732. end;
  733. procedure tcgarm.g_proc_entry(list : taasmoutput;localsize : longint;nostackframe:boolean);
  734. var
  735. ref : treference;
  736. shift : byte;
  737. firstfloatreg,lastfloatreg,
  738. r : byte;
  739. begin
  740. LocalSize:=align(LocalSize,4);
  741. firstfloatreg:=RS_NO;
  742. { save floating point registers? }
  743. for r:=RS_F0 to RS_F7 do
  744. if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
  745. begin
  746. if firstfloatreg=RS_NO then
  747. firstfloatreg:=r;
  748. lastfloatreg:=r;
  749. end;
  750. a_reg_alloc(list,NR_STACK_POINTER_REG);
  751. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  752. a_reg_alloc(list,NR_R12);
  753. list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
  754. { save int registers }
  755. reference_reset(ref);
  756. ref.index:=NR_STACK_POINTER_REG;
  757. ref.addressmode:=AM_PREINDEXED;
  758. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,
  759. rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R12,RS_R14,RS_R15]),
  760. PF_FD));
  761. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
  762. { allocate necessary stack size }
  763. { don't use a_op_const_reg_reg here because we don't allow register allocations
  764. in the entry/exit code }
  765. if not(is_shifter_const(localsize,shift)) then
  766. begin
  767. a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
  768. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
  769. a_reg_dealloc(list,NR_R12);
  770. end
  771. else
  772. begin
  773. a_reg_dealloc(list,NR_R12);
  774. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
  775. end;
  776. if firstfloatreg<>RS_NO then
  777. begin
  778. reference_reset(ref);
  779. ref.base:=NR_FRAME_POINTER_REG;
  780. ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
  781. list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
  782. lastfloatreg-firstfloatreg+1,ref));
  783. end;
  784. end;
  785. procedure tcgarm.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean);
  786. var
  787. ref : treference;
  788. firstfloatreg,lastfloatreg,
  789. r : byte;
  790. begin
  791. { restore floating point register }
  792. firstfloatreg:=RS_NO;
  793. { save floating point registers? }
  794. for r:=RS_F0 to RS_F7 do
  795. if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
  796. begin
  797. if firstfloatreg=RS_NO then
  798. firstfloatreg:=r;
  799. lastfloatreg:=r;
  800. end;
  801. if firstfloatreg<>RS_NO then
  802. begin
  803. reference_reset(ref);
  804. ref.base:=NR_FRAME_POINTER_REG;
  805. ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
  806. list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
  807. lastfloatreg-firstfloatreg+1,ref));
  808. end;
  809. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  810. list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
  811. else
  812. begin
  813. { restore int registers and return }
  814. reference_reset(ref);
  815. ref.index:=NR_FRAME_POINTER_REG;
  816. 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));
  817. end;
  818. end;
  819. procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  820. var
  821. b : byte;
  822. tmpref : treference;
  823. instr : taicpu;
  824. begin
  825. if ref.addressmode<>AM_OFFSET then
  826. internalerror(200309071);
  827. tmpref:=ref;
  828. { Be sure to have a base register }
  829. if (tmpref.base=NR_NO) then
  830. begin
  831. if tmpref.shiftmode<>SM_None then
  832. internalerror(200308294);
  833. if tmpref.signindex<0 then
  834. internalerror(200312023);
  835. tmpref.base:=tmpref.index;
  836. tmpref.index:=NR_NO;
  837. end;
  838. if assigned(tmpref.symbol) or
  839. not((is_shifter_const(tmpref.offset,b)) or
  840. (is_shifter_const(-tmpref.offset,b))
  841. ) then
  842. fixref(list,tmpref);
  843. { expect a base here }
  844. if tmpref.base=NR_NO then
  845. internalerror(200312022);
  846. if tmpref.index<>NR_NO then
  847. begin
  848. if tmpref.shiftmode<>SM_None then
  849. internalerror(200312021);
  850. if tmpref.signindex<0 then
  851. a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
  852. else
  853. a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
  854. if tmpref.offset<>0 then
  855. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
  856. end
  857. else
  858. begin
  859. if tmpref.offset<>0 then
  860. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
  861. else
  862. begin
  863. instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
  864. list.concat(instr);
  865. add_move_instruction(instr);
  866. end;
  867. end;
  868. end;
  869. procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
  870. var
  871. tmpreg : tregister;
  872. tmpref : treference;
  873. l : tasmlabel;
  874. begin
  875. { absolute symbols can't be handled directly, we've to store the symbol reference
  876. in the text segment and access it pc relative
  877. For now, we assume that references where base or index equals to PC are already
  878. relative, all other references are assumed to be absolute and thus they need
  879. to be handled extra.
  880. A proper solution would be to change refoptions to a set and store the information
  881. if the symbol is absolute or relative there.
  882. }
  883. { create consts entry }
  884. reference_reset(tmpref);
  885. objectlibrary.getlabel(l);
  886. cg.a_label(current_procinfo.aktlocaldata,l);
  887. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  888. if assigned(ref.symbol) then
  889. current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
  890. else
  891. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  892. { load consts entry }
  893. tmpreg:=getintregister(list,OS_INT);
  894. tmpref.symbol:=l;
  895. tmpref.base:=NR_PC;
  896. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  897. if (ref.base<>NR_NO) then
  898. begin
  899. if ref.index<>NR_NO then
  900. begin
  901. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  902. ref.base:=tmpreg;
  903. end
  904. else
  905. begin
  906. ref.index:=tmpreg;
  907. ref.shiftimm:=0;
  908. ref.signindex:=1;
  909. ref.shiftmode:=SM_None;
  910. end;
  911. end
  912. else
  913. ref.base:=tmpreg;
  914. ref.offset:=0;
  915. ref.symbol:=nil;
  916. end;
  917. procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);
  918. var
  919. srcref,dstref:treference;
  920. srcreg,destreg,countreg,r:tregister;
  921. helpsize:aword;
  922. copysize:byte;
  923. cgsize:Tcgsize;
  924. procedure genloop(count : aword;size : byte);
  925. const
  926. size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
  927. var
  928. l : tasmlabel;
  929. begin
  930. objectlibrary.getlabel(l);
  931. a_load_const_reg(list,OS_INT,count,countreg);
  932. cg.a_label(list,l);
  933. srcref.addressmode:=AM_POSTINDEXED;
  934. dstref.addressmode:=AM_POSTINDEXED;
  935. srcref.offset:=size;
  936. dstref.offset:=size;
  937. r:=getintregister(list,size2opsize[size]);
  938. a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
  939. a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
  940. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
  941. list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
  942. { keep the registers alive }
  943. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  944. list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
  945. list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
  946. end;
  947. begin
  948. if len=0 then
  949. exit;
  950. helpsize:=12;
  951. dstref:=dest;
  952. srcref:=source;
  953. if cs_littlesize in aktglobalswitches then
  954. helpsize:=8;
  955. if (len<=helpsize) then
  956. begin
  957. copysize:=4;
  958. cgsize:=OS_32;
  959. while len<>0 do
  960. begin
  961. if len<2 then
  962. begin
  963. copysize:=1;
  964. cgsize:=OS_8;
  965. end
  966. else if len<4 then
  967. begin
  968. copysize:=2;
  969. cgsize:=OS_16;
  970. end;
  971. dec(len,copysize);
  972. r:=getintregister(list,cgsize);
  973. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  974. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  975. inc(srcref.offset,copysize);
  976. inc(dstref.offset,copysize);
  977. end;
  978. end
  979. else
  980. begin
  981. destreg:=getintregister(list,OS_ADDR);
  982. a_loadaddr_ref_reg(list,dest,destreg);
  983. reference_reset_base(dstref,destreg,0);
  984. srcreg:=getintregister(list,OS_ADDR);
  985. a_loadaddr_ref_reg(list,source,srcreg);
  986. reference_reset_base(srcref,srcreg,0);
  987. countreg:=getintregister(list,OS_32);
  988. // if cs_littlesize in aktglobalswitches then
  989. genloop(len,1);
  990. {
  991. else
  992. begin
  993. helpsize:=len shr 2;
  994. len:=len and 3;
  995. if helpsize>1 then
  996. begin
  997. a_load_const_reg(list,OS_INT,helpsize,countreg);
  998. list.concat(Taicpu.op_none(A_REP,S_NO));
  999. end;
  1000. if helpsize>0 then
  1001. list.concat(Taicpu.op_none(A_MOVSD,S_NO));
  1002. if len>1 then
  1003. begin
  1004. dec(len,2);
  1005. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  1006. end;
  1007. if len=1 then
  1008. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  1009. end;
  1010. }
  1011. end;
  1012. end;
  1013. procedure tcgarm.g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
  1014. begin
  1015. end;
  1016. procedure tcgarm.g_save_standard_registers(list : taasmoutput);
  1017. begin
  1018. { this work is done in g_proc_entry }
  1019. end;
  1020. procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
  1021. begin
  1022. { this work is done in g_proc_exit }
  1023. end;
  1024. procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  1025. var
  1026. ai : taicpu;
  1027. begin
  1028. ai:=Taicpu.Op_sym(A_B,l);
  1029. ai.SetCondition(OpCmp2AsmCond[cond]);
  1030. ai.is_jmp:=true;
  1031. list.concat(ai);
  1032. end;
  1033. procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  1034. var
  1035. tmpreg : tregister;
  1036. begin
  1037. case op of
  1038. OP_NEG:
  1039. begin
  1040. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
  1041. list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
  1042. end;
  1043. OP_NOT:
  1044. begin
  1045. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
  1046. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
  1047. end;
  1048. else
  1049. a_op64_reg_reg_reg(list,op,regsrc,regdst,regdst);
  1050. end;
  1051. end;
  1052. procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);
  1053. begin
  1054. a_op64_const_reg_reg(list,op,value,reg,reg);
  1055. end;
  1056. procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : int64;regsrc,regdst : tregister64);
  1057. var
  1058. tmpreg : tregister;
  1059. b : byte;
  1060. begin
  1061. case op of
  1062. OP_AND,OP_OR,OP_XOR:
  1063. begin
  1064. cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
  1065. cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
  1066. end;
  1067. OP_ADD:
  1068. begin
  1069. if is_shifter_const(lo(value),b) then
  1070. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1071. else
  1072. begin
  1073. tmpreg:=cg.getintregister(list,OS_32);
  1074. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1075. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1076. end;
  1077. if is_shifter_const(hi(value),b) then
  1078. list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
  1079. else
  1080. begin
  1081. tmpreg:=cg.getintregister(list,OS_32);
  1082. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1083. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
  1084. end;
  1085. end;
  1086. OP_SUB:
  1087. begin
  1088. if is_shifter_const(lo(value),b) then
  1089. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1090. else
  1091. begin
  1092. tmpreg:=cg.getintregister(list,OS_32);
  1093. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1094. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1095. end;
  1096. if is_shifter_const(hi(value),b) then
  1097. list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
  1098. else
  1099. begin
  1100. tmpreg:=cg.getintregister(list,OS_32);
  1101. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1102. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
  1103. end;
  1104. end;
  1105. else
  1106. internalerror(2003083101);
  1107. end;
  1108. end;
  1109. procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
  1110. begin
  1111. case op of
  1112. OP_AND,OP_OR,OP_XOR:
  1113. begin
  1114. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
  1115. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
  1116. end;
  1117. OP_ADD:
  1118. begin
  1119. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1120. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
  1121. end;
  1122. OP_SUB:
  1123. begin
  1124. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1125. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
  1126. end;
  1127. else
  1128. internalerror(2003083101);
  1129. end;
  1130. end;
  1131. begin
  1132. cg:=tcgarm.create;
  1133. cg64:=tcg64farm.create;
  1134. end.
  1135. {
  1136. $Log$
  1137. Revision 1.63 2004-11-06 15:18:57 florian
  1138. * fixed OP_SUB for negative constants fitting in the shifter
  1139. Revision 1.62 2004/11/01 17:41:28 florian
  1140. * fixed arm compilation with cgutils
  1141. * ...
  1142. Revision 1.61 2004/10/31 16:47:43 florian
  1143. * fixed ie with pi_do_call
  1144. Revision 1.60 2004/10/31 16:04:30 florian
  1145. * fixed compilation of system unit on arm
  1146. Revision 1.59 2004/10/31 12:37:11 florian
  1147. * another couple of arm fixed
  1148. Revision 1.58 2004/10/24 17:32:53 florian
  1149. * fixed several arm compiler bugs
  1150. Revision 1.57 2004/10/24 11:53:45 peter
  1151. * fixed compilation with removed loadref
  1152. Revision 1.56 2004/10/24 07:54:25 florian
  1153. * fixed compilation of arm compiler
  1154. Revision 1.55 2004/10/11 15:46:45 peter
  1155. * length parameter for copyvaluearray changed to tlocation
  1156. Revision 1.54 2004/07/03 19:29:14 florian
  1157. * fixed problem with cpu interferences
  1158. Revision 1.53 2004/06/20 08:55:31 florian
  1159. * logs truncated
  1160. Revision 1.52 2004/06/16 20:07:10 florian
  1161. * dwarf branch merged
  1162. Revision 1.51.2.1 2004/06/12 17:01:01 florian
  1163. * fixed compilation of arm compiler
  1164. Revision 1.51 2004/03/31 19:13:04 florian
  1165. * concatcopy with len=0 exits now immediatly
  1166. Revision 1.50 2004/03/29 19:19:35 florian
  1167. + arm floating point register saving implemented
  1168. * hopefully stabs generation for MacOSX fixed
  1169. + some defines for arm added
  1170. Revision 1.49 2004/03/14 21:42:24 florian
  1171. * optimized mul code generation
  1172. }