cgcpu.pas 47 KB

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