cgcpu.pas 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  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. reference_reset(hr);
  370. objectlibrary.getlabel(l);
  371. cg.a_label(current_procinfo.aktlocaldata,l);
  372. hr.symboldata:=current_procinfo.aktlocaldata.last;
  373. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
  374. hr.symbol:=l;
  375. list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
  376. end;
  377. end;
  378. procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  379. var
  380. tmpreg : tregister;
  381. tmpref : treference;
  382. l : tasmlabel;
  383. begin
  384. tmpreg:=NR_NO;
  385. { Be sure to have a base register }
  386. if (ref.base=NR_NO) then
  387. begin
  388. if ref.shiftmode<>SM_None then
  389. internalerror(200308294);
  390. ref.base:=ref.index;
  391. ref.index:=NR_NO;
  392. end;
  393. { absolute symbols can't be handled directly, we've to store the symbol reference
  394. in the text segment and access it pc relative
  395. For now, we assume that references where base or index equals to PC are already
  396. relative, all other references are assumed to be absolute and thus they need
  397. to be handled extra.
  398. A proper solution would be to change refoptions to a set and store the information
  399. if the symbol is absolute or relative there.
  400. }
  401. if (assigned(ref.symbol) and
  402. not(is_pc(ref.base)) and
  403. not(is_pc(ref.index))
  404. ) or
  405. (ref.offset<-4095) or
  406. (ref.offset>4095) or
  407. ((oppostfix in [PF_SB,PF_H,PF_SH]) and
  408. ((ref.offset<-255) or
  409. (ref.offset>255)
  410. )
  411. ) then
  412. begin
  413. reference_reset(tmpref);
  414. { create consts entry }
  415. objectlibrary.getlabel(l);
  416. cg.a_label(current_procinfo.aktlocaldata,l);
  417. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  418. if assigned(ref.symbol) then
  419. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  420. else
  421. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  422. { load consts entry }
  423. tmpreg:=getintregister(list,OS_INT);
  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. { create consts entry }
  784. reference_reset(tmpref);
  785. objectlibrary.getlabel(l);
  786. cg.a_label(current_procinfo.aktlocaldata,l);
  787. tmpref.symboldata:=current_procinfo.aktlocaldata.last;
  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. tmpreg:=getintregister(list,OS_INT);
  794. tmpref.symbol:=l;
  795. tmpref.base:=NR_PC;
  796. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  797. if (ref.base<>NR_NO) then
  798. begin
  799. if ref.index<>NR_NO then
  800. begin
  801. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  802. ref.base:=tmpreg;
  803. end
  804. else
  805. begin
  806. ref.index:=tmpreg;
  807. ref.shiftimm:=0;
  808. ref.signindex:=1;
  809. ref.shiftmode:=SM_None;
  810. end;
  811. end
  812. else
  813. ref.base:=tmpreg;
  814. ref.offset:=0;
  815. ref.symbol:=nil;
  816. end;
  817. procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
  818. var
  819. srcref,dstref:treference;
  820. srcreg,destreg,countreg,r:tregister;
  821. helpsize:aword;
  822. copysize:byte;
  823. cgsize:Tcgsize;
  824. procedure genloop(count : aword;size : byte);
  825. const
  826. size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
  827. var
  828. l : tasmlabel;
  829. begin
  830. objectlibrary.getlabel(l);
  831. a_load_const_reg(list,OS_INT,count,countreg);
  832. cg.a_label(list,l);
  833. srcref.addressmode:=AM_POSTINDEXED;
  834. dstref.addressmode:=AM_POSTINDEXED;
  835. srcref.offset:=size;
  836. dstref.offset:=size;
  837. r:=getintregister(list,size2opsize[size]);
  838. a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
  839. a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
  840. ungetregister(list,r);
  841. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
  842. list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
  843. { keep the registers alive }
  844. list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
  845. list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
  846. list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
  847. end;
  848. begin
  849. helpsize:=12;
  850. dstref:=dest;
  851. srcref:=source;
  852. if cs_littlesize in aktglobalswitches then
  853. helpsize:=8;
  854. if not loadref and (len<=helpsize) then
  855. begin
  856. copysize:=4;
  857. cgsize:=OS_32;
  858. while len<>0 do
  859. begin
  860. if len<2 then
  861. begin
  862. copysize:=1;
  863. cgsize:=OS_8;
  864. end
  865. else if len<4 then
  866. begin
  867. copysize:=2;
  868. cgsize:=OS_16;
  869. end;
  870. dec(len,copysize);
  871. r:=getintregister(list,cgsize);
  872. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  873. if (len=0) and delsource then
  874. reference_release(list,source);
  875. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  876. inc(srcref.offset,copysize);
  877. inc(dstref.offset,copysize);
  878. ungetregister(list,r);
  879. end;
  880. end
  881. else
  882. begin
  883. destreg:=getintregister(list,OS_ADDR);
  884. a_loadaddr_ref_reg(list,dest,destreg);
  885. reference_reset_base(dstref,destreg,0);
  886. srcreg:=getintregister(list,OS_ADDR);
  887. if loadref then
  888. a_load_ref_reg(list,OS_ADDR,OS_ADDR,source,srcreg)
  889. else
  890. a_loadaddr_ref_reg(list,source,srcreg);
  891. reference_reset_base(srcref,srcreg,0);
  892. if delsource then
  893. reference_release(list,source);
  894. countreg:=getintregister(list,OS_32);
  895. // if cs_littlesize in aktglobalswitches then
  896. genloop(len,1);
  897. {
  898. else
  899. begin
  900. helpsize:=len shr 2;
  901. len:=len and 3;
  902. if helpsize>1 then
  903. begin
  904. a_load_const_reg(list,OS_INT,helpsize,countreg);
  905. list.concat(Taicpu.op_none(A_REP,S_NO));
  906. end;
  907. if helpsize>0 then
  908. list.concat(Taicpu.op_none(A_MOVSD,S_NO));
  909. if len>1 then
  910. begin
  911. dec(len,2);
  912. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  913. end;
  914. if len=1 then
  915. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  916. end;
  917. }
  918. ungetregister(list,countreg);
  919. ungetregister(list,srcreg);
  920. ungetregister(list,destreg);
  921. end;
  922. if delsource then
  923. tg.ungetiftemp(list,source);
  924. end;
  925. procedure tcgarm.g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
  926. begin
  927. end;
  928. procedure tcgarm.g_save_standard_registers(list : taasmoutput);
  929. begin
  930. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  931. end;
  932. procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
  933. begin
  934. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  935. end;
  936. procedure tcgarm.g_save_all_registers(list : taasmoutput);
  937. begin
  938. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  939. end;
  940. procedure tcgarm.g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);
  941. begin
  942. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  943. end;
  944. procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  945. var
  946. ai : taicpu;
  947. begin
  948. ai:=Taicpu.Op_sym(A_B,l);
  949. ai.SetCondition(OpCmp2AsmCond[cond]);
  950. ai.is_jmp:=true;
  951. list.concat(ai);
  952. end;
  953. procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  954. var
  955. tmpreg : tregister;
  956. begin
  957. case op of
  958. OP_NEG:
  959. begin
  960. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
  961. list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
  962. end;
  963. else
  964. a_op64_reg_reg_reg(list,op,regsrc,regdst,regdst);
  965. end;
  966. end;
  967. procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
  968. begin
  969. a_op64_const_reg_reg(list,op,value,reg,reg);
  970. end;
  971. procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;regsrc,regdst : tregister64);
  972. var
  973. tmpreg : tregister;
  974. b : byte;
  975. begin
  976. case op of
  977. OP_AND,OP_OR,OP_XOR:
  978. begin
  979. cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
  980. cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
  981. end;
  982. OP_ADD:
  983. begin
  984. if is_shifter_const(lo(value),b) then
  985. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  986. else
  987. begin
  988. tmpreg:=cg.getintregister(list,OS_32);
  989. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  990. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  991. cg.ungetregister(list,tmpreg);
  992. end;
  993. if is_shifter_const(hi(value),b) then
  994. list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
  995. else
  996. begin
  997. tmpreg:=cg.getintregister(list,OS_32);
  998. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  999. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
  1000. cg.ungetregister(list,tmpreg);
  1001. end;
  1002. end;
  1003. OP_SUB:
  1004. begin
  1005. if is_shifter_const(lo(value),b) then
  1006. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1007. else
  1008. begin
  1009. tmpreg:=cg.getintregister(list,OS_32);
  1010. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1011. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1012. cg.ungetregister(list,tmpreg);
  1013. end;
  1014. if is_shifter_const(hi(value),b) then
  1015. list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
  1016. else
  1017. begin
  1018. tmpreg:=cg.getintregister(list,OS_32);
  1019. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1020. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
  1021. cg.ungetregister(list,tmpreg);
  1022. end;
  1023. end;
  1024. else
  1025. internalerror(2003083101);
  1026. end;
  1027. end;
  1028. procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
  1029. begin
  1030. case op of
  1031. OP_AND,OP_OR,OP_XOR:
  1032. begin
  1033. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
  1034. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
  1035. end;
  1036. OP_ADD:
  1037. begin
  1038. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1039. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
  1040. end;
  1041. OP_SUB:
  1042. begin
  1043. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1044. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
  1045. end;
  1046. else
  1047. internalerror(2003083101);
  1048. end;
  1049. end;
  1050. begin
  1051. cg:=tcgarm.create;
  1052. cg64:=tcg64farm.create;
  1053. end.
  1054. {
  1055. $Log$
  1056. Revision 1.34 2004-01-21 19:01:03 florian
  1057. * fixed handling of max. distance of pc relative symbols
  1058. Revision 1.33 2004/01/21 15:41:56 florian
  1059. * fixed register allocator problems with concatcopy
  1060. Revision 1.32 2004/01/21 14:22:00 florian
  1061. + reintroduce implemented
  1062. Revision 1.31 2004/01/21 01:22:35 florian
  1063. * fixed a_cmp_const_reg_label
  1064. * fixed volatile register handling which was broken by my last patch
  1065. Revision 1.30 2004/01/20 23:18:00 florian
  1066. * fixed a_call_reg
  1067. + implemented paramgr.get_volative_registers
  1068. Revision 1.29 2003/12/26 14:02:30 peter
  1069. * sparc updates
  1070. * use registertype in spill_register
  1071. Revision 1.28 2003/12/18 17:06:21 florian
  1072. * arm compiler compilation fixed
  1073. Revision 1.27 2003/12/08 17:43:57 florian
  1074. * fixed ldm/stm arm assembler reading
  1075. * fixed a_load_reg_reg with OS_8 on ARM
  1076. * non supported calling conventions cause only a warning now
  1077. Revision 1.26 2003/12/03 17:39:05 florian
  1078. * fixed several arm calling conventions issues
  1079. * fixed reference reading in the assembler reader
  1080. * fixed a_loadaddr_ref_reg
  1081. Revision 1.25 2003/11/30 19:35:29 florian
  1082. * fixed several arm related problems
  1083. Revision 1.24 2003/11/24 15:17:37 florian
  1084. * changed some types to prevend range check errors
  1085. Revision 1.23 2003/11/21 16:29:26 florian
  1086. * fixed reading of reg. sets in the arm assembler reader
  1087. Revision 1.22 2003/11/07 15:58:32 florian
  1088. * Florian's culmutative nr. 1; contains:
  1089. - invalid calling conventions for a certain cpu are rejected
  1090. - arm softfloat calling conventions
  1091. - -Sp for cpu dependend code generation
  1092. - several arm fixes
  1093. - remaining code for value open array paras on heap
  1094. Revision 1.21 2003/11/02 14:30:03 florian
  1095. * fixed ARM for new reg. allocation scheme
  1096. Revision 1.20 2003/10/11 16:06:42 florian
  1097. * fixed some MMX<->SSE
  1098. * started to fix ppc, needs an overhaul
  1099. + stabs info improve for spilling, not sure if it works correctly/completly
  1100. - MMX_SUPPORT removed from Makefile.fpc
  1101. Revision 1.19 2003/09/11 11:55:00 florian
  1102. * improved arm code generation
  1103. * move some protected and private field around
  1104. * the temp. register for register parameters/arguments are now released
  1105. before the move to the parameter register is done. This improves
  1106. the code in a lot of cases.
  1107. Revision 1.18 2003/09/09 12:53:40 florian
  1108. * some assembling problems fixed
  1109. * improved loadaddr_ref_reg
  1110. Revision 1.17 2003/09/06 16:45:51 florian
  1111. * fixed exit code (no preindexed addressing mode in LDM)
  1112. Revision 1.16 2003/09/06 11:21:50 florian
  1113. * fixed stm and ldm to be usable with preindex operand
  1114. Revision 1.15 2003/09/05 23:57:01 florian
  1115. * arm is working again as before the new register naming scheme was implemented
  1116. Revision 1.14 2003/09/04 21:07:03 florian
  1117. * ARM compiler compiles again
  1118. Revision 1.13 2003/09/04 00:15:29 florian
  1119. * first bunch of adaptions of arm compiler for new register type
  1120. Revision 1.12 2003/09/03 19:10:30 florian
  1121. * initial revision of new register naming
  1122. Revision 1.11 2003/09/03 11:18:37 florian
  1123. * fixed arm concatcopy
  1124. + arm support in the common compiler sources added
  1125. * moved some generic cg code around
  1126. + tfputype added
  1127. * ...
  1128. Revision 1.10 2003/09/01 15:11:16 florian
  1129. * fixed reference handling
  1130. * fixed operand postfix for floating point instructions
  1131. * fixed wrong shifter constant handling
  1132. Revision 1.9 2003/09/01 09:54:57 florian
  1133. * results of work on arm port last weekend
  1134. Revision 1.8 2003/08/29 21:36:28 florian
  1135. * fixed procedure entry/exit code
  1136. * started to fix reference handling
  1137. Revision 1.7 2003/08/28 13:26:10 florian
  1138. * another couple of arm fixes
  1139. Revision 1.6 2003/08/28 00:05:29 florian
  1140. * today's arm patches
  1141. Revision 1.5 2003/08/25 23:20:38 florian
  1142. + started to implement FPU support for the ARM
  1143. * fixed a lot of other things
  1144. Revision 1.4 2003/08/24 12:27:26 florian
  1145. * continued to work on the arm port
  1146. Revision 1.3 2003/08/21 03:14:00 florian
  1147. * arm compiler can be compiled; far from being working
  1148. Revision 1.2 2003/08/20 15:50:12 florian
  1149. * more arm stuff
  1150. Revision 1.1 2003/07/21 16:35:30 florian
  1151. * very basic stuff for the arm
  1152. }