cgcpu.pas 46 KB

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