cgcpu.pas 46 KB

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