cgcpu.pas 46 KB

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