cgcpu.pas 47 KB

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