cgcpu.pas 46 KB

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