cgcpu.pas 43 KB

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