cgcpu.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  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. rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
  94. [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
  95. RS_R9,RS_R10,RS_R12],first_int_imreg,[]);
  96. rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  97. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
  98. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  99. [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
  100. end;
  101. procedure tcgarm.done_register_allocators;
  102. begin
  103. rg[R_INTREGISTER].free;
  104. rg[R_FPUREGISTER].free;
  105. rg[R_MMREGISTER].free;
  106. inherited done_register_allocators;
  107. end;
  108. procedure tcgarm.a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);
  109. var
  110. ref: treference;
  111. begin
  112. case locpara.loc of
  113. LOC_REGISTER,LOC_CREGISTER:
  114. a_load_const_reg(list,size,a,locpara.register);
  115. LOC_REFERENCE:
  116. begin
  117. reference_reset(ref);
  118. ref.base:=locpara.reference.index;
  119. ref.offset:=locpara.reference.offset;
  120. a_load_const_ref(list,size,a,ref);
  121. end;
  122. else
  123. internalerror(2002081101);
  124. end;
  125. if locpara.alignment<>0 then
  126. internalerror(2002081102);
  127. end;
  128. procedure tcgarm.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
  129. var
  130. ref: treference;
  131. tmpreg: tregister;
  132. begin
  133. case locpara.loc of
  134. LOC_REGISTER,LOC_CREGISTER:
  135. a_load_ref_reg(list,size,size,r,locpara.register);
  136. LOC_REFERENCE:
  137. begin
  138. reference_reset(ref);
  139. ref.base:=locpara.reference.index;
  140. ref.offset:=locpara.reference.offset;
  141. tmpreg := getintregister(list,size);
  142. a_load_ref_reg(list,size,size,r,tmpreg);
  143. a_load_reg_ref(list,size,size,tmpreg,ref);
  144. ungetregister(list,tmpreg);
  145. end;
  146. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  147. case size of
  148. OS_F32, OS_F64:
  149. a_loadfpu_ref_reg(list,size,r,locpara.register);
  150. else
  151. internalerror(2002072801);
  152. end;
  153. else
  154. internalerror(2002081103);
  155. end;
  156. if locpara.alignment<>0 then
  157. internalerror(2002081104);
  158. end;
  159. procedure tcgarm.a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  160. var
  161. ref: treference;
  162. tmpreg: tregister;
  163. begin
  164. case locpara.loc of
  165. LOC_REGISTER,LOC_CREGISTER:
  166. a_loadaddr_ref_reg(list,r,locpara.register);
  167. LOC_REFERENCE:
  168. begin
  169. reference_reset(ref);
  170. ref.base := locpara.reference.index;
  171. ref.offset := locpara.reference.offset;
  172. tmpreg := getintregister(list,OS_ADDR);
  173. a_loadaddr_ref_reg(list,r,tmpreg);
  174. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  175. ungetregister(list,tmpreg);
  176. end;
  177. else
  178. internalerror(2002080701);
  179. end;
  180. end;
  181. procedure tcgarm.a_call_name(list : taasmoutput;const s : string);
  182. begin
  183. list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s)));
  184. if not(pi_do_call in current_procinfo.flags) then
  185. internalerror(2003060703);
  186. end;
  187. procedure tcgarm.a_call_reg(list : taasmoutput;reg: tregister);
  188. var
  189. r : tregister;
  190. begin
  191. list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
  192. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
  193. if not(pi_do_call in current_procinfo.flags) then
  194. internalerror(2003060704);
  195. end;
  196. procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister);
  197. begin
  198. a_op_const_reg_reg(list,op,size,a,reg,reg);
  199. end;
  200. procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  201. begin
  202. case op of
  203. OP_NEG:
  204. list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
  205. OP_NOT:
  206. list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
  207. else
  208. a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
  209. end;
  210. end;
  211. const
  212. op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
  213. (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
  214. A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
  215. procedure tcgarm.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  216. size: tcgsize; a: aword; src, dst: tregister);
  217. var
  218. shift : byte;
  219. tmpreg : tregister;
  220. so : tshifterop;
  221. begin
  222. if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
  223. case op of
  224. OP_NEG,OP_NOT,
  225. OP_DIV,OP_IDIV:
  226. internalerror(200308281);
  227. OP_SHL:
  228. begin
  229. if a>32 then
  230. internalerror(200308291);
  231. shifterop_reset(so);
  232. so.shiftmode:=SM_LSL;
  233. so.shiftimm:=a;
  234. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  235. end;
  236. OP_SHR:
  237. begin
  238. if a>32 then
  239. internalerror(200308292);
  240. shifterop_reset(so);
  241. so.shiftmode:=SM_LSR;
  242. so.shiftimm:=a;
  243. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  244. end;
  245. OP_SAR:
  246. begin
  247. if a>32 then
  248. internalerror(200308291);
  249. shifterop_reset(so);
  250. so.shiftmode:=SM_LSL;
  251. so.shiftimm:=a;
  252. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  253. end;
  254. else
  255. list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a));
  256. end
  257. else
  258. begin
  259. { there could be added some more sophisticated optimizations }
  260. if (op in [OP_MUL,OP_IMUL]) and (a=1) then
  261. a_load_reg_reg(list,size,size,src,dst)
  262. else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
  263. a_load_const_reg(list,size,0,dst)
  264. else if (op in [OP_IMUL]) and (a=-1) then
  265. a_op_reg_reg(list,OP_NEG,size,src,dst)
  266. else
  267. begin
  268. tmpreg:=getintregister(list,size);
  269. a_load_const_reg(list,size,a,tmpreg);
  270. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  271. ungetregister(list,tmpreg);
  272. end;
  273. end;
  274. end;
  275. procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  276. size: tcgsize; src1, src2, dst: tregister);
  277. var
  278. so : tshifterop;
  279. tmpreg : tregister;
  280. begin
  281. case op of
  282. OP_NEG,OP_NOT,
  283. OP_DIV,OP_IDIV:
  284. internalerror(200308281);
  285. OP_SHL:
  286. begin
  287. shifterop_reset(so);
  288. so.rs:=src1;
  289. so.shiftmode:=SM_LSL;
  290. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  291. end;
  292. OP_SHR:
  293. begin
  294. shifterop_reset(so);
  295. so.rs:=src1;
  296. so.shiftmode:=SM_LSR;
  297. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  298. end;
  299. OP_SAR:
  300. begin
  301. shifterop_reset(so);
  302. so.rs:=src1;
  303. so.shiftmode:=SM_ASR;
  304. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  305. end;
  306. OP_IMUL,
  307. OP_MUL:
  308. begin
  309. { the arm doesn't allow that rd and rm are the same }
  310. if dst=src2 then
  311. begin
  312. if dst<>src1 then
  313. begin
  314. rg[R_INTREGISTER].add_edge(getsupreg(dst),getsupreg(src1));
  315. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2));
  316. end
  317. else
  318. begin
  319. tmpreg:=getintregister(list,size);
  320. a_load_reg_reg(list,size,size,src2,dst);
  321. rg[R_INTREGISTER].add_edge(getsupreg(dst),getsupreg(tmpreg));
  322. ungetregister(list,tmpreg);
  323. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
  324. end;
  325. end
  326. else
  327. begin
  328. rg[R_INTREGISTER].add_edge(getsupreg(dst),getsupreg(src2));
  329. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
  330. end;
  331. end;
  332. else
  333. list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
  334. end;
  335. end;
  336. function rotl(d : dword;b : byte) : dword;
  337. begin
  338. result:=(d shr (32-b)) or (d shl b);
  339. end;
  340. function is_shifter_const(d : dword;var imm_shift : byte) : boolean;
  341. var
  342. i : longint;
  343. begin
  344. for i:=0 to 15 do
  345. begin
  346. if (d and not(rotl($ff,i*2)))=0 then
  347. begin
  348. imm_shift:=i*2;
  349. result:=true;
  350. exit;
  351. end;
  352. end;
  353. result:=false;
  354. end;
  355. procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);
  356. var
  357. imm_shift : byte;
  358. l : tasmlabel;
  359. hr : treference;
  360. begin
  361. if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
  362. internalerror(2002090902);
  363. if is_shifter_const(dword(a),imm_shift) then
  364. list.concat(taicpu.op_reg_const(A_MOV,reg,a))
  365. else if is_shifter_const(dword(not(a)),imm_shift) then
  366. list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
  367. else
  368. begin
  369. objectlibrary.getdatalabel(l);
  370. current_procinfo.aktlocaldata.concat(tai_symbol.Create(l,0));
  371. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
  372. reference_reset(hr);
  373. hr.symbol:=l;
  374. list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
  375. end;
  376. end;
  377. procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  378. var
  379. tmpreg : tregister;
  380. tmpref : treference;
  381. l : tasmlabel;
  382. begin
  383. tmpreg:=NR_NO;
  384. { Be sure to have a base register }
  385. if (ref.base=NR_NO) then
  386. begin
  387. if ref.shiftmode<>SM_None then
  388. internalerror(200308294);
  389. ref.base:=ref.index;
  390. ref.index:=NR_NO;
  391. end;
  392. { absolute symbols can't be handled directly, we've to store the symbol reference
  393. in the text segment and access it pc relative
  394. For now, we assume that references where base or index equals to PC are already
  395. relative, all other references are assumed to be absolute and thus they need
  396. to be handled extra.
  397. A proper solution would be to change refoptions to a set and store the information
  398. if the symbol is absolute or relative there.
  399. }
  400. if (assigned(ref.symbol) and
  401. not(is_pc(ref.base)) and
  402. not(is_pc(ref.index))
  403. ) or
  404. (ref.offset<-4095) or
  405. (ref.offset>4095) or
  406. ((oppostfix in [PF_SB,PF_H,PF_SH]) and
  407. ((ref.offset<-255) or
  408. (ref.offset>255)
  409. )
  410. ) then
  411. begin
  412. { check consts distance }
  413. { !!!! }
  414. { create consts entry }
  415. objectlibrary.getdatalabel(l);
  416. current_procinfo.aktlocaldata.concat(Tai_symbol.Create(l,0));
  417. if assigned(ref.symbol) then
  418. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  419. else
  420. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  421. { load consts entry }
  422. tmpreg:=getintregister(list,OS_INT);
  423. reference_reset(tmpref);
  424. tmpref.symbol:=l;
  425. tmpref.base:=NR_R15;
  426. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  427. if (ref.base<>NR_NO) then
  428. begin
  429. if ref.index<>NR_NO then
  430. begin
  431. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  432. ref.base:=tmpreg;
  433. end
  434. else
  435. begin
  436. ref.index:=tmpreg;
  437. ref.shiftimm:=0;
  438. ref.signindex:=1;
  439. ref.shiftmode:=SM_None;
  440. end;
  441. end
  442. else
  443. ref.base:=tmpreg;
  444. ref.offset:=0;
  445. ref.symbol:=nil;
  446. end;
  447. { floating point operations have only limited references
  448. we expect here, that a base is already set }
  449. if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
  450. begin
  451. if ref.shiftmode<>SM_none then
  452. internalerror(200309121);
  453. if tmpreg<>NR_NO then
  454. begin
  455. if ref.base=tmpreg then
  456. begin
  457. if ref.signindex<0 then
  458. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index))
  459. else
  460. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index));
  461. ref.index:=NR_NO;
  462. end
  463. else
  464. begin
  465. if ref.signindex<0 then
  466. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.base))
  467. else
  468. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.base));
  469. ref.index:=NR_NO;
  470. ref.index:=tmpreg;
  471. end;
  472. end
  473. else
  474. begin
  475. tmpreg:=getintregister(list,OS_INT);
  476. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  477. ref.base:=tmpreg;
  478. ref.index:=NR_NO;
  479. end;
  480. end;
  481. list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
  482. if (tmpreg<>NR_NO) then
  483. ungetregister(list,tmpreg);
  484. end;
  485. procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  486. var
  487. oppostfix:toppostfix;
  488. begin
  489. case ToSize of
  490. { signed integer registers }
  491. OS_8,
  492. OS_S8:
  493. oppostfix:=PF_B;
  494. OS_16,
  495. OS_S16:
  496. oppostfix:=PF_H;
  497. OS_32,
  498. OS_S32:
  499. oppostfix:=PF_None;
  500. else
  501. InternalError(200308295);
  502. end;
  503. handle_load_store(list,A_STR,oppostfix,reg,ref);
  504. end;
  505. procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
  506. var
  507. oppostfix:toppostfix;
  508. begin
  509. case FromSize of
  510. { signed integer registers }
  511. OS_8:
  512. oppostfix:=PF_B;
  513. OS_S8:
  514. oppostfix:=PF_SB;
  515. OS_16:
  516. oppostfix:=PF_H;
  517. OS_S16:
  518. oppostfix:=PF_SH;
  519. OS_32,
  520. OS_S32:
  521. oppostfix:=PF_None;
  522. else
  523. InternalError(200308291);
  524. end;
  525. handle_load_store(list,A_LDR,oppostfix,reg,ref);
  526. end;
  527. procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  528. var
  529. instr: taicpu;
  530. so : tshifterop;
  531. begin
  532. shifterop_reset(so);
  533. if (reg1<>reg2) or
  534. (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  535. ((tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  536. (tosize <> fromsize) and
  537. not(fromsize in [OS_32,OS_S32])) then
  538. begin
  539. case tosize of
  540. OS_8:
  541. list.concat(taicpu.op_reg_reg_const(A_AND,
  542. reg2,reg1,$ff));
  543. OS_S8:
  544. begin
  545. so.shiftmode:=SM_LSL;
  546. so.shiftimm:=24;
  547. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  548. so.shiftmode:=SM_ASR;
  549. so.shiftimm:=24;
  550. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  551. end;
  552. OS_16:
  553. begin
  554. so.shiftmode:=SM_LSL;
  555. so.shiftimm:=16;
  556. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  557. so.shiftmode:=SM_LSR;
  558. so.shiftimm:=16;
  559. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  560. end;
  561. OS_S16:
  562. begin
  563. so.shiftmode:=SM_LSL;
  564. so.shiftimm:=16;
  565. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  566. so.shiftmode:=SM_ASR;
  567. so.shiftimm:=16;
  568. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  569. end;
  570. OS_32,OS_S32:
  571. begin
  572. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  573. list.concat(instr);
  574. add_move_instruction(instr);
  575. end;
  576. else internalerror(2002090901);
  577. end;
  578. end;
  579. end;
  580. procedure tcgarm.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
  581. begin
  582. list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
  583. end;
  584. procedure tcgarm.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  585. var
  586. oppostfix:toppostfix;
  587. begin
  588. case size of
  589. OS_F32:
  590. oppostfix:=PF_S;
  591. OS_F64:
  592. oppostfix:=PF_D;
  593. OS_F80:
  594. oppostfix:=PF_E;
  595. else
  596. InternalError(200309021);
  597. end;
  598. handle_load_store(list,A_LDF,oppostfix,reg,ref);
  599. end;
  600. procedure tcgarm.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  601. var
  602. oppostfix:toppostfix;
  603. begin
  604. case size of
  605. OS_F32:
  606. oppostfix:=PF_S;
  607. OS_F64:
  608. oppostfix:=PF_D;
  609. OS_F80:
  610. oppostfix:=PF_E;
  611. else
  612. InternalError(200309021);
  613. end;
  614. handle_load_store(list,A_STF,oppostfix,reg,ref);
  615. end;
  616. { comparison operations }
  617. procedure tcgarm.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  618. l : tasmlabel);
  619. var
  620. tmpreg : tregister;
  621. b : byte;
  622. begin
  623. if is_shifter_const(a,b) then
  624. list.concat(taicpu.op_reg_const(A_CMP,reg,a))
  625. { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
  626. and CMP reg,$7fffffff regarding the flags according to the ARM manual }
  627. else if is_shifter_const(not(a),b) and (a<>$7fffffff) and (a<>$ffffffff) then
  628. list.concat(taicpu.op_reg_const(A_CMN,reg,not(a)))
  629. else
  630. begin
  631. tmpreg:=getintregister(list,size);
  632. a_load_const_reg(list,size,a,tmpreg);
  633. list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
  634. ungetregister(list,tmpreg);
  635. end;
  636. a_jmp_cond(list,cmp_op,l);
  637. end;
  638. procedure tcgarm.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  639. begin
  640. list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
  641. a_jmp_cond(list,cmp_op,l);
  642. end;
  643. procedure tcgarm.a_jmp_always(list : taasmoutput;l: tasmlabel);
  644. begin
  645. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(l.name)));
  646. end;
  647. procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  648. var
  649. ai : taicpu;
  650. begin
  651. ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
  652. ai.is_jmp:=true;
  653. list.concat(ai);
  654. end;
  655. procedure tcgarm.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
  656. var
  657. ai : taicpu;
  658. begin
  659. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
  660. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond[flags_to_cond(f)]));
  661. end;
  662. procedure tcgarm.g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);
  663. begin
  664. end;
  665. procedure tcgarm.g_stackframe_entry(list : taasmoutput;localsize : longint);
  666. var
  667. ref : treference;
  668. shift : byte;
  669. begin
  670. LocalSize:=align(LocalSize,4);
  671. a_reg_alloc(list,NR_STACK_POINTER_REG);
  672. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  673. a_reg_alloc(list,NR_R12);
  674. list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
  675. { save int registers }
  676. reference_reset(ref);
  677. ref.index:=NR_STACK_POINTER_REG;
  678. ref.addressmode:=AM_PREINDEXED;
  679. 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));
  680. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
  681. { allocate necessary stack size }
  682. { don't use a_op_const_reg_reg here because we don't allow register allocations
  683. in the entry/exit code }
  684. if not(is_shifter_const(localsize,shift)) then
  685. begin
  686. a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
  687. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
  688. a_reg_dealloc(list,NR_R12);
  689. end
  690. else
  691. begin
  692. a_reg_dealloc(list,NR_R12);
  693. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
  694. end;
  695. end;
  696. procedure tcgarm.g_return_from_proc(list : taasmoutput;parasize : aword);
  697. var
  698. ref : treference;
  699. begin
  700. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  701. list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
  702. else
  703. begin
  704. { restore int registers and return }
  705. reference_reset(ref);
  706. ref.index:=NR_FRAME_POINTER_REG;
  707. 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));
  708. end;
  709. end;
  710. procedure tcgarm.g_restore_frame_pointer(list : taasmoutput);
  711. begin
  712. { the frame pointer on the ARM is restored while the ret is executed }
  713. end;
  714. procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  715. var
  716. b : byte;
  717. tmpref : treference;
  718. instr : taicpu;
  719. begin
  720. if ref.addressmode<>AM_OFFSET then
  721. internalerror(200309071);
  722. tmpref:=ref;
  723. { Be sure to have a base register }
  724. if (tmpref.base=NR_NO) then
  725. begin
  726. if tmpref.shiftmode<>SM_None then
  727. internalerror(200308294);
  728. if tmpref.signindex<0 then
  729. internalerror(200312023);
  730. tmpref.base:=tmpref.index;
  731. tmpref.index:=NR_NO;
  732. end;
  733. if assigned(tmpref.symbol) or
  734. not((is_shifter_const(dword(tmpref.offset),b)) or
  735. (is_shifter_const(dword(-tmpref.offset),b))
  736. ) then
  737. fixref(list,tmpref);
  738. { expect a base here }
  739. if tmpref.base=NR_NO then
  740. internalerror(200312022);
  741. if tmpref.index<>NR_NO then
  742. begin
  743. if tmpref.shiftmode<>SM_None then
  744. internalerror(200312021);
  745. if tmpref.signindex<0 then
  746. list.concat(taicpu.op_reg_reg_reg(A_SUB,r,tmpref.base,tmpref.index))
  747. else
  748. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,tmpref.base,tmpref.index));
  749. if tmpref.offset>0 then
  750. list.concat(taicpu.op_reg_reg_const(A_ADD,r,r,tmpref.offset))
  751. else if tmpref.offset<0 then
  752. list.concat(taicpu.op_reg_reg_const(A_SUB,r,r,-tmpref.offset));
  753. end
  754. else
  755. begin
  756. if tmpref.offset>0 then
  757. list.concat(taicpu.op_reg_reg_const(A_ADD,r,tmpref.base,tmpref.offset))
  758. else if tmpref.offset<0 then
  759. list.concat(taicpu.op_reg_reg_const(A_SUB,r,tmpref.base,-tmpref.offset))
  760. else
  761. begin
  762. instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
  763. list.concat(instr);
  764. add_move_instruction(instr);
  765. end;
  766. end;
  767. reference_release(list,tmpref);
  768. end;
  769. procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
  770. var
  771. tmpreg : tregister;
  772. tmpref : treference;
  773. l : tasmlabel;
  774. begin
  775. { absolute symbols can't be handled directly, we've to store the symbol reference
  776. in the text segment and access it pc relative
  777. For now, we assume that references where base or index equals to PC are already
  778. relative, all other references are assumed to be absolute and thus they need
  779. to be handled extra.
  780. A proper solution would be to change refoptions to a set and store the information
  781. if the symbol is absolute or relative there.
  782. }
  783. { check consts distance }
  784. {!!!!!}
  785. { create consts entry }
  786. objectlibrary.getdatalabel(l);
  787. current_procinfo.aktlocaldata.concat(Tai_symbol.Create(l,0));
  788. if assigned(ref.symbol) then
  789. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  790. else
  791. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  792. { load consts entry }
  793. reference_reset(tmpref);
  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.33 2004-01-21 15:41:56 florian
  1058. * fixed register allocator problems with concatcopy
  1059. Revision 1.32 2004/01/21 14:22:00 florian
  1060. + reintroduce implemented
  1061. Revision 1.31 2004/01/21 01:22:35 florian
  1062. * fixed a_cmp_const_reg_label
  1063. * fixed volatile register handling which was broken by my last patch
  1064. Revision 1.30 2004/01/20 23:18:00 florian
  1065. * fixed a_call_reg
  1066. + implemented paramgr.get_volative_registers
  1067. Revision 1.29 2003/12/26 14:02:30 peter
  1068. * sparc updates
  1069. * use registertype in spill_register
  1070. Revision 1.28 2003/12/18 17:06:21 florian
  1071. * arm compiler compilation fixed
  1072. Revision 1.27 2003/12/08 17:43:57 florian
  1073. * fixed ldm/stm arm assembler reading
  1074. * fixed a_load_reg_reg with OS_8 on ARM
  1075. * non supported calling conventions cause only a warning now
  1076. Revision 1.26 2003/12/03 17:39:05 florian
  1077. * fixed several arm calling conventions issues
  1078. * fixed reference reading in the assembler reader
  1079. * fixed a_loadaddr_ref_reg
  1080. Revision 1.25 2003/11/30 19:35:29 florian
  1081. * fixed several arm related problems
  1082. Revision 1.24 2003/11/24 15:17:37 florian
  1083. * changed some types to prevend range check errors
  1084. Revision 1.23 2003/11/21 16:29:26 florian
  1085. * fixed reading of reg. sets in the arm assembler reader
  1086. Revision 1.22 2003/11/07 15:58:32 florian
  1087. * Florian's culmutative nr. 1; contains:
  1088. - invalid calling conventions for a certain cpu are rejected
  1089. - arm softfloat calling conventions
  1090. - -Sp for cpu dependend code generation
  1091. - several arm fixes
  1092. - remaining code for value open array paras on heap
  1093. Revision 1.21 2003/11/02 14:30:03 florian
  1094. * fixed ARM for new reg. allocation scheme
  1095. Revision 1.20 2003/10/11 16:06:42 florian
  1096. * fixed some MMX<->SSE
  1097. * started to fix ppc, needs an overhaul
  1098. + stabs info improve for spilling, not sure if it works correctly/completly
  1099. - MMX_SUPPORT removed from Makefile.fpc
  1100. Revision 1.19 2003/09/11 11:55:00 florian
  1101. * improved arm code generation
  1102. * move some protected and private field around
  1103. * the temp. register for register parameters/arguments are now released
  1104. before the move to the parameter register is done. This improves
  1105. the code in a lot of cases.
  1106. Revision 1.18 2003/09/09 12:53:40 florian
  1107. * some assembling problems fixed
  1108. * improved loadaddr_ref_reg
  1109. Revision 1.17 2003/09/06 16:45:51 florian
  1110. * fixed exit code (no preindexed addressing mode in LDM)
  1111. Revision 1.16 2003/09/06 11:21:50 florian
  1112. * fixed stm and ldm to be usable with preindex operand
  1113. Revision 1.15 2003/09/05 23:57:01 florian
  1114. * arm is working again as before the new register naming scheme was implemented
  1115. Revision 1.14 2003/09/04 21:07:03 florian
  1116. * ARM compiler compiles again
  1117. Revision 1.13 2003/09/04 00:15:29 florian
  1118. * first bunch of adaptions of arm compiler for new register type
  1119. Revision 1.12 2003/09/03 19:10:30 florian
  1120. * initial revision of new register naming
  1121. Revision 1.11 2003/09/03 11:18:37 florian
  1122. * fixed arm concatcopy
  1123. + arm support in the common compiler sources added
  1124. * moved some generic cg code around
  1125. + tfputype added
  1126. * ...
  1127. Revision 1.10 2003/09/01 15:11:16 florian
  1128. * fixed reference handling
  1129. * fixed operand postfix for floating point instructions
  1130. * fixed wrong shifter constant handling
  1131. Revision 1.9 2003/09/01 09:54:57 florian
  1132. * results of work on arm port last weekend
  1133. Revision 1.8 2003/08/29 21:36:28 florian
  1134. * fixed procedure entry/exit code
  1135. * started to fix reference handling
  1136. Revision 1.7 2003/08/28 13:26:10 florian
  1137. * another couple of arm fixes
  1138. Revision 1.6 2003/08/28 00:05:29 florian
  1139. * today's arm patches
  1140. Revision 1.5 2003/08/25 23:20:38 florian
  1141. + started to implement FPU support for the ARM
  1142. * fixed a lot of other things
  1143. Revision 1.4 2003/08/24 12:27:26 florian
  1144. * continued to work on the arm port
  1145. Revision 1.3 2003/08/21 03:14:00 florian
  1146. * arm compiler can be compiled; far from being working
  1147. Revision 1.2 2003/08/20 15:50:12 florian
  1148. * more arm stuff
  1149. Revision 1.1 2003/07/21 16:35:30 florian
  1150. * very basic stuff for the arm
  1151. }