cgcpu.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. This unit implements the code generator for the PowerPC
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. interface
  20. uses
  21. cgbase,cgobj,aasm,cpuasm,cpubase,cpuinfo;
  22. type
  23. pcgppc = ^tcgppc;
  24. tcgppc = object(tcg)
  25. { passing parameters, per default the parameter is pushed }
  26. { nr gives the number of the parameter (enumerated from }
  27. { left to right), this allows to move the parameter to }
  28. { register, if the cpu supports register calling }
  29. { conventions }
  30. procedure a_param_reg(list : paasmoutput;size : tcgsize;r : tregister;nr : longint);virtual;
  31. procedure a_param_const(list : paasmoutput;size : tcgsize;a : aword;nr : longint);virtual;
  32. procedure a_param_ref(list : paasmoutput;size : tcgsize;const r : treference;nr : longint);virtual;
  33. procedure a_paramaddr_ref(list : paasmoutput;const r : treference;nr : longint);virtual;
  34. procedure a_call_name(list : paasmoutput;const s : string;
  35. offset : longint);virtual;
  36. procedure a_op_reg_const(list : paasmoutput; Op: TOpCG; size: TCGSize; reg: TRegister; a: AWord); virtual;
  37. { move instructions }
  38. procedure a_load_const_reg(list : paasmoutput; size: tcgsize; a : aword;reg : tregister);virtual;
  39. procedure a_load_reg_ref(list : paasmoutput; size: tcgsize; reg : tregister;const ref2 : treference);virtual;
  40. procedure a_load_ref_reg(list : paasmoutput;size : tcgsize;const Ref2 : treference;reg : tregister);virtual;
  41. procedure a_load_reg_reg(list : paasmoutput;size : tcgsize;reg1,reg2 : tregister);virtual;
  42. { comparison operations }
  43. procedure a_cmp_reg_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  44. l : pasmlabel);virtual;
  45. procedure a_cmp_reg_reg_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : pasmlabel);
  46. procedure g_stackframe_entry(list : paasmoutput;localsize : longint);virtual;
  47. procedure g_restore_frame_pointer(list : paasmoutput);virtual;
  48. procedure g_return_from_proc(list : paasmoutput;parasize : aword); virtual;
  49. procedure a_loadaddress_ref_reg(list : paasmoutput;const ref2 : treference;r : tregister);virtual;
  50. procedure g_concatcopy(list : paasmoutput;const source,dest : treference;len : aword;loadref : boolean);virtual;
  51. private
  52. { Generates }
  53. { OpLo reg1, reg2, (a and $ffff) and/or }
  54. { OpHi reg1, reg2, (a shr 16) }
  55. { depending on the value of a }
  56. procedure a_op_reg_reg_const32(list: paasmOutPut; oplo, ophi: tasmop;
  57. reg1, reg2: tregister; a: aword);
  58. { Make sure ref is a valid reference for the PowerPC and sets the }
  59. { base to the value of the index if (base = R_NO). }
  60. procedure fixref(var ref: treference);
  61. { contains the common code of a_load_reg_ref and a_load_ref_reg }
  62. procedure a_load_store(list:paasmoutput;op: tasmop;reg:tregister;
  63. var ref: treference);
  64. { creates the correct branch instruction for a given combination }
  65. { of asmcondflags and destination addressing mode }
  66. procedure a_jmp(list: paasmoutput; op: tasmop;
  67. c: tasmcondflags; l: pasmlabel);
  68. end;
  69. const
  70. TOpCG2AsmOpLo: Array[topcg] of TAsmOp = (A_ADDI,A_ANDI_,A_DIVWU,
  71. A_DIVW,A_MULLW, A_MULLW, A_NONE,A_NONE,A_ORI,
  72. A_SRAWI,A_SLWI,A_SRWI,A_SUBI,A_XORI);
  73. TOpCG2AsmOpHi: Array[topcg] of TAsmOp = (A_ADDIS,A_ANDIS_,
  74. A_DIVWU,A_DIVW, A_MULLW,A_MULLW,A_NONE,A_NONE,
  75. A_ORIS,A_NONE, A_NONE,A_NONE,A_SUBIS,A_XORIS);
  76. TOpCmp2AsmCond: Array[topcmp] of TAsmCondFlags = (CF_EQ,CF_GT,CF_LT,CF_GE,
  77. CF_LE,CF_NE,CF_LE,CF_NG,CF_GE,CF_NL);
  78. LoadInstr: Array[OS_8..OS_32,boolean, boolean] of TAsmOp =
  79. { indexed? updating?}
  80. (((A_LBZ,A_LBZU),(A_LBZX,A_LBZUX)),
  81. ((A_LHZ,A_LHZU),(A_LHZX,A_LHZUX)),
  82. ((A_LWZ,A_LWZU),(A_LWZX,A_LWZUX)));
  83. StoreInstr: Array[OS_8..OS_32,boolean, boolean] of TAsmOp =
  84. { indexed? updating?}
  85. (((A_STB,A_STBU),(A_STBX,A_STBUX)),
  86. ((A_STH,A_STHU),(A_STHX,A_STHUX)),
  87. ((A_STW,A_STWU),(A_STWX,A_STWUX)));
  88. implementation
  89. uses
  90. globtype,globals,verbose;
  91. { parameter passing... Still needs extra support from the processor }
  92. { independent code generator }
  93. procedure tcgppc.a_param_reg(list : paasmoutput;size : tcgsize;r : tregister;nr : longint);
  94. var ref: treference;
  95. begin
  96. {$ifdef para_sizes_known}
  97. if (nr <= max_param_regs_int) then
  98. a_load_reg_reg(list,size,r,param_regs_int[nr])
  99. else
  100. begin
  101. reset_reference(ref);
  102. ref.base := stack_pointer;
  103. ref.offset := LinkageAreaSize+para_size_till_now;
  104. a_load_reg_ref(list,size,reg,ref);
  105. end;
  106. {$endif para_sizes_known}
  107. end;
  108. procedure tcgppc.a_param_const(list : paasmoutput;size : tcgsize;a : aword;nr : longint);
  109. var ref: treference;
  110. begin
  111. {$ifdef para_sizes_known}
  112. if (nr <= max_param_regs_int) then
  113. a_load_const_reg(list,size,a,param_regs_int[nr])
  114. else
  115. begin
  116. reset_reference(ref);
  117. ref.base := stack_pointer;
  118. ref.offset := LinkageAreaSize+para_size_till_now;
  119. a_load_const_ref(list,size,a,ref);
  120. end;
  121. {$endif para_sizes_known}
  122. end;
  123. procedure tcgppc.a_param_ref(list : paasmoutput;size : tcgsize;const r : treference;nr : longint);
  124. var ref: treference;
  125. tmpreg: tregister;
  126. begin
  127. {$ifdef para_sizes_known}
  128. if (nr <= max_param_regs_int) then
  129. a_load_ref_reg(list,size,r,param_regs_int[nr])
  130. else
  131. begin
  132. reset_reference(ref);
  133. ref.base := stack_pointer;
  134. ref.offset := LinkageAreaSize+para_size_till_now;
  135. tmpreg := get_scratch_reg(list);
  136. a_load_ref_reg(list,size,r,tmpreg);
  137. a_load_reg_ref(list,size,tmpreg,ref);
  138. free_scratch_reg(list,tmpreg);
  139. end;
  140. {$endif para_sizes_known}
  141. end;
  142. procedure tcgppc.a_paramaddr_ref(list : paasmoutput;const r : treference;nr : longint);
  143. var ref: treference;
  144. tmpreg: tregister;
  145. begin
  146. {$ifdef para_sizes_known}
  147. if (nr <= max_param_regs_int) then
  148. a_loadaddress_ref_reg(list,size,r,param_regs_int[nr])
  149. else
  150. begin
  151. reset_reference(ref);
  152. ref.base := stack_pointer;
  153. ref.offset := LinkageAreaSize+para_size_till_now;
  154. tmpreg := get_scratch_reg(list);
  155. a_loadaddress_ref_reg(list,size,r,tmpreg);
  156. a_load_reg_ref(list,size,tmpreg,ref);
  157. free_scratch_reg(list,tmpreg);
  158. end;
  159. {$endif para_sizes_known}
  160. end;
  161. { calling a code fragment by name }
  162. procedure tcgppc.a_call_name(list : paasmoutput;const s : string;
  163. offset : longint);
  164. begin
  165. { save our RTOC register value. Only necessary when doing pointer based }
  166. { calls or cross TOC calls, but currently done always }
  167. list^.concat(new(paicpu,op_reg_ref(A_STW,R_RTOC,
  168. new_reference(stack_pointer,LA_RTOC))));
  169. list^.concat(new(paicpu,op_sym(A_BL,newasmsymbol(s))));
  170. list^.concat(new(paicpu,op_reg_ref(A_LWZ,R_RTOC,
  171. new_reference(stack_pointer,LA_RTOC))));
  172. end;
  173. {********************** load instructions ********************}
  174. procedure tcgppc.a_load_const_reg(list : paasmoutput; size: TCGSize; a : aword; reg : TRegister);
  175. begin
  176. If (a and $ffff) <> 0 Then
  177. Begin
  178. list^.concat(new(paicpu,op_reg_const(A_LI,reg,a and $ffff)));
  179. If (a shr 16) <> 0 Then
  180. list^.concat(new(paicpu,op_reg_const(A_ORIS,reg,a shr 16)))
  181. End
  182. Else
  183. list^.concat(new(paicpu,op_reg_const(A_LIS,reg,a shr 16)));
  184. end;
  185. procedure tcgppc.a_load_reg_ref(list : paasmoutput; size: TCGSize; reg : tregister;const ref2 : treference);
  186. Var
  187. op: TAsmOp;
  188. ref: TReference;
  189. begin
  190. ref := ref2;
  191. FixRef(ref);
  192. op := storeinstr[size,ref.index<>R_NO,false];
  193. a_load_store(list,op,reg,ref);
  194. End;
  195. procedure tcgppc.a_load_ref_reg(list : paasmoutput;size : tcgsize;const ref2: treference;reg : tregister);
  196. Var
  197. op: TAsmOp;
  198. tmpreg: tregister;
  199. ref, tmpref: TReference;
  200. begin
  201. ref := ref2;
  202. FixRef(ref);
  203. op := loadinstr[size,ref.index<>R_NO,false];
  204. a_load_store(list,op,reg,ref);
  205. end;
  206. procedure tcgppc.a_load_reg_reg(list : paasmoutput;size : tcgsize;reg1,reg2 : tregister);
  207. begin
  208. list^.concat(new(paicpu,op_reg_reg(A_MR,reg2,reg1)));
  209. end;
  210. procedure tcgppc.a_op_reg_const(list : paasmoutput; Op: TOpCG; size: TCGSize; reg: TRegister; a: AWord);
  211. var scratch_register: TRegister;
  212. begin
  213. Case Op of
  214. OP_DIV, OP_IDIV, OP_IMUL, OP_MUL:
  215. If (Op = OP_IMUL) And (longint(a) >= -32768) And
  216. (longint(a) <= 32767) Then
  217. list^.concat(new(paicpu,op_reg_reg_const(A_MULLI,reg,reg,a)))
  218. Else
  219. Begin
  220. scratch_register := get_scratch_reg(list);
  221. a_load_const_reg(list, OS_32, a, scratch_register);
  222. list^.concat(new(paicpu,op_reg_reg_reg(TOpCG2AsmOpLo[Op],
  223. reg,reg,scratch_register)));
  224. free_scratch_reg(list,scratch_register);
  225. End;
  226. OP_ADD, OP_AND, OP_OR, OP_SUB,OP_XOR:
  227. a_op_reg_reg_const32(list,TOpCG2AsmOpLo[Op],
  228. TOpCG2AsmOpHi[Op],reg,reg,a);
  229. OP_SHL,OP_SHR,OP_SAR:
  230. Begin
  231. if (a and 31) <> 0 Then
  232. list^.concat(new(paicpu,op_reg_reg_const(
  233. TOpCG2AsmOpLo[Op],reg,reg,a and 31)));
  234. If (a shr 5) <> 0 Then
  235. InternalError(68991);
  236. End
  237. Else InternalError(68992);
  238. end;
  239. end;
  240. {*************** compare instructructions ****************}
  241. procedure tcgppc.a_cmp_reg_const_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  242. l : pasmlabel);
  243. var p: paicpu;
  244. scratch_register: TRegister;
  245. signed: boolean;
  246. begin
  247. signed := cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE];
  248. If signed Then
  249. If (longint(a) >= -32768) and (longint(a) <= 32767) Then
  250. list^.concat(new(paicpu,op_const_reg_const(A_CMPI,0,reg,a)))
  251. else
  252. begin
  253. scratch_register := get_scratch_reg(list);
  254. a_load_const_reg(list,OS_32,a,scratch_register);
  255. list^.concat(new(paicpu,op_const_reg_reg(A_CMP,0,reg,scratch_register)));
  256. free_scratch_reg(list,scratch_register);
  257. end
  258. else
  259. if (a <= $ffff) then
  260. list^.concat(new(paicpu,op_const_reg_const(A_CMPLI,0,reg,a)))
  261. else
  262. begin
  263. scratch_register := get_scratch_reg(list);
  264. a_load_const_reg(list,OS_32,a,scratch_register);
  265. list^.concat(new(paicpu,op_const_reg_reg(A_CMPL,0,reg,scratch_register)));
  266. free_scratch_reg(list,scratch_register);
  267. end;
  268. a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],l);
  269. end;
  270. procedure tcgppc.a_cmp_reg_reg_label(list : paasmoutput;size : tcgsize;cmp_op : topcmp;
  271. reg1,reg2 : tregister;l : pasmlabel);
  272. var p: paicpu;
  273. AsmCond: TAsmCondFlags;
  274. begin
  275. list^.concat(new(paicpu,op_const_reg_reg(A_CMPL,0,reg1,reg2)));
  276. a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],l);
  277. end;
  278. { *********** entry/exit code and address loading ************ }
  279. procedure tcgppc.g_stackframe_entry(list : paasmoutput;localsize : longint);
  280. { generated the entry code of a procedure/function. Note: localsize is the }
  281. { sum of the size necessary for local variables and the maximum possible }
  282. { combined size of ALL the parameters of a procedure called by the current }
  283. { one }
  284. var scratch_register: TRegister;
  285. begin
  286. if (localsize mod 8) <> 0 then internalerror(58991);
  287. { CR and LR only have to be saved in case they are modified by the current }
  288. { procedure, but currently this isn't checked, so save them always }
  289. scratch_register := get_scratch_reg(list);
  290. list^.concat(new(paicpu,op_reg(A_MFCR,scratch_register)));
  291. list^.concat(new(paicpu,op_reg_ref(A_STW,scratch_register,
  292. new_reference(stack_pointer,LA_CR))));
  293. free_scratch_reg(list,scratch_register);
  294. scratch_register := get_scratch_reg(list);
  295. list^.concat(new(paicpu,op_reg_reg(A_MFSPR,scratch_register,
  296. R_LR)));
  297. list^.concat(new(paicpu,op_reg_ref(A_STW,scratch_register,
  298. new_reference(stack_pointer,LA_LR))));
  299. free_scratch_reg(list,scratch_register);
  300. { if the current procedure is a leaf procedure, we can use the Red Zone, }
  301. { but this is not yet implemented }
  302. { if ((procinfo.flags and pi_do_call) <> 0) And }
  303. { (localsize <= (256 - LinkageAreaSize)) Then }
  304. Begin
  305. if localsize<>0 then
  306. begin
  307. { allocate space for the local variable, parameter and linkage area and }
  308. { save the stack pointer at the end of the linkage area }
  309. if localsize <= $ffff Then
  310. list^.concat(new(paicpu,op_reg_ref
  311. (A_STWU,stack_pointer, new_reference(stack_pointer,localsize+
  312. LinkageAreaSize))))
  313. else
  314. Begin
  315. scratch_register := get_scratch_reg(list);
  316. a_load_const_reg(list,OS_32,localsize,scratch_register);
  317. list^.concat(new(paicpu,op_reg_reg_reg(A_STWUX,stack_pointer,
  318. stack_pointer,scratch_register)));
  319. free_scratch_reg(list,scratch_register);
  320. End;
  321. End
  322. End;
  323. end;
  324. procedure tcgppc.g_restore_frame_pointer(list : paasmoutput);
  325. begin
  326. { no frame pointer on the PowerPC }
  327. end;
  328. procedure tcgppc.g_return_from_proc(list : paasmoutput;parasize : aword);
  329. begin
  330. abstract;
  331. end;
  332. procedure tcgppc.a_loadaddress_ref_reg(list : paasmoutput;const ref2 : treference;r : tregister);
  333. Var
  334. ref: TReference;
  335. begin
  336. ref := ref2;
  337. FixRef(ref);
  338. If ref.offset <> 0 Then
  339. If ref.base <> R_NO then
  340. a_op_reg_reg_const32(list,A_ADDI,A_ADDIS,r,r,ref.offset)
  341. { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
  342. { occurs, so now only ref.offset has to be loaded }
  343. else a_load_const_reg(list, OS_32, ref.offset, r)
  344. else
  345. if ref.index <> R_NO Then
  346. list^.concat(new(paicpu,op_reg_reg_reg(A_ADD,r,ref.base,ref.index)))
  347. else list^.concat(new(paicpu,op_reg_reg(A_MR,r,ref.base)))
  348. end;
  349. { ************* concatcopy ************ }
  350. procedure tcgppc.g_concatcopy(list : paasmoutput;const source,dest : treference;len : aword;loadref : boolean);
  351. var
  352. p: paicpu;
  353. countreg, tempreg: TRegister;
  354. src, dst: TReference;
  355. lab: PAsmLabel;
  356. count, count2: aword;
  357. begin
  358. { make sure source and dest are valid }
  359. src := source;
  360. fixref(src);
  361. dst := dest;
  362. fixref(dst);
  363. reset_reference(src);
  364. reset_reference(dst);
  365. { load the address of source into src.base }
  366. src.base := get_scratch_reg(list);
  367. if loadref then
  368. a_load_ref_reg(list,OS_32,source,src.base)
  369. else a_loadaddress_ref_reg(list,source,src.base);
  370. { load the address of dest into dst.base }
  371. dst.base := get_scratch_reg(list);
  372. a_loadaddress_ref_reg(list,dest,dst.base);
  373. count := len div 4;
  374. if count > 3 then
  375. { generate a loop }
  376. begin
  377. Inc(dst.offset,4);
  378. Inc(src.offset,4);
  379. a_op_reg_reg_const32(list,A_SUBI,A_NONE,src.base,src.base,4);
  380. a_op_reg_reg_const32(list,A_SUBI,A_NONE,dst.base,dst.base,4);
  381. countreg := get_scratch_reg(list);
  382. a_load_const_reg(list,OS_32,count-1,countreg);
  383. tempreg := get_scratch_reg(list);
  384. getlabel(lab);
  385. a_label(list, lab);
  386. list^.concat(new(paicpu,op_reg_ref(A_LWZU,tempreg,
  387. newreference(src))));
  388. a_op_reg_reg_const32(list,A_CMPI,A_NONE,R_CR0,countreg,0);
  389. list^.concat(new(paicpu,op_reg_ref(A_STWU,tempreg,
  390. newreference(dst))));
  391. a_op_reg_reg_const32(list,A_SUBI,A_NONE,countreg,countreg,1);
  392. a_jmp(list,A_BC,CF_NE,lab);
  393. free_scratch_reg(list,countreg);
  394. end
  395. else
  396. { unrolled loop }
  397. begin
  398. tempreg := get_scratch_reg(list);
  399. for count2 := 1 to count do
  400. begin
  401. a_load_ref_reg(list,OS_32,src,tempreg);
  402. a_load_reg_ref(list,OS_32,tempreg,dst);
  403. inc(src.offset,4);
  404. inc(dst.offset,4);
  405. end
  406. end;
  407. { copy the leftovers }
  408. if (len and 2) <> 0 then
  409. begin
  410. a_load_ref_reg(list,OS_16,src,tempreg);
  411. a_load_reg_ref(list,OS_16,tempreg,dst);
  412. inc(src.offset,2);
  413. inc(dst.offset,2);
  414. end;
  415. if (len and 1) <> 0 then
  416. begin
  417. a_load_ref_reg(list,OS_8,src,tempreg);
  418. a_load_reg_ref(list,OS_8,tempreg,dst);
  419. end;
  420. free_scratch_reg(list,tempreg);
  421. free_scratch_reg(list,src.base);
  422. free_scratch_reg(list,dst.base);
  423. end;
  424. {***************** This is private property, keep out! :) *****************}
  425. procedure tcgppc.fixref(var ref: treference);
  426. begin
  427. If (ref.base <> R_NO) then
  428. begin
  429. if (ref.index <> R_NO) and
  430. ((ref.offset <> 0) or assigned(ref.symbol)) Then
  431. Internalerror(58992)
  432. end
  433. else
  434. begin
  435. ref.base := ref.index;
  436. ref.index := R_NO
  437. end
  438. end;
  439. procedure tcgppc.a_op_reg_reg_const32(list: paasmoutput; oplo, ophi:
  440. tasmop; reg1, reg2: tregister; a: aword);
  441. begin
  442. if (a and $ffff) <> 0 Then
  443. list^.concat(new(paicpu,op_reg_reg_const(OpLo,reg1,reg2,a and $ffff)));
  444. If (a shr 16) <> 0 Then
  445. list^.concat(new(paicpu,op_reg_reg_const(OpHi,reg1,reg2,a shr 16)))
  446. end;
  447. procedure tcgppc.a_load_store(list:paasmoutput;op: tasmop;reg:tregister;
  448. var ref: treference);
  449. var tmpreg: tregister;
  450. tmpref: treference;
  451. begin
  452. if assigned(ref.symbol) then
  453. begin
  454. tmpreg := get_scratch_reg(list);
  455. reset_reference(tmpref);
  456. tmpref.symbol := ref.symbol;
  457. tmpref.symaddr := refs_ha;
  458. tmpref.is_immediate := true;
  459. if ref.base <> R_NO then
  460. list^.concat(new(paicpu,op_reg_reg_ref(A_ADDIS,tmpreg,
  461. ref.base,newreference(tmpref))))
  462. else
  463. list^.concat(new(paicpu,op_reg_ref(A_LIS,tmpreg,
  464. newreference(tmpref))));
  465. ref.base := tmpreg
  466. end;
  467. list^.concat(new(paicpu,op_reg_ref(op,reg,newreference(ref))));
  468. if assigned(ref.symbol) then
  469. free_scratch_reg(list,tmpreg);
  470. end;
  471. procedure tcgppc.a_jmp(list: paasmoutput; op: tasmop; c: tasmcondflags;
  472. l: pasmlabel);
  473. var p: paicpu;
  474. begin
  475. p := new(paicpu,op_sym(op,newasmsymbol(l^.name)));
  476. p^.condition := create_cond_norm(c,0);
  477. list^.concat(p)
  478. end;
  479. end.
  480. {
  481. $Log$
  482. Revision 1.5 1999-09-03 13:14:11 jonas
  483. + implemented some parameter passing methods, but they require\n some more helper routines\n * fix for loading symbol addresses (still needs to be done in a_loadaddress)\n * several changes to the way conditional branches are handled
  484. Revision 1.4 1999/08/26 14:53:41 jonas
  485. * first implementation of concatcopy (requires 4 scratch regs)
  486. Revision 1.3 1999/08/25 12:00:23 jonas
  487. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  488. Revision 1.2 1999/08/18 17:05:57 florian
  489. + implemented initilizing of data for the new code generator
  490. so it should compile now simple programs
  491. Revision 1.1 1999/08/06 16:41:11 jonas
  492. * PowerPC compiles again, several routines implemented in cgcpu.pas
  493. * added constant to cpubase of alpha and powerpc for maximum
  494. number of operands
  495. }