cgcpu.pas 48 KB

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