cgcpu.pas 48 KB

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