cgcpu.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  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. if not(nostackframe) then
  742. begin
  743. firstfloatreg:=RS_NO;
  744. { save floating point registers? }
  745. for r:=RS_F0 to RS_F7 do
  746. if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
  747. begin
  748. if firstfloatreg=RS_NO then
  749. firstfloatreg:=r;
  750. lastfloatreg:=r;
  751. end;
  752. a_reg_alloc(list,NR_STACK_POINTER_REG);
  753. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  754. a_reg_alloc(list,NR_R12);
  755. list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
  756. { save int registers }
  757. reference_reset(ref);
  758. ref.index:=NR_STACK_POINTER_REG;
  759. ref.addressmode:=AM_PREINDEXED;
  760. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,
  761. rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R12,RS_R14,RS_R15]),
  762. PF_FD));
  763. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
  764. { allocate necessary stack size }
  765. { don't use a_op_const_reg_reg here because we don't allow register allocations
  766. in the entry/exit code }
  767. if not(is_shifter_const(localsize,shift)) then
  768. begin
  769. a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
  770. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
  771. a_reg_dealloc(list,NR_R12);
  772. end
  773. else
  774. begin
  775. a_reg_dealloc(list,NR_R12);
  776. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
  777. end;
  778. if firstfloatreg<>RS_NO then
  779. begin
  780. reference_reset(ref);
  781. ref.base:=NR_FRAME_POINTER_REG;
  782. ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
  783. list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
  784. lastfloatreg-firstfloatreg+1,ref));
  785. end;
  786. end;
  787. end;
  788. procedure tcgarm.g_proc_exit(list : taasmoutput;parasize : longint;nostackframe:boolean);
  789. var
  790. ref : treference;
  791. firstfloatreg,lastfloatreg,
  792. r : byte;
  793. begin
  794. if not(nostackframe) then
  795. begin
  796. { restore floating point register }
  797. firstfloatreg:=RS_NO;
  798. { save floating point registers? }
  799. for r:=RS_F0 to RS_F7 do
  800. if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
  801. begin
  802. if firstfloatreg=RS_NO then
  803. firstfloatreg:=r;
  804. lastfloatreg:=r;
  805. end;
  806. if firstfloatreg<>RS_NO then
  807. begin
  808. reference_reset(ref);
  809. ref.base:=NR_FRAME_POINTER_REG;
  810. ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
  811. list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
  812. lastfloatreg-firstfloatreg+1,ref));
  813. end;
  814. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  815. list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
  816. else
  817. begin
  818. { restore int registers and return }
  819. reference_reset(ref);
  820. ref.index:=NR_FRAME_POINTER_REG;
  821. 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));
  822. end;
  823. end
  824. else
  825. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
  826. end;
  827. procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  828. var
  829. b : byte;
  830. tmpref : treference;
  831. instr : taicpu;
  832. begin
  833. if ref.addressmode<>AM_OFFSET then
  834. internalerror(200309071);
  835. tmpref:=ref;
  836. { Be sure to have a base register }
  837. if (tmpref.base=NR_NO) then
  838. begin
  839. if tmpref.shiftmode<>SM_None then
  840. internalerror(200308294);
  841. if tmpref.signindex<0 then
  842. internalerror(200312023);
  843. tmpref.base:=tmpref.index;
  844. tmpref.index:=NR_NO;
  845. end;
  846. if assigned(tmpref.symbol) or
  847. not((is_shifter_const(tmpref.offset,b)) or
  848. (is_shifter_const(-tmpref.offset,b))
  849. ) then
  850. fixref(list,tmpref);
  851. { expect a base here }
  852. if tmpref.base=NR_NO then
  853. internalerror(200312022);
  854. if tmpref.index<>NR_NO then
  855. begin
  856. if tmpref.shiftmode<>SM_None then
  857. internalerror(200312021);
  858. if tmpref.signindex<0 then
  859. a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
  860. else
  861. a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
  862. if tmpref.offset<>0 then
  863. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
  864. end
  865. else
  866. begin
  867. if tmpref.offset<>0 then
  868. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
  869. else
  870. begin
  871. instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
  872. list.concat(instr);
  873. add_move_instruction(instr);
  874. end;
  875. end;
  876. end;
  877. procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
  878. var
  879. tmpreg : tregister;
  880. tmpref : treference;
  881. l : tasmlabel;
  882. begin
  883. { absolute symbols can't be handled directly, we've to store the symbol reference
  884. in the text segment and access it pc relative
  885. For now, we assume that references where base or index equals to PC are already
  886. relative, all other references are assumed to be absolute and thus they need
  887. to be handled extra.
  888. A proper solution would be to change refoptions to a set and store the information
  889. if the symbol is absolute or relative there.
  890. }
  891. { create consts entry }
  892. reference_reset(tmpref);
  893. objectlibrary.getlabel(l);
  894. cg.a_label(current_procinfo.aktlocaldata,l);
  895. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  896. if assigned(ref.symbol) then
  897. current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
  898. else
  899. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  900. { load consts entry }
  901. tmpreg:=getintregister(list,OS_INT);
  902. tmpref.symbol:=l;
  903. tmpref.base:=NR_PC;
  904. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  905. if (ref.base<>NR_NO) then
  906. begin
  907. if ref.index<>NR_NO then
  908. begin
  909. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  910. ref.base:=tmpreg;
  911. end
  912. else
  913. begin
  914. ref.index:=tmpreg;
  915. ref.shiftimm:=0;
  916. ref.signindex:=1;
  917. ref.shiftmode:=SM_None;
  918. end;
  919. end
  920. else
  921. ref.base:=tmpreg;
  922. ref.offset:=0;
  923. ref.symbol:=nil;
  924. end;
  925. procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aint);
  926. var
  927. srcref,dstref:treference;
  928. srcreg,destreg,countreg,r:tregister;
  929. helpsize:aword;
  930. copysize:byte;
  931. cgsize:Tcgsize;
  932. procedure genloop(count : aword;size : byte);
  933. const
  934. size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
  935. var
  936. l : tasmlabel;
  937. begin
  938. objectlibrary.getlabel(l);
  939. a_load_const_reg(list,OS_INT,count,countreg);
  940. cg.a_label(list,l);
  941. srcref.addressmode:=AM_POSTINDEXED;
  942. dstref.addressmode:=AM_POSTINDEXED;
  943. srcref.offset:=size;
  944. dstref.offset:=size;
  945. r:=getintregister(list,size2opsize[size]);
  946. a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
  947. a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
  948. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
  949. list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
  950. { keep the registers alive }
  951. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  952. list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
  953. list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
  954. end;
  955. begin
  956. if len=0 then
  957. exit;
  958. helpsize:=12;
  959. dstref:=dest;
  960. srcref:=source;
  961. if cs_littlesize in aktglobalswitches then
  962. helpsize:=8;
  963. if (len<=helpsize) then
  964. begin
  965. copysize:=4;
  966. cgsize:=OS_32;
  967. while len<>0 do
  968. begin
  969. if len<2 then
  970. begin
  971. copysize:=1;
  972. cgsize:=OS_8;
  973. end
  974. else if len<4 then
  975. begin
  976. copysize:=2;
  977. cgsize:=OS_16;
  978. end;
  979. dec(len,copysize);
  980. r:=getintregister(list,cgsize);
  981. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  982. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  983. inc(srcref.offset,copysize);
  984. inc(dstref.offset,copysize);
  985. end;
  986. end
  987. else
  988. begin
  989. destreg:=getintregister(list,OS_ADDR);
  990. a_loadaddr_ref_reg(list,dest,destreg);
  991. reference_reset_base(dstref,destreg,0);
  992. srcreg:=getintregister(list,OS_ADDR);
  993. a_loadaddr_ref_reg(list,source,srcreg);
  994. reference_reset_base(srcref,srcreg,0);
  995. countreg:=getintregister(list,OS_32);
  996. // if cs_littlesize in aktglobalswitches then
  997. genloop(len,1);
  998. {
  999. else
  1000. begin
  1001. helpsize:=len shr 2;
  1002. len:=len and 3;
  1003. if helpsize>1 then
  1004. begin
  1005. a_load_const_reg(list,OS_INT,helpsize,countreg);
  1006. list.concat(Taicpu.op_none(A_REP,S_NO));
  1007. end;
  1008. if helpsize>0 then
  1009. list.concat(Taicpu.op_none(A_MOVSD,S_NO));
  1010. if len>1 then
  1011. begin
  1012. dec(len,2);
  1013. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  1014. end;
  1015. if len=1 then
  1016. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  1017. end;
  1018. }
  1019. end;
  1020. end;
  1021. procedure tcgarm.g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
  1022. begin
  1023. end;
  1024. procedure tcgarm.g_save_standard_registers(list : taasmoutput);
  1025. begin
  1026. { this work is done in g_proc_entry }
  1027. end;
  1028. procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
  1029. begin
  1030. { this work is done in g_proc_exit }
  1031. end;
  1032. procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  1033. var
  1034. ai : taicpu;
  1035. begin
  1036. ai:=Taicpu.Op_sym(A_B,l);
  1037. ai.SetCondition(OpCmp2AsmCond[cond]);
  1038. ai.is_jmp:=true;
  1039. list.concat(ai);
  1040. end;
  1041. procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  1042. var
  1043. tmpreg : tregister;
  1044. begin
  1045. case op of
  1046. OP_NEG:
  1047. begin
  1048. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
  1049. list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
  1050. end;
  1051. OP_NOT:
  1052. begin
  1053. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
  1054. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
  1055. end;
  1056. else
  1057. a_op64_reg_reg_reg(list,op,regsrc,regdst,regdst);
  1058. end;
  1059. end;
  1060. procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);
  1061. begin
  1062. a_op64_const_reg_reg(list,op,value,reg,reg);
  1063. end;
  1064. procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : int64;regsrc,regdst : tregister64);
  1065. var
  1066. tmpreg : tregister;
  1067. b : byte;
  1068. begin
  1069. case op of
  1070. OP_AND,OP_OR,OP_XOR:
  1071. begin
  1072. cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
  1073. cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
  1074. end;
  1075. OP_ADD:
  1076. begin
  1077. if is_shifter_const(lo(value),b) then
  1078. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1079. else
  1080. begin
  1081. tmpreg:=cg.getintregister(list,OS_32);
  1082. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1083. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1084. end;
  1085. if is_shifter_const(hi(value),b) then
  1086. list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
  1087. else
  1088. begin
  1089. tmpreg:=cg.getintregister(list,OS_32);
  1090. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1091. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
  1092. end;
  1093. end;
  1094. OP_SUB:
  1095. begin
  1096. if is_shifter_const(lo(value),b) then
  1097. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1098. else
  1099. begin
  1100. tmpreg:=cg.getintregister(list,OS_32);
  1101. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1102. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1103. end;
  1104. if is_shifter_const(hi(value),b) then
  1105. list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
  1106. else
  1107. begin
  1108. tmpreg:=cg.getintregister(list,OS_32);
  1109. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1110. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
  1111. end;
  1112. end;
  1113. else
  1114. internalerror(2003083101);
  1115. end;
  1116. end;
  1117. procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
  1118. begin
  1119. case op of
  1120. OP_AND,OP_OR,OP_XOR:
  1121. begin
  1122. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
  1123. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
  1124. end;
  1125. OP_ADD:
  1126. begin
  1127. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1128. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
  1129. end;
  1130. OP_SUB:
  1131. begin
  1132. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1133. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
  1134. end;
  1135. else
  1136. internalerror(2003083101);
  1137. end;
  1138. end;
  1139. begin
  1140. cg:=tcgarm.create;
  1141. cg64:=tcg64farm.create;
  1142. end.
  1143. {
  1144. $Log$
  1145. Revision 1.64 2005-01-04 15:36:32 florian
  1146. * implemented nostackframe calling convention directive
  1147. Revision 1.63 2004/11/06 15:18:57 florian
  1148. * fixed OP_SUB for negative constants fitting in the shifter
  1149. Revision 1.62 2004/11/01 17:41:28 florian
  1150. * fixed arm compilation with cgutils
  1151. * ...
  1152. Revision 1.61 2004/10/31 16:47:43 florian
  1153. * fixed ie with pi_do_call
  1154. Revision 1.60 2004/10/31 16:04:30 florian
  1155. * fixed compilation of system unit on arm
  1156. Revision 1.59 2004/10/31 12:37:11 florian
  1157. * another couple of arm fixed
  1158. Revision 1.58 2004/10/24 17:32:53 florian
  1159. * fixed several arm compiler bugs
  1160. Revision 1.57 2004/10/24 11:53:45 peter
  1161. * fixed compilation with removed loadref
  1162. Revision 1.56 2004/10/24 07:54:25 florian
  1163. * fixed compilation of arm compiler
  1164. Revision 1.55 2004/10/11 15:46:45 peter
  1165. * length parameter for copyvaluearray changed to tlocation
  1166. Revision 1.54 2004/07/03 19:29:14 florian
  1167. * fixed problem with cpu interferences
  1168. Revision 1.53 2004/06/20 08:55:31 florian
  1169. * logs truncated
  1170. Revision 1.52 2004/06/16 20:07:10 florian
  1171. * dwarf branch merged
  1172. Revision 1.51.2.1 2004/06/12 17:01:01 florian
  1173. * fixed compilation of arm compiler
  1174. Revision 1.51 2004/03/31 19:13:04 florian
  1175. * concatcopy with len=0 exits now immediatly
  1176. Revision 1.50 2004/03/29 19:19:35 florian
  1177. + arm floating point register saving implemented
  1178. * hopefully stabs generation for MacOSX fixed
  1179. + some defines for arm added
  1180. Revision 1.49 2004/03/14 21:42:24 florian
  1181. * optimized mul code generation
  1182. }