cgcpu.pas 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428
  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. 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 : aword;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: AWord; 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: aword; 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 : aword;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 : aword;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_always(list : taasmoutput;l: tasmlabel); override;
  58. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  59. procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  60. procedure g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);override;
  61. procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
  62. procedure g_return_from_proc(list : taasmoutput;parasize : aword); override;
  63. procedure g_restore_frame_pointer(list : taasmoutput);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 : aword; 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;accused,acchiused:boolean);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 : qword;reg : tregister64);override;
  78. procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;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. globtype,globals,verbose,systems,cutils,
  89. symconst,symdef,symsym,
  90. tgobj,
  91. procinfo,cpupi,
  92. paramgr;
  93. function get_fpu_postfix(def : tdef) : toppostfix;
  94. begin
  95. if def.deftype=floatdef then
  96. begin
  97. case tfloatdef(def).typ of
  98. s32real:
  99. result:=PF_S;
  100. s64real:
  101. result:=PF_D;
  102. s80real:
  103. result:=PF_E;
  104. else
  105. internalerror(200401272);
  106. end;
  107. end
  108. else
  109. internalerror(200401271);
  110. end;
  111. procedure tcgarm.init_register_allocators;
  112. begin
  113. inherited init_register_allocators;
  114. { currently, we save R14 always, so we can use it }
  115. rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
  116. [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
  117. RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
  118. rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  119. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
  120. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  121. [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
  122. end;
  123. procedure tcgarm.done_register_allocators;
  124. begin
  125. rg[R_INTREGISTER].free;
  126. rg[R_FPUREGISTER].free;
  127. rg[R_MMREGISTER].free;
  128. inherited done_register_allocators;
  129. end;
  130. procedure tcgarm.a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);
  131. var
  132. ref: treference;
  133. begin
  134. case locpara.loc of
  135. LOC_REGISTER,LOC_CREGISTER:
  136. a_load_const_reg(list,size,a,locpara.register);
  137. LOC_REFERENCE:
  138. begin
  139. reference_reset(ref);
  140. ref.base:=locpara.reference.index;
  141. ref.offset:=locpara.reference.offset;
  142. a_load_const_ref(list,size,a,ref);
  143. end;
  144. else
  145. internalerror(2002081101);
  146. end;
  147. if locpara.alignment<>0 then
  148. internalerror(2002081102);
  149. end;
  150. procedure tcgarm.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
  151. var
  152. ref: treference;
  153. tmpreg: tregister;
  154. begin
  155. case locpara.loc of
  156. LOC_REGISTER,LOC_CREGISTER:
  157. a_load_ref_reg(list,size,size,r,locpara.register);
  158. LOC_REFERENCE:
  159. begin
  160. reference_reset(ref);
  161. ref.base:=locpara.reference.index;
  162. ref.offset:=locpara.reference.offset;
  163. tmpreg := getintregister(list,size);
  164. a_load_ref_reg(list,size,size,r,tmpreg);
  165. a_load_reg_ref(list,size,size,tmpreg,ref);
  166. ungetregister(list,tmpreg);
  167. end;
  168. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  169. case size of
  170. OS_F32, OS_F64:
  171. a_loadfpu_ref_reg(list,size,r,locpara.register);
  172. else
  173. internalerror(2002072801);
  174. end;
  175. else
  176. internalerror(2002081103);
  177. end;
  178. if locpara.alignment<>0 then
  179. internalerror(2002081104);
  180. end;
  181. procedure tcgarm.a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  182. var
  183. ref: treference;
  184. tmpreg: tregister;
  185. begin
  186. case locpara.loc of
  187. LOC_REGISTER,LOC_CREGISTER:
  188. a_loadaddr_ref_reg(list,r,locpara.register);
  189. LOC_REFERENCE:
  190. begin
  191. reference_reset(ref);
  192. ref.base := locpara.reference.index;
  193. ref.offset := locpara.reference.offset;
  194. tmpreg := getintregister(list,OS_ADDR);
  195. a_loadaddr_ref_reg(list,r,tmpreg);
  196. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  197. ungetregister(list,tmpreg);
  198. end;
  199. else
  200. internalerror(2002080701);
  201. end;
  202. end;
  203. procedure tcgarm.a_call_name(list : taasmoutput;const s : string);
  204. begin
  205. list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s)));
  206. if not(pi_do_call in current_procinfo.flags) then
  207. internalerror(2003060703);
  208. end;
  209. procedure tcgarm.a_call_reg(list : taasmoutput;reg: tregister);
  210. var
  211. r : tregister;
  212. begin
  213. list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
  214. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
  215. if not(pi_do_call in current_procinfo.flags) then
  216. internalerror(2003060704);
  217. end;
  218. procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister);
  219. begin
  220. a_op_const_reg_reg(list,op,size,a,reg,reg);
  221. end;
  222. procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  223. begin
  224. case op of
  225. OP_NEG:
  226. list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
  227. OP_NOT:
  228. list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
  229. else
  230. a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
  231. end;
  232. end;
  233. const
  234. op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
  235. (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
  236. A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
  237. procedure tcgarm.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  238. size: tcgsize; a: aword; src, dst: tregister);
  239. var
  240. shift : byte;
  241. tmpreg : tregister;
  242. so : tshifterop;
  243. begin
  244. if is_shifter_const(dword(-a),shift) then
  245. case op of
  246. OP_ADD:
  247. begin
  248. op:=OP_SUB;
  249. a:=dword(-a);
  250. end;
  251. OP_SUB:
  252. begin
  253. op:=OP_SUB;
  254. a:=dword(-a);
  255. end
  256. end;
  257. if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
  258. case op of
  259. OP_NEG,OP_NOT,
  260. OP_DIV,OP_IDIV:
  261. internalerror(200308281);
  262. OP_SHL:
  263. begin
  264. if a>32 then
  265. internalerror(200308291);
  266. if a<>0 then
  267. begin
  268. shifterop_reset(so);
  269. so.shiftmode:=SM_LSL;
  270. so.shiftimm:=a;
  271. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  272. end
  273. else
  274. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  275. end;
  276. OP_SHR:
  277. begin
  278. if a>32 then
  279. internalerror(200308292);
  280. shifterop_reset(so);
  281. if a<>0 then
  282. begin
  283. so.shiftmode:=SM_LSR;
  284. so.shiftimm:=a;
  285. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  286. end
  287. else
  288. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  289. end;
  290. OP_SAR:
  291. begin
  292. if a>32 then
  293. internalerror(200308291);
  294. if a<>0 then
  295. begin
  296. shifterop_reset(so);
  297. so.shiftmode:=SM_ASR;
  298. so.shiftimm:=a;
  299. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  300. end
  301. else
  302. list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
  303. end;
  304. else
  305. list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a));
  306. end
  307. else
  308. begin
  309. { there could be added some more sophisticated optimizations }
  310. if (op in [OP_MUL,OP_IMUL]) and (a=1) then
  311. a_load_reg_reg(list,size,size,src,dst)
  312. else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
  313. a_load_const_reg(list,size,0,dst)
  314. else if (op in [OP_IMUL]) and (a=-1) then
  315. a_op_reg_reg(list,OP_NEG,size,src,dst)
  316. else
  317. begin
  318. tmpreg:=getintregister(list,size);
  319. a_load_const_reg(list,size,a,tmpreg);
  320. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  321. ungetregister(list,tmpreg);
  322. end;
  323. end;
  324. end;
  325. procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  326. size: tcgsize; src1, src2, dst: tregister);
  327. var
  328. so : tshifterop;
  329. tmpreg : tregister;
  330. begin
  331. case op of
  332. OP_NEG,OP_NOT,
  333. OP_DIV,OP_IDIV:
  334. internalerror(200308281);
  335. OP_SHL:
  336. begin
  337. shifterop_reset(so);
  338. so.rs:=src1;
  339. so.shiftmode:=SM_LSL;
  340. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  341. end;
  342. OP_SHR:
  343. begin
  344. shifterop_reset(so);
  345. so.rs:=src1;
  346. so.shiftmode:=SM_LSR;
  347. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  348. end;
  349. OP_SAR:
  350. begin
  351. shifterop_reset(so);
  352. so.rs:=src1;
  353. so.shiftmode:=SM_ASR;
  354. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  355. end;
  356. OP_IMUL,
  357. OP_MUL:
  358. begin
  359. { the arm doesn't allow that rd and rm are the same }
  360. if dst=src2 then
  361. begin
  362. if dst<>src1 then
  363. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
  364. else
  365. begin
  366. tmpreg:=getintregister(list,size);
  367. a_load_reg_reg(list,size,size,src2,dst);
  368. ungetregister(list,tmpreg);
  369. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
  370. end;
  371. end
  372. else
  373. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
  374. end;
  375. else
  376. list.concat(setoppostfix(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1),toppostfix(ord(setflags)*ord(PF_S))));
  377. end;
  378. end;
  379. function rotl(d : dword;b : byte) : dword;
  380. begin
  381. result:=(d shr (32-b)) or (d shl b);
  382. end;
  383. function is_shifter_const(d : dword;var imm_shift : byte) : boolean;
  384. var
  385. i : longint;
  386. begin
  387. for i:=0 to 15 do
  388. begin
  389. if (d and not(rotl($ff,i*2)))=0 then
  390. begin
  391. imm_shift:=i*2;
  392. result:=true;
  393. exit;
  394. end;
  395. end;
  396. result:=false;
  397. end;
  398. procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);
  399. var
  400. imm_shift : byte;
  401. l : tasmlabel;
  402. hr : treference;
  403. begin
  404. if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
  405. internalerror(2002090902);
  406. if is_shifter_const(dword(a),imm_shift) then
  407. list.concat(taicpu.op_reg_const(A_MOV,reg,a))
  408. else if is_shifter_const(dword(not(a)),imm_shift) then
  409. list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
  410. else
  411. begin
  412. reference_reset(hr);
  413. objectlibrary.getlabel(l);
  414. cg.a_label(current_procinfo.aktlocaldata,l);
  415. hr.symboldata:=current_procinfo.aktlocaldata.last;
  416. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
  417. hr.symbol:=l;
  418. list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
  419. end;
  420. end;
  421. procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  422. var
  423. tmpreg : tregister;
  424. tmpref : treference;
  425. l : tasmlabel;
  426. begin
  427. tmpreg:=NR_NO;
  428. { Be sure to have a base register }
  429. if (ref.base=NR_NO) then
  430. begin
  431. if ref.shiftmode<>SM_None then
  432. internalerror(200308294);
  433. ref.base:=ref.index;
  434. ref.index:=NR_NO;
  435. end;
  436. { absolute symbols can't be handled directly, we've to store the symbol reference
  437. in the text segment and access it pc relative
  438. For now, we assume that references where base or index equals to PC are already
  439. relative, all other references are assumed to be absolute and thus they need
  440. to be handled extra.
  441. A proper solution would be to change refoptions to a set and store the information
  442. if the symbol is absolute or relative there.
  443. }
  444. if (assigned(ref.symbol) and
  445. not(is_pc(ref.base)) and
  446. not(is_pc(ref.index))
  447. ) or
  448. (ref.offset<-4095) or
  449. (ref.offset>4095) or
  450. ((oppostfix in [PF_SB,PF_H,PF_SH]) and
  451. ((ref.offset<-255) or
  452. (ref.offset>255)
  453. )
  454. ) then
  455. begin
  456. reference_reset(tmpref);
  457. { create consts entry }
  458. objectlibrary.getlabel(l);
  459. cg.a_label(current_procinfo.aktlocaldata,l);
  460. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  461. if assigned(ref.symbol) then
  462. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  463. else
  464. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  465. { load consts entry }
  466. tmpreg:=getintregister(list,OS_INT);
  467. tmpref.symbol:=l;
  468. tmpref.base:=NR_R15;
  469. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  470. if (ref.base<>NR_NO) then
  471. begin
  472. if ref.index<>NR_NO then
  473. begin
  474. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  475. ref.base:=tmpreg;
  476. end
  477. else
  478. begin
  479. ref.index:=tmpreg;
  480. ref.shiftimm:=0;
  481. ref.signindex:=1;
  482. ref.shiftmode:=SM_None;
  483. end;
  484. end
  485. else
  486. ref.base:=tmpreg;
  487. ref.offset:=0;
  488. ref.symbol:=nil;
  489. end;
  490. if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
  491. begin
  492. if tmpreg<>NR_NO then
  493. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
  494. else
  495. begin
  496. tmpreg:=getintregister(list,OS_ADDR);
  497. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
  498. ref.base:=tmpreg;
  499. end;
  500. ref.offset:=0;
  501. end;
  502. { floating point operations have only limited references
  503. we expect here, that a base is already set }
  504. if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
  505. begin
  506. if ref.shiftmode<>SM_none then
  507. internalerror(200309121);
  508. if tmpreg<>NR_NO then
  509. begin
  510. if ref.base=tmpreg then
  511. begin
  512. if ref.signindex<0 then
  513. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index))
  514. else
  515. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index));
  516. ref.index:=NR_NO;
  517. end
  518. else
  519. begin
  520. if ref.signindex<0 then
  521. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.base))
  522. else
  523. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.base));
  524. ref.index:=NR_NO;
  525. ref.index:=tmpreg;
  526. end;
  527. end
  528. else
  529. begin
  530. tmpreg:=getintregister(list,OS_ADDR);
  531. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  532. ref.base:=tmpreg;
  533. ref.index:=NR_NO;
  534. end;
  535. end;
  536. list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
  537. if (tmpreg<>NR_NO) then
  538. ungetregister(list,tmpreg);
  539. end;
  540. procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  541. var
  542. oppostfix:toppostfix;
  543. begin
  544. case ToSize of
  545. { signed integer registers }
  546. OS_8,
  547. OS_S8:
  548. oppostfix:=PF_B;
  549. OS_16,
  550. OS_S16:
  551. oppostfix:=PF_H;
  552. OS_32,
  553. OS_S32:
  554. oppostfix:=PF_None;
  555. else
  556. InternalError(200308295);
  557. end;
  558. handle_load_store(list,A_STR,oppostfix,reg,ref);
  559. end;
  560. procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
  561. var
  562. oppostfix:toppostfix;
  563. begin
  564. case FromSize of
  565. { signed integer registers }
  566. OS_8:
  567. oppostfix:=PF_B;
  568. OS_S8:
  569. oppostfix:=PF_SB;
  570. OS_16:
  571. oppostfix:=PF_H;
  572. OS_S16:
  573. oppostfix:=PF_SH;
  574. OS_32,
  575. OS_S32:
  576. oppostfix:=PF_None;
  577. else
  578. InternalError(200308291);
  579. end;
  580. handle_load_store(list,A_LDR,oppostfix,reg,ref);
  581. end;
  582. procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  583. var
  584. instr: taicpu;
  585. so : tshifterop;
  586. begin
  587. shifterop_reset(so);
  588. if (reg1<>reg2) or
  589. (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  590. ((tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  591. (tosize <> fromsize) and
  592. not(fromsize in [OS_32,OS_S32])) then
  593. begin
  594. case tosize of
  595. OS_8:
  596. list.concat(taicpu.op_reg_reg_const(A_AND,
  597. reg2,reg1,$ff));
  598. OS_S8:
  599. begin
  600. so.shiftmode:=SM_LSL;
  601. so.shiftimm:=24;
  602. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  603. so.shiftmode:=SM_ASR;
  604. so.shiftimm:=24;
  605. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  606. end;
  607. OS_16:
  608. begin
  609. so.shiftmode:=SM_LSL;
  610. so.shiftimm:=16;
  611. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  612. so.shiftmode:=SM_LSR;
  613. so.shiftimm:=16;
  614. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  615. end;
  616. OS_S16:
  617. begin
  618. so.shiftmode:=SM_LSL;
  619. so.shiftimm:=16;
  620. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  621. so.shiftmode:=SM_ASR;
  622. so.shiftimm:=16;
  623. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  624. end;
  625. OS_32,OS_S32:
  626. begin
  627. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  628. list.concat(instr);
  629. add_move_instruction(instr);
  630. end;
  631. else internalerror(2002090901);
  632. end;
  633. end;
  634. end;
  635. procedure tcgarm.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
  636. begin
  637. list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
  638. end;
  639. procedure tcgarm.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  640. var
  641. oppostfix:toppostfix;
  642. begin
  643. case size of
  644. OS_F32:
  645. oppostfix:=PF_S;
  646. OS_F64:
  647. oppostfix:=PF_D;
  648. OS_F80:
  649. oppostfix:=PF_E;
  650. else
  651. InternalError(200309021);
  652. end;
  653. handle_load_store(list,A_LDF,oppostfix,reg,ref);
  654. end;
  655. procedure tcgarm.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  656. var
  657. oppostfix:toppostfix;
  658. begin
  659. case size of
  660. OS_F32:
  661. oppostfix:=PF_S;
  662. OS_F64:
  663. oppostfix:=PF_D;
  664. OS_F80:
  665. oppostfix:=PF_E;
  666. else
  667. InternalError(200309021);
  668. end;
  669. handle_load_store(list,A_STF,oppostfix,reg,ref);
  670. end;
  671. { comparison operations }
  672. procedure tcgarm.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  673. l : tasmlabel);
  674. var
  675. tmpreg : tregister;
  676. b : byte;
  677. begin
  678. if is_shifter_const(a,b) then
  679. list.concat(taicpu.op_reg_const(A_CMP,reg,a))
  680. { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
  681. and CMP reg,$7fffffff regarding the flags according to the ARM manual }
  682. else if is_shifter_const(not(a),b) and (a<>$7fffffff) and (a<>$ffffffff) then
  683. list.concat(taicpu.op_reg_const(A_CMN,reg,not(a)))
  684. else
  685. begin
  686. tmpreg:=getintregister(list,size);
  687. a_load_const_reg(list,size,a,tmpreg);
  688. list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
  689. ungetregister(list,tmpreg);
  690. end;
  691. a_jmp_cond(list,cmp_op,l);
  692. end;
  693. procedure tcgarm.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  694. begin
  695. list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
  696. a_jmp_cond(list,cmp_op,l);
  697. end;
  698. procedure tcgarm.a_jmp_always(list : taasmoutput;l: tasmlabel);
  699. begin
  700. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(l.name)));
  701. end;
  702. procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  703. var
  704. ai : taicpu;
  705. begin
  706. ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
  707. ai.is_jmp:=true;
  708. list.concat(ai);
  709. end;
  710. procedure tcgarm.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
  711. var
  712. ai : taicpu;
  713. begin
  714. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
  715. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond[flags_to_cond(f)]));
  716. end;
  717. procedure tcgarm.g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);
  718. begin
  719. end;
  720. procedure tcgarm.g_stackframe_entry(list : taasmoutput;localsize : longint);
  721. var
  722. ref : treference;
  723. shift : byte;
  724. begin
  725. LocalSize:=align(LocalSize,4);
  726. a_reg_alloc(list,NR_STACK_POINTER_REG);
  727. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  728. a_reg_alloc(list,NR_R12);
  729. list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
  730. { save int registers }
  731. reference_reset(ref);
  732. ref.index:=NR_STACK_POINTER_REG;
  733. ref.addressmode:=AM_PREINDEXED;
  734. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R12,RS_R14,RS_R15]),PF_FD));
  735. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
  736. { allocate necessary stack size }
  737. { don't use a_op_const_reg_reg here because we don't allow register allocations
  738. in the entry/exit code }
  739. if not(is_shifter_const(localsize,shift)) then
  740. begin
  741. a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
  742. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
  743. a_reg_dealloc(list,NR_R12);
  744. end
  745. else
  746. begin
  747. a_reg_dealloc(list,NR_R12);
  748. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
  749. end;
  750. end;
  751. procedure tcgarm.g_return_from_proc(list : taasmoutput;parasize : aword);
  752. var
  753. ref : treference;
  754. begin
  755. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  756. list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
  757. else
  758. begin
  759. { restore int registers and return }
  760. reference_reset(ref);
  761. ref.index:=NR_FRAME_POINTER_REG;
  762. 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));
  763. end;
  764. end;
  765. procedure tcgarm.g_restore_frame_pointer(list : taasmoutput);
  766. begin
  767. { the frame pointer on the ARM is restored while the ret is executed }
  768. end;
  769. procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  770. var
  771. b : byte;
  772. tmpref : treference;
  773. instr : taicpu;
  774. begin
  775. if ref.addressmode<>AM_OFFSET then
  776. internalerror(200309071);
  777. tmpref:=ref;
  778. { Be sure to have a base register }
  779. if (tmpref.base=NR_NO) then
  780. begin
  781. if tmpref.shiftmode<>SM_None then
  782. internalerror(200308294);
  783. if tmpref.signindex<0 then
  784. internalerror(200312023);
  785. tmpref.base:=tmpref.index;
  786. tmpref.index:=NR_NO;
  787. end;
  788. if assigned(tmpref.symbol) or
  789. not((is_shifter_const(dword(tmpref.offset),b)) or
  790. (is_shifter_const(dword(-tmpref.offset),b))
  791. ) then
  792. fixref(list,tmpref);
  793. { expect a base here }
  794. if tmpref.base=NR_NO then
  795. internalerror(200312022);
  796. if tmpref.index<>NR_NO then
  797. begin
  798. if tmpref.shiftmode<>SM_None then
  799. internalerror(200312021);
  800. if tmpref.signindex<0 then
  801. a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
  802. else
  803. a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
  804. if tmpref.offset<>0 then
  805. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
  806. end
  807. else
  808. begin
  809. if tmpref.offset<>0 then
  810. a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
  811. else
  812. begin
  813. instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
  814. list.concat(instr);
  815. add_move_instruction(instr);
  816. end;
  817. end;
  818. reference_release(list,tmpref);
  819. end;
  820. procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
  821. var
  822. tmpreg : tregister;
  823. tmpref : treference;
  824. l : tasmlabel;
  825. begin
  826. { absolute symbols can't be handled directly, we've to store the symbol reference
  827. in the text segment and access it pc relative
  828. For now, we assume that references where base or index equals to PC are already
  829. relative, all other references are assumed to be absolute and thus they need
  830. to be handled extra.
  831. A proper solution would be to change refoptions to a set and store the information
  832. if the symbol is absolute or relative there.
  833. }
  834. { create consts entry }
  835. reference_reset(tmpref);
  836. objectlibrary.getlabel(l);
  837. cg.a_label(current_procinfo.aktlocaldata,l);
  838. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  839. if assigned(ref.symbol) then
  840. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  841. else
  842. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  843. { load consts entry }
  844. tmpreg:=getintregister(list,OS_INT);
  845. tmpref.symbol:=l;
  846. tmpref.base:=NR_PC;
  847. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  848. if (ref.base<>NR_NO) then
  849. begin
  850. if ref.index<>NR_NO then
  851. begin
  852. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  853. ref.base:=tmpreg;
  854. end
  855. else
  856. begin
  857. ref.index:=tmpreg;
  858. ref.shiftimm:=0;
  859. ref.signindex:=1;
  860. ref.shiftmode:=SM_None;
  861. end;
  862. end
  863. else
  864. ref.base:=tmpreg;
  865. ref.offset:=0;
  866. ref.symbol:=nil;
  867. end;
  868. procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
  869. var
  870. srcref,dstref:treference;
  871. srcreg,destreg,countreg,r:tregister;
  872. helpsize:aword;
  873. copysize:byte;
  874. cgsize:Tcgsize;
  875. procedure genloop(count : aword;size : byte);
  876. const
  877. size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
  878. var
  879. l : tasmlabel;
  880. begin
  881. objectlibrary.getlabel(l);
  882. a_load_const_reg(list,OS_INT,count,countreg);
  883. cg.a_label(list,l);
  884. srcref.addressmode:=AM_POSTINDEXED;
  885. dstref.addressmode:=AM_POSTINDEXED;
  886. srcref.offset:=size;
  887. dstref.offset:=size;
  888. r:=getintregister(list,size2opsize[size]);
  889. a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
  890. a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
  891. ungetregister(list,r);
  892. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
  893. list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
  894. { keep the registers alive }
  895. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  896. list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
  897. list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
  898. end;
  899. begin
  900. helpsize:=12;
  901. dstref:=dest;
  902. srcref:=source;
  903. if cs_littlesize in aktglobalswitches then
  904. helpsize:=8;
  905. if not loadref and (len<=helpsize) then
  906. begin
  907. copysize:=4;
  908. cgsize:=OS_32;
  909. while len<>0 do
  910. begin
  911. if len<2 then
  912. begin
  913. copysize:=1;
  914. cgsize:=OS_8;
  915. end
  916. else if len<4 then
  917. begin
  918. copysize:=2;
  919. cgsize:=OS_16;
  920. end;
  921. dec(len,copysize);
  922. r:=getintregister(list,cgsize);
  923. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  924. if (len=0) and delsource then
  925. reference_release(list,source);
  926. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  927. inc(srcref.offset,copysize);
  928. inc(dstref.offset,copysize);
  929. ungetregister(list,r);
  930. end;
  931. end
  932. else
  933. begin
  934. destreg:=getintregister(list,OS_ADDR);
  935. a_loadaddr_ref_reg(list,dest,destreg);
  936. reference_reset_base(dstref,destreg,0);
  937. srcreg:=getintregister(list,OS_ADDR);
  938. if loadref then
  939. a_load_ref_reg(list,OS_ADDR,OS_ADDR,source,srcreg)
  940. else
  941. a_loadaddr_ref_reg(list,source,srcreg);
  942. reference_reset_base(srcref,srcreg,0);
  943. if delsource then
  944. reference_release(list,source);
  945. countreg:=getintregister(list,OS_32);
  946. // if cs_littlesize in aktglobalswitches then
  947. genloop(len,1);
  948. {
  949. else
  950. begin
  951. helpsize:=len shr 2;
  952. len:=len and 3;
  953. if helpsize>1 then
  954. begin
  955. a_load_const_reg(list,OS_INT,helpsize,countreg);
  956. list.concat(Taicpu.op_none(A_REP,S_NO));
  957. end;
  958. if helpsize>0 then
  959. list.concat(Taicpu.op_none(A_MOVSD,S_NO));
  960. if len>1 then
  961. begin
  962. dec(len,2);
  963. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  964. end;
  965. if len=1 then
  966. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  967. end;
  968. }
  969. ungetregister(list,countreg);
  970. ungetregister(list,srcreg);
  971. ungetregister(list,destreg);
  972. end;
  973. if delsource then
  974. tg.ungetiftemp(list,source);
  975. end;
  976. procedure tcgarm.g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
  977. begin
  978. end;
  979. procedure tcgarm.g_save_standard_registers(list : taasmoutput);
  980. begin
  981. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  982. end;
  983. procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
  984. begin
  985. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  986. end;
  987. procedure tcgarm.g_save_all_registers(list : taasmoutput);
  988. begin
  989. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  990. end;
  991. procedure tcgarm.g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);
  992. begin
  993. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  994. end;
  995. procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  996. var
  997. ai : taicpu;
  998. begin
  999. ai:=Taicpu.Op_sym(A_B,l);
  1000. ai.SetCondition(OpCmp2AsmCond[cond]);
  1001. ai.is_jmp:=true;
  1002. list.concat(ai);
  1003. end;
  1004. procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  1005. var
  1006. tmpreg : tregister;
  1007. begin
  1008. case op of
  1009. OP_NEG:
  1010. begin
  1011. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
  1012. list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
  1013. end;
  1014. OP_NOT:
  1015. begin
  1016. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
  1017. cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
  1018. end;
  1019. else
  1020. a_op64_reg_reg_reg(list,op,regsrc,regdst,regdst);
  1021. end;
  1022. end;
  1023. procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
  1024. begin
  1025. a_op64_const_reg_reg(list,op,value,reg,reg);
  1026. end;
  1027. procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;regsrc,regdst : tregister64);
  1028. var
  1029. tmpreg : tregister;
  1030. b : byte;
  1031. begin
  1032. case op of
  1033. OP_AND,OP_OR,OP_XOR:
  1034. begin
  1035. cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
  1036. cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
  1037. end;
  1038. OP_ADD:
  1039. begin
  1040. if is_shifter_const(lo(value),b) then
  1041. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1042. else
  1043. begin
  1044. tmpreg:=cg.getintregister(list,OS_32);
  1045. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1046. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1047. cg.ungetregister(list,tmpreg);
  1048. end;
  1049. if is_shifter_const(hi(value),b) then
  1050. list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
  1051. else
  1052. begin
  1053. tmpreg:=cg.getintregister(list,OS_32);
  1054. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1055. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
  1056. cg.ungetregister(list,tmpreg);
  1057. end;
  1058. end;
  1059. OP_SUB:
  1060. begin
  1061. if is_shifter_const(lo(value),b) then
  1062. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1063. else
  1064. begin
  1065. tmpreg:=cg.getintregister(list,OS_32);
  1066. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1067. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1068. cg.ungetregister(list,tmpreg);
  1069. end;
  1070. if is_shifter_const(hi(value),b) then
  1071. list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
  1072. else
  1073. begin
  1074. tmpreg:=cg.getintregister(list,OS_32);
  1075. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1076. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
  1077. cg.ungetregister(list,tmpreg);
  1078. end;
  1079. end;
  1080. else
  1081. internalerror(2003083101);
  1082. end;
  1083. end;
  1084. procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
  1085. begin
  1086. case op of
  1087. OP_AND,OP_OR,OP_XOR:
  1088. begin
  1089. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
  1090. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
  1091. end;
  1092. OP_ADD:
  1093. begin
  1094. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1095. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
  1096. end;
  1097. OP_SUB:
  1098. begin
  1099. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1100. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
  1101. end;
  1102. else
  1103. internalerror(2003083101);
  1104. end;
  1105. end;
  1106. begin
  1107. cg:=tcgarm.create;
  1108. cg64:=tcg64farm.create;
  1109. end.
  1110. {
  1111. $Log$
  1112. Revision 1.42 2004-01-28 15:36:47 florian
  1113. * fixed another couple of arm bugs
  1114. Revision 1.41 2004/01/27 15:04:06 florian
  1115. * fixed code generation for math inl. nodes
  1116. * more code generator improvements
  1117. Revision 1.40 2004/01/26 19:05:56 florian
  1118. * fixed several arm issues
  1119. Revision 1.39 2004/01/24 20:19:46 florian
  1120. * fixed some spilling stuff
  1121. + not(<int64>) implemented
  1122. + small set comparisations implemented
  1123. Revision 1.38 2004/01/24 01:33:20 florian
  1124. * fixref fixed if index, base and offset were given
  1125. Revision 1.37 2004/01/22 20:13:18 florian
  1126. * fixed several issues with flags
  1127. Revision 1.36 2004/01/22 02:22:47 florian
  1128. * op_const_reg_reg with OP_SAR fixed
  1129. Revision 1.35 2004/01/22 01:47:15 florian
  1130. * improved register usage
  1131. + implemented second_cmp64bit
  1132. Revision 1.34 2004/01/21 19:01:03 florian
  1133. * fixed handling of max. distance of pc relative symbols
  1134. Revision 1.33 2004/01/21 15:41:56 florian
  1135. * fixed register allocator problems with concatcopy
  1136. Revision 1.32 2004/01/21 14:22:00 florian
  1137. + reintroduce implemented
  1138. Revision 1.31 2004/01/21 01:22:35 florian
  1139. * fixed a_cmp_const_reg_label
  1140. * fixed volatile register handling which was broken by my last patch
  1141. Revision 1.30 2004/01/20 23:18:00 florian
  1142. * fixed a_call_reg
  1143. + implemented paramgr.get_volative_registers
  1144. Revision 1.29 2003/12/26 14:02:30 peter
  1145. * sparc updates
  1146. * use registertype in spill_register
  1147. Revision 1.28 2003/12/18 17:06:21 florian
  1148. * arm compiler compilation fixed
  1149. Revision 1.27 2003/12/08 17:43:57 florian
  1150. * fixed ldm/stm arm assembler reading
  1151. * fixed a_load_reg_reg with OS_8 on ARM
  1152. * non supported calling conventions cause only a warning now
  1153. Revision 1.26 2003/12/03 17:39:05 florian
  1154. * fixed several arm calling conventions issues
  1155. * fixed reference reading in the assembler reader
  1156. * fixed a_loadaddr_ref_reg
  1157. Revision 1.25 2003/11/30 19:35:29 florian
  1158. * fixed several arm related problems
  1159. Revision 1.24 2003/11/24 15:17:37 florian
  1160. * changed some types to prevend range check errors
  1161. Revision 1.23 2003/11/21 16:29:26 florian
  1162. * fixed reading of reg. sets in the arm assembler reader
  1163. Revision 1.22 2003/11/07 15:58:32 florian
  1164. * Florian's culmutative nr. 1; contains:
  1165. - invalid calling conventions for a certain cpu are rejected
  1166. - arm softfloat calling conventions
  1167. - -Sp for cpu dependend code generation
  1168. - several arm fixes
  1169. - remaining code for value open array paras on heap
  1170. Revision 1.21 2003/11/02 14:30:03 florian
  1171. * fixed ARM for new reg. allocation scheme
  1172. Revision 1.20 2003/10/11 16:06:42 florian
  1173. * fixed some MMX<->SSE
  1174. * started to fix ppc, needs an overhaul
  1175. + stabs info improve for spilling, not sure if it works correctly/completly
  1176. - MMX_SUPPORT removed from Makefile.fpc
  1177. Revision 1.19 2003/09/11 11:55:00 florian
  1178. * improved arm code generation
  1179. * move some protected and private field around
  1180. * the temp. register for register parameters/arguments are now released
  1181. before the move to the parameter register is done. This improves
  1182. the code in a lot of cases.
  1183. Revision 1.18 2003/09/09 12:53:40 florian
  1184. * some assembling problems fixed
  1185. * improved loadaddr_ref_reg
  1186. Revision 1.17 2003/09/06 16:45:51 florian
  1187. * fixed exit code (no preindexed addressing mode in LDM)
  1188. Revision 1.16 2003/09/06 11:21:50 florian
  1189. * fixed stm and ldm to be usable with preindex operand
  1190. Revision 1.15 2003/09/05 23:57:01 florian
  1191. * arm is working again as before the new register naming scheme was implemented
  1192. Revision 1.14 2003/09/04 21:07:03 florian
  1193. * ARM compiler compiles again
  1194. Revision 1.13 2003/09/04 00:15:29 florian
  1195. * first bunch of adaptions of arm compiler for new register type
  1196. Revision 1.12 2003/09/03 19:10:30 florian
  1197. * initial revision of new register naming
  1198. Revision 1.11 2003/09/03 11:18:37 florian
  1199. * fixed arm concatcopy
  1200. + arm support in the common compiler sources added
  1201. * moved some generic cg code around
  1202. + tfputype added
  1203. * ...
  1204. Revision 1.10 2003/09/01 15:11:16 florian
  1205. * fixed reference handling
  1206. * fixed operand postfix for floating point instructions
  1207. * fixed wrong shifter constant handling
  1208. Revision 1.9 2003/09/01 09:54:57 florian
  1209. * results of work on arm port last weekend
  1210. Revision 1.8 2003/08/29 21:36:28 florian
  1211. * fixed procedure entry/exit code
  1212. * started to fix reference handling
  1213. Revision 1.7 2003/08/28 13:26:10 florian
  1214. * another couple of arm fixes
  1215. Revision 1.6 2003/08/28 00:05:29 florian
  1216. * today's arm patches
  1217. Revision 1.5 2003/08/25 23:20:38 florian
  1218. + started to implement FPU support for the ARM
  1219. * fixed a lot of other things
  1220. Revision 1.4 2003/08/24 12:27:26 florian
  1221. * continued to work on the arm port
  1222. Revision 1.3 2003/08/21 03:14:00 florian
  1223. * arm compiler can be compiled; far from being working
  1224. Revision 1.2 2003/08/20 15:50:12 florian
  1225. * more arm stuff
  1226. Revision 1.1 2003/07/21 16:35:30 florian
  1227. * very basic stuff for the arm
  1228. }