1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2008
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef __nanojit_NativePPC__
41 #define __nanojit_NativePPC__
45 #include "../vprof/vprof.h"
46 #define count_instr() _nvprof("ppc",1)
47 #define count_prolog() _nvprof("ppc-prolog",1); count_instr();
48 #define count_imt() _nvprof("ppc-imt",1) count_instr()
51 #define count_prolog()
57 #define NJ_MAX_STACK_ENTRY 4096
58 #define NJ_ALIGN_STACK 16
60 #define NJ_JTBL_SUPPORTED 1
61 #define NJ_EXPANDED_LOADSTORE_SUPPORTED 0
62 #define NJ_F2I_SUPPORTED 0
63 #define NJ_SOFTFLOAT_SUPPORTED 0
65 enum ConditionRegister
{
77 COND_lt
= 0, // msb of CR
80 COND_so
= 3, // lsb of CR
84 // this is the BO field in condition instructions
85 enum ConditionOption
{
86 BO_true
= 12, // branch if true
87 BO_false
= 4, // branch if false
91 // general purpose 32bit regs
92 R0
= 0, // scratch or the value 0, excluded from regalloc
93 SP
= 1, // stack pointer, excluded from regalloc
94 R2
= 2, // scratch on MacOSX, rtoc pointer elsewhere
95 R3
= 3, // this, return value, MSW of int64 return
96 R4
= 4, // param, LSW of int64 return
103 R11
= 11, // scratch in leaf funcs, outgoing arg ptr otherwise
105 R13
= 13, // ppc32: saved, ppc64: thread-specific storage
123 R31
= 31, // excluded from regalloc since we use it as FP
127 F0
= 32, // scratch, excluded from reg alloc
128 F1
= 33, // param, double return value
141 F14
= 46, // F14-31 saved
160 // special purpose registers (SPR)
165 deprecated_UnknownReg
= 127, // XXX: remove eventually, see bug 538924
172 PPC_add
= 0x7C000214, // add
173 PPC_addo
= 0x7C000614, // add & OE=1 (can set OV)
174 PPC_addi
= 0x38000000, // add immediate
175 PPC_addis
= 0x3C000000, // add immediate shifted
176 PPC_and
= 0x7C000038, // and
177 PPC_andc
= 0x7C000078, // and with compliment
178 PPC_andi
= 0x70000000, // and immediate
179 PPC_andis
= 0x74000000, // and immediate shifted
180 PPC_b
= 0x48000000, // branch
181 PPC_bc
= 0x40000000, // branch conditional
182 PPC_bcctr
= 0x4C000420, // branch conditional to count register
183 PPC_cmp
= 0x7C000000, // compare
184 PPC_cmpi
= 0x2C000000, // compare immediate
185 PPC_cmpl
= 0x7C000040, // compare logical
186 PPC_cmpli
= 0x28000000, // compare logical immediate
187 PPC_cror
= 0x4C000382, // condition register or
188 PPC_extsw
= 0x7C0007B4, // extend sign word
189 PPC_fadd
= 0xFC00002A, // floating add (double precision)
190 PPC_fcfid
= 0xFC00069C, // floating convert from integer doubleword
191 PPC_fcmpu
= 0xFC000000, // floating compare unordered
192 PPC_fdiv
= 0xFC000024, // floating divide (double precision)
193 PPC_fmr
= 0xFC000090, // floating move register (double precision)
194 PPC_fmul
= 0xFC000032, // floating multiply (double precision)
195 PPC_fneg
= 0xFC000050, // floating negate
196 PPC_fsub
= 0xFC000028, // floating subtract (double precision)
197 PPC_lbz
= 0x88000000, // load byte and zero
198 PPC_lbzx
= 0x7C0000AE, // load byte and zero indexed
199 PPC_ld
= 0xE8000000, // load doubleword
200 PPC_ldx
= 0x7C00002A, // load doubleword indexed
201 PPC_lfd
= 0xC8000000, // load floating point double
202 PPC_lfdx
= 0x7C0004AE, // load floating-point double indexed
203 PPC_lhz
= 0xA0000000, // load halfword and zero
204 PPC_lhzx
= 0x7C00022E, // load halfword and zero indexed
205 PPC_lwz
= 0x80000000, // load word and zero
206 PPC_lwzx
= 0x7C00002E, // load word and zero indexed
207 PPC_mfcr
= 0x7C000026, // move from condition register
208 PPC_mfspr
= 0x7C0002A6, // move from spr (special purpose register)
209 PPC_mtspr
= 0x7C0003A6, // move to spr
210 PPC_mulli
= 0x1C000000, // multiply low immediate
211 PPC_mullw
= 0x7C0001D6, // multiply low word
212 PPC_neg
= 0x7C0000D0, // negate
213 PPC_nor
= 0x7C0000F8, // nor
214 PPC_or
= 0x7C000378, // or
215 PPC_ori
= 0x60000000, // or immediate
216 PPC_oris
= 0x64000000, // or immediate shifted
217 PPC_rlwinm
= 0x54000000, // rotate left word then and with mask
218 PPC_rldicl
= 0x78000000, // rotate left doubleword immediate then clear left
219 PPC_rldicr
= 0x78000004, // rotate left doubleword immediate then clear right
220 PPC_rldimi
= 0x7800000C, // rotate left doubleword immediate then mask insert
221 PPC_sld
= 0x7C000036, // shift left doubleword
222 PPC_slw
= 0x7C000030, // shift left word
223 PPC_srad
= 0x7C000634, // shift right algebraic doubleword (sign ext)
224 PPC_sradi
= 0x7C000674, // shift right algebraic doubleword immediate
225 PPC_sraw
= 0x7C000630, // shift right algebraic word (sign ext)
226 PPC_srawi
= 0x7C000670, // shift right algebraic word immediate
227 PPC_srd
= 0x7C000436, // shift right doubleword (zero ext)
228 PPC_srw
= 0x7C000430, // shift right word (zero ext)
229 PPC_stb
= 0x98000000, // store byte
230 PPC_stbx
= 0x7C0001AE, // store byte indexed
231 PPC_std
= 0xF8000000, // store doubleword
232 PPC_stdu
= 0xF8000001, // store doubleword with update
233 PPC_stdux
= 0x7C00016A, // store doubleword with update indexed
234 PPC_stdx
= 0x7C00012A, // store doubleword indexed
235 PPC_stfd
= 0xD8000000, // store floating-point double
236 PPC_stfdx
= 0x7C0005AE, // store floating-point double indexed
237 PPC_stw
= 0x90000000, // store word
238 PPC_stwu
= 0x94000000, // store word with update
239 PPC_stwux
= 0x7C00016E, // store word with update indexed
240 PPC_stwx
= 0x7C00012E, // store word indexed
241 PPC_subf
= 0x7C000050, // subtract from
242 PPC_xor
= 0x7C000278, // xor
243 PPC_xori
= 0x68000000, // xor immediate
244 PPC_xoris
= 0x6C000000, // xor immediate shifted
246 // simplified mnemonics
252 typedef uint64_t RegisterMask
;
254 static const RegisterMask GpRegs
= 0xffffffff;
255 static const RegisterMask FpRegs
= 0xffffffff00000000LL
;
256 // R31 is a saved reg too, but we use it as our Frame ptr FP
258 // R13 reserved for thread-specific storage on ppc64-darwin
259 static const RegisterMask SavedRegs
= 0x7fffc000; // R14-R30 saved
260 static const int NumSavedRegs
= 17; // R14-R30
262 static const RegisterMask SavedRegs
= 0x7fffe000; // R13-R30 saved
263 static const int NumSavedRegs
= 18; // R13-R30
266 static inline bool IsGpReg(Register r
) {
269 static inline bool IsFpReg(Register r
) {
273 verbose_only( extern const char* regNames
[]; )
275 #define DECLARE_PLATFORM_STATS()
276 #define DECLARE_PLATFORM_REGALLOC()
279 #define DECL_PPC64()\
280 void asm_qbinop(LIns*);
285 #define DECLARE_PLATFORM_ASSEMBLER() \
286 const static Register argRegs[8], retRegs[2]; \
287 void underrunProtect(int bytes); \
288 void nativePageReset(); \
289 void nativePageSetup(); \
290 void br(NIns *addr, int link); \
291 void br_far(NIns *addr, int link); \
292 void asm_regarg(ArgType, LIns*, Register); \
293 void asm_li(Register r, int32_t imm); \
294 void asm_li32(Register r, int32_t imm); \
295 void asm_li64(Register r, uint64_t imm); \
296 void asm_cmp(LOpcode op, LIns *a, LIns *b, ConditionRegister); \
297 NIns* asm_branch_far(bool onfalse, LIns *cond, NIns * const targ); \
298 NIns* asm_branch_near(bool onfalse, LIns *cond, NIns * const targ); \
299 int max_param_size; /* bytes */ \
302 const int LARGEST_UNDERRUN_PROT
= 9*4; // largest value passed to underrunProtect
304 typedef uint32_t NIns
;
306 // Bytes of icache to flush after Assembler::patch
307 const size_t LARGEST_BRANCH_PATCH
= 4 * sizeof(NIns
);
309 #define EMIT1(ins, fmt, ...) do {\
311 *(--_nIns) = (NIns) (ins);\
312 asm_output(fmt, ##__VA_ARGS__);\
313 } while (0) /* no semi */
316 #define FPR(r) ((r)&31)
318 #define Bx(li,aa,lk) EMIT1(PPC_b | ((li)&0xffffff)<<2 | (aa)<<1 | (lk),\
319 "b%s%s %p", (lk)?"l":"", (aa)?"a":"", _nIns+(li))
321 #define B(li) Bx(li,0,0)
322 #define BA(li) Bx(li,1,0)
323 #define BL(li) Bx(li,0,1)
324 #define BLA(li) Bx(li,1,1)
326 #define BCx(op,bo,bit,cr,bd,aa,lk) EMIT1(PPC_bc | (bo)<<21 | (4*(cr)+COND_##bit)<<16 |\
327 ((bd)&0x3fff)<<2 | (aa)<<1 | (lk),\
328 "%s%s%s cr%d,%p", #op, (lk)?"l":"", (aa)?"a":"", (cr), _nIns+(bd))
330 #define BLT(cr,bd) BCx(blt, BO_true, lt, cr, bd, 0, 0)
331 #define BGT(cr,bd) BCx(bgt, BO_true, gt, cr, bd, 0, 0)
332 #define BEQ(cr,bd) BCx(beq, BO_true, eq, cr, bd, 0, 0)
333 #define BGE(cr,bd) BCx(bge, BO_false, lt, cr, bd, 0, 0)
334 #define BLE(cr,bd) BCx(ble, BO_false, gt, cr, bd, 0, 0)
335 #define BNE(cr,bd) BCx(bne, BO_false, eq, cr, bd, 0, 0)
336 #define BNG(cr,bd) BCx(bng, BO_false, gt, cr, bd, 0, 0)
337 #define BNL(cr,bd) BCx(bnl, BO_false, lt, cr, bd, 0, 0)
339 #define BCCTRx(op, bo, bit, cr, lk) EMIT1(PPC_bcctr | (bo)<<21 | (4*(cr)+COND_##bit)<<16 | (lk)&1,\
340 "%sctr%s cr%d", #op, (lk)?"l":"", (cr))
342 #define BLTCTR(cr) BCCTRx(blt, BO_true, lt, cr, 0)
343 #define BGTCTR(cr) BCCTRx(bgt, BO_true, gt, cr, 0)
344 #define BEQCTR(cr) BCCTRx(beq, BO_true, eq, cr, 0)
345 #define BGECTR(cr) BCCTRx(bge, BO_false, lt, cr, 0)
346 #define BLECTR(cr) BCCTRx(ble, BO_false, gt, cr, 0)
347 #define BNECTR(cr) BCCTRx(bne, BO_false, eq, cr, 0)
348 #define BNGCTR(cr) BCCTRx(bng, BO_false, gt, cr, 0)
349 #define BNLCTR(cr) BCCTRx(bnl, BO_false, lt, cr, 0)
351 #define Simple(asm,op) EMIT1(op, "%s", #asm)
353 #define BCTR(link) EMIT1(0x4E800420 | (link), "bctr%s", (link) ? "l" : "")
354 #define BCTRL() BCTR(1)
356 #define BLR() EMIT1(0x4E800020, "blr")
357 #define NOP() EMIT1(PPC_nop, "nop") /* ori 0,0,0 */
359 #define ALU2(op, rd, ra, rb, rc) EMIT1(PPC_##op | GPR(rd)<<21 | GPR(ra)<<16 | GPR(rb)<<11 | (rc),\
360 "%s%s %s,%s,%s", #op, (rc)?".":"", gpn(rd), gpn(ra), gpn(rb))
361 #define BITALU2(op, ra, rs, rb, rc) EMIT1(PPC_##op | GPR(rs)<<21 | GPR(ra)<<16 | GPR(rb)<<11 | (rc),\
362 "%s%s %s,%s,%s", #op, (rc)?".":"", gpn(ra), gpn(rs), gpn(rb))
363 #define FPUAB(op, d, a, b, rc) EMIT1(PPC_##op | FPR(d)<<21 | FPR(a)<<16 | FPR(b)<<11 | (rc),\
364 "%s%s %s,%s,%s", #op, (rc)?".":"", gpn(d), gpn(a), gpn(b))
365 #define FPUAC(op, d, a, c, rc) EMIT1(PPC_##op | FPR(d)<<21 | FPR(a)<<16 | FPR(c)<<6 | (rc),\
366 "%s%s %s,%s,%s", #op, (rc)?".":"", gpn(d), gpn(a), gpn(c))
368 #define ADD(rd,ra,rb) ALU2(add, rd, ra, rb, 0)
369 #define ADD_(rd,ra,rb) ALU2(add, rd, ra, rb, 1)
370 #define ADDO(rd,ra,rb) ALU2(addo, rd, ra, rb, 0)
371 #define ADDO_(rd,ra,rb) ALU2(addo, rd, ra, rb, 1)
372 #define SUBF(rd,ra,rb) ALU2(subf, rd, ra, rb, 0)
373 #define SUBF_(rd,ra,rb) ALU2(subf, rd, ra, rb, 1)
375 #define AND(rd,rs,rb) BITALU2(and, rd, rs, rb, 0)
376 #define AND_(rd,rs,rb) BITALU2(and, rd, rs, rb, 1)
377 #define OR(rd,rs,rb) BITALU2(or, rd, rs, rb, 0)
378 #define OR_(rd,rs,rb) BITALU2(or, rd, rs, rb, 1)
379 #define NOR(rd,rs,rb) BITALU2(nor, rd, rs, rb, 0)
380 #define NOR_(rd,rs,rb) BITALU2(nor, rd, rs, rb, 1)
381 #define SLW(rd,rs,rb) BITALU2(slw, rd, rs, rb, 0)
382 #define SLW_(rd,rs,rb) BITALU2(slw, rd, rs, rb, 1)
383 #define SRW(rd,rs,rb) BITALU2(srw, rd, rs, rb, 0)
384 #define SRW_(rd,rs,rb) BITALU2(srw, rd, rs, rb, 1)
385 #define SRAW(rd,rs,rb) BITALU2(sraw, rd, rs, rb, 0)
386 #define SRAW_(rd,rs,rb) BITALU2(sraw, rd, rs, rb, 1)
387 #define XOR(rd,rs,rb) BITALU2(xor, rd, rs, rb, 0)
388 #define XOR_(rd,rs,rb) BITALU2(xor, rd, rs, rb, 1)
390 #define SLD(rd,rs,rb) BITALU2(sld, rd, rs, rb, 0)
391 #define SRD(rd,rs,rb) BITALU2(srd, rd, rs, rb, 0)
392 #define SRAD(rd,rs,rb) BITALU2(srad, rd, rs, rb, 0)
394 #define FADD(rd,ra,rb) FPUAB(fadd, rd, ra, rb, 0)
395 #define FADD_(rd,ra,rb) FPUAB(fadd, rd, ra, rb, 1)
396 #define FDIV(rd,ra,rb) FPUAB(fdiv, rd, ra, rb, 0)
397 #define FDIV_(rd,ra,rb) FPUAB(fdiv, rd, ra, rb, 1)
398 #define FMUL(rd,ra,rb) FPUAC(fmul, rd, ra, rb, 0)
399 #define FMUL_(rd,ra,rb) FPUAC(fmul, rd, ra, rb, 1)
400 #define FSUB(rd,ra,rb) FPUAB(fsub, rd, ra, rb, 0)
401 #define FSUB_(rd,ra,rb) FPUAB(fsub, rd, ra, rb, 1)
403 #define MULLI(rd,ra,simm) EMIT1(PPC_mulli | GPR(rd)<<21 | GPR(ra)<<16 | uint16_t(simm),\
404 "mulli %s,%s,%d", gpn(rd), gpn(ra), int16_t(simm))
405 #define MULLW(rd,ra,rb) EMIT1(PPC_mullw | GPR(rd)<<21 | GPR(ra)<<16 | GPR(rb)<<11,\
406 "mullw %s,%s,%s", gpn(rd), gpn(ra), gpn(rb))
408 // same as ALU2 with rs=rb, for simplified mnemonics
409 #define ALU1(op, ra, rs, rc) EMIT1(PPC_##op | GPR(rs)<<21 | GPR(ra)<<16 | GPR(rs)<<11 | (rc),\
410 "%s%s %s,%s", #op, (rc)?".":"", gpn(ra), gpn(rs))
412 #define MR(rd, rs) ALU1(mr, rd, rs, 0) // or rd,rs,rs
413 #define MR_(rd, rs) ALU1(mr, rd, rs, 1) // or. rd,rs,rs
414 #define NOT(rd, rs) ALU1(not, rd, rs, 0) // nor rd,rs,rs
415 #define NOT_(rd, rs) ALU1(not, rd, rs, 0) // nor. rd,rs,rs
417 #define EXTSW(rd, rs) EMIT1(PPC_extsw | GPR(rs)<<21 | GPR(rd)<<16,\
418 "extsw %s,%s", gpn(rd), gpn(rs))
420 #define NEG(rd, rs) EMIT1(PPC_neg | GPR(rd)<<21 | GPR(rs)<<16, "neg %s,%s", gpn(rd), gpn(rs))
421 #define FNEG(rd,rs) EMIT1(PPC_fneg | FPR(rd)<<21 | FPR(rs)<<11, "fneg %s,%s", gpn(rd), gpn(rs))
422 #define FMR(rd,rb) EMIT1(PPC_fmr | FPR(rd)<<21 | FPR(rb)<<11, "fmr %s,%s", gpn(rd), gpn(rb))
423 #define FCFID(rd,rs) EMIT1(PPC_fcfid | FPR(rd)<<21 | FPR(rs)<<11, "fcfid %s,%s", gpn(rd), gpn(rs))
425 #define JMP(addr) br(addr, 0)
427 #define SPR(spr) ((R##spr)>>5|(R##spr&31)<<5)
428 #define MTSPR(spr,rs) EMIT1(PPC_mtspr | GPR(rs)<<21 | SPR(spr)<<11,\
429 "mt%s %s", #spr, gpn(rs))
430 #define MFSPR(rd,spr) EMIT1(PPC_mfspr | GPR(rd)<<21 | SPR(spr)<<11,\
431 "mf%s %s", #spr, gpn(rd))
433 #define MTXER(r) MTSPR(xer, r)
434 #define MTLR(r) MTSPR(lr, r)
435 #define MTCTR(r) MTSPR(ctr, r)
437 #define MFXER(r) MFSPR(r, xer)
438 #define MFLR(r) MFSPR(r, lr)
439 #define MFCTR(r) MFSPR(r, ctr)
441 #define MEMd(op, r, d, a) do {\
442 NanoAssert(isS16(d));\
443 EMIT1(PPC_##op | GPR(r)<<21 | GPR(a)<<16 | uint16_t(d), "%s %s,%d(%s)", #op, gpn(r), int16_t(d), gpn(a));\
444 } while(0) /* no addr */
446 #define FMEMd(op, r, d, b) do {\
447 NanoAssert(isS16(d));\
448 EMIT1(PPC_##op | FPR(r)<<21 | GPR(b)<<16 | uint16_t(d), "%s %s,%d(%s)", #op, gpn(r), int16_t(d), gpn(b));\
449 } while(0) /* no addr */
451 #define MEMx(op, r, a, b) EMIT1(PPC_##op | GPR(r)<<21 | GPR(a)<<16 | GPR(b)<<11,\
452 "%s %s,%s,%s", #op, gpn(r), gpn(a), gpn(b))
453 #define FMEMx(op, r, a, b) EMIT1(PPC_##op | FPR(r)<<21 | GPR(a)<<16 | GPR(b)<<11,\
454 "%s %s,%s,%s", #op, gpn(r), gpn(a), gpn(b))
456 #define MEMux(op, rs, ra, rb) EMIT1(PPC_##op | GPR(rs)<<21 | GPR(ra)<<16 | GPR(rb)<<11,\
457 "%s %s,%s,%s", #op, gpn(rs), gpn(ra), gpn(rb))
459 #define LBZ(r, d, b) MEMd(lbz, r, d, b)
460 #define LHZ(r, d, b) MEMd(lhz, r, d, b)
461 #define LWZ(r, d, b) MEMd(lwz, r, d, b)
462 #define LD(r, d, b) MEMd(ld, r, d, b)
463 #define LBZX(r, a, b) MEMx(lbzx, r, a, b)
464 #define LHZX(r, a, b) MEMx(lhzx, r, a, b)
465 #define LWZX(r, a, b) MEMx(lwzx, r, a, b)
466 #define LDX(r, a, b) MEMx(ldx, r, a, b)
468 // store word (32-bit integer)
469 #define STW(r, d, b) MEMd(stw, r, d, b)
470 #define STWU(r, d, b) MEMd(stwu, r, d, b)
471 #define STWX(s, a, b) MEMx(stwx, s, a, b)
472 #define STWUX(s, a, b) MEMux(stwux, s, a, b)
475 #define STB(r, d, b) MEMd(stb, r, d, b)
476 #define STBX(s, a, b) MEMx(stbx, s, a, b)
478 // store double (64-bit float)
479 #define STD(r, d, b) MEMd(std, r, d, b)
480 #define STDU(r, d, b) MEMd(stdu, r, d, b)
481 #define STDX(s, a, b) MEMx(stdx, s, a, b)
482 #define STDUX(s, a, b) MEMux(stdux, s, a, b)
485 #define LP(r, d, b) LD(r, d, b)
486 #define STP(r, d, b) STD(r, d, b)
487 #define STPU(r, d, b) STDU(r, d, b)
488 #define STPX(s, a, b) STDX(s, a, b)
489 #define STPUX(s, a, b) STDUX(s, a, b)
491 #define LP(r, d, b) LWZ(r, d, b)
492 #define STP(r, d, b) STW(r, d, b)
493 #define STPU(r, d, b) STWU(r, d, b)
494 #define STPX(s, a, b) STWX(s, a, b)
495 #define STPUX(s, a, b) STWUX(s, a, b)
498 #define LFD(r, d, b) FMEMd(lfd, r, d, b)
499 #define LFDX(r, a, b) FMEMx(lfdx, r, a, b)
500 #define STFD(r, d, b) FMEMd(stfd, r, d, b)
501 #define STFDX(s, a, b) FMEMx(stfdx, s, a, b)
503 #define ALUI(op,rd,ra,d) EMIT1(PPC_##op | GPR(rd)<<21 | GPR(ra)<<16 | uint16_t(d),\
504 "%s %s,%s,%d (0x%x)", #op, gpn(rd), gpn(ra), int16_t(d), int16_t(d))
506 #define ADDI(rd,ra,d) ALUI(addi, rd, ra, d)
507 #define ADDIS(rd,ra,d) ALUI(addis, rd, ra, d)
509 // bitwise operators have different src/dest registers
510 #define BITALUI(op,rd,ra,d) EMIT1(PPC_##op | GPR(ra)<<21 | GPR(rd)<<16 | uint16_t(d),\
511 "%s %s,%s,%u (0x%x)", #op, gpn(rd), gpn(ra), uint16_t(d), uint16_t(d))
513 #define ANDI(rd,ra,d) BITALUI(andi, rd, ra, d)
514 #define ORI(rd,ra,d) BITALUI(ori, rd, ra, d)
515 #define ORIS(rd,ra,d) BITALUI(oris, rd, ra, d)
516 #define XORI(rd,ra,d) BITALUI(xori, rd, ra, d)
517 #define XORIS(rd,ra,d) BITALUI(xoris, rd, ra, d)
519 #define SUBI(rd,ra,d) EMIT1(PPC_addi | GPR(rd)<<21 | GPR(ra)<<16 | uint16_t(-(d)),\
520 "subi %s,%s,%d", gpn(rd), gpn(ra), (d))
522 #define LI(rd,v) EMIT1(PPC_addi | GPR(rd)<<21 | uint16_t(v),\
523 "li %s,%d (0x%x)", gpn(rd), int16_t(v), int16_t(v)) /* addi rd,0,v */
525 #define LIS(rd,v) EMIT1(PPC_addis | GPR(rd)<<21 | uint16_t(v),\
526 "lis %s,%d (0x%x)", gpn(rd), int16_t(v), int16_t(v)<<16) /* addis, rd,0,v */
528 #define MTCR(rs) /* mtcrf 0xff,rs */
529 #define MFCR(rd) EMIT1(PPC_mfcr | GPR(rd)<<21, "mfcr %s", gpn(rd))
531 #define CMPx(op, crfd, ra, rb, l) EMIT1(PPC_##op | (crfd)<<23 | (l)<<21 | GPR(ra)<<16 | GPR(rb)<<11,\
532 "%s%c cr%d,%s,%s", #op, (l)?'d':'w', (crfd), gpn(ra), gpn(rb))
534 #define CMPW(cr, ra, rb) CMPx(cmp, cr, ra, rb, 0)
535 #define CMPLW(cr, ra, rb) CMPx(cmpl, cr, ra, rb, 0)
536 #define CMPD(cr, ra, rb) CMPx(cmp, cr, ra, rb, 1)
537 #define CMPLD(cr, ra, rb) CMPx(cmpl, cr, ra, rb, 1)
539 #define CMPxI(cr, ra, simm, l) EMIT1(PPC_cmpi | (cr)<<23 | (l)<<21 | GPR(ra)<<16 | uint16_t(simm),\
540 "cmp%ci cr%d,%s,%d (0x%x)", (l)?'d':'w', (cr), gpn(ra), int16_t(simm), int16_t(simm))
542 #define CMPWI(cr, ra, simm) CMPxI(cr, ra, simm, 0)
543 #define CMPDI(cr, ra, simm) CMPxI(cr, ra, simm, 1)
545 #define CMPLxI(cr, ra, uimm, l) EMIT1(PPC_cmpli | (cr)<<23 | (l)<<21 | GPR(ra)<<16 | uint16_t(uimm),\
546 "cmp%ci cr%d,%s,%d (0x%x)", (l)?'d':'w', (cr), gpn(ra), uint16_t(uimm), uint16_t(uimm))
548 #define CMPLWI(cr, ra, uimm) CMPLxI(cr, ra, uimm, 0)
549 #define CMPLDI(cr, ra, uimm) CMPLxI(cr, ra, uimm, 1)
551 #define FCMPx(op, crfd, ra, rb) EMIT1(PPC_##op | (crfd)<<23 | FPR(ra)<<16 | FPR(rb)<<11,\
552 "%s cr%d,%s,%s", #op, (crfd), gpn(ra), gpn(rb))
554 #define FCMPU(cr, ra, rb) FCMPx(fcmpu, cr, ra, rb)
556 #define CROR(cr,d,a,b) EMIT1(PPC_cror | (4*(cr)+COND_##d)<<21 | (4*(cr)+COND_##a)<<16 | (4*(cr)+COND_##b)<<11,\
557 "cror %d,%d,%d", 4*(cr)+COND_##d, 4*(cr)+COND_##a, 4*(cr)+COND_##b)
559 #define RLWINM(rd,rs,sh,mb,me) EMIT1(PPC_rlwinm | GPR(rs)<<21 | GPR(rd)<<16 | (sh)<<11 | (mb)<<6 | (me)<<1,\
560 "rlwinm %s,%s,%d,%d,%d", gpn(rd), gpn(rs), (sh), (mb), (me))
562 #define LO5(sh) ((sh) & 31)
563 #define BIT6(sh) (((sh) >> 5) & 1)
564 #define SPLITMB(mb) (LO5(mb)<<1 | BIT6(mb))
566 #define RLDICL(rd,rs,sh,mb) \
567 EMIT1(PPC_rldicl | GPR(rs)<<21 | GPR(rd)<<16 | LO5(sh)<<11 | SPLITMB(mb)<<5 | BIT6(sh)<<1,\
568 "rldicl %s,%s,%d,%d", gpn(rd), gpn(rs), (sh), (mb))
570 // clrldi d,s,n => rldicl d,s,0,n
571 #define CLRLDI(rd,rs,n) \
572 EMIT1(PPC_rldicl | GPR(rs)<<21 | GPR(rd)<<16 | SPLITMB(n)<<5,\
573 "clrldi %s,%s,%d", gpn(rd), gpn(rs), (n))
575 #define RLDIMI(rd,rs,sh,mb) \
576 EMIT1(PPC_rldimi | GPR(rs)<<21 | GPR(rd)<<16 | LO5(sh)<<11 | SPLITMB(mb)<<5 | BIT6(sh)<<1,\
577 "rldimi %s,%s,%d,%d", gpn(rd), gpn(rs), (sh), (mb))
579 // insrdi rD,rS,n,b => rldimi rD,rS,64-(b+n),b: insert n bit value into rD starting at b
580 #define INSRDI(rd,rs,n,b) \
581 EMIT1(PPC_rldimi | GPR(rs)<<21 | GPR(rd)<<16 | LO5(64-((b)+(n)))<<11 | SPLITMB(b)<<5 | BIT6(64-((b)+(n)))<<1,\
582 "insrdi %s,%s,%d,%d", gpn(rd), gpn(rs), (n), (b))
584 #define EXTRWI(rd,rs,n,b) EMIT1(PPC_rlwinm | GPR(rs)<<21 | GPR(rd)<<16 | ((n)+(b))<<11 | (32-(n))<<6 | 31<<1,\
585 "extrwi %s,%s,%d,%d", gpn(rd), gpn(rs), (n), (b))
587 // sldi rd,rs,n (n<64) => rldicr rd,rs,n,63-n
588 #define SLDI(rd,rs,n) EMIT1(PPC_rldicr | GPR(rs)<<21 | GPR(rd)<<16 | LO5(n)<<11 | SPLITMB(63-(n))<<5 | BIT6(n)<<1,\
589 "sldi %s,%s,%d", gpn(rd), gpn(rs), (n))
591 #define SLWI(rd,rs,n) EMIT1(PPC_rlwinm | GPR(rs)<<21 | GPR(rd)<<16 | (n)<<11 | 0<<6 | (31-(n))<<1,\
592 "slwi %s,%s,%d", gpn(rd), gpn(rs), (n))
593 #define SRWI(rd,rs,n) EMIT1(PPC_rlwinm | GPR(rs)<<21 | GPR(rd)<<16 | (32-(n))<<11 | (n)<<6 | 31<<1,\
594 "slwi %s,%s,%d", gpn(rd), gpn(rs), (n))
595 #define SRAWI(rd,rs,n) EMIT1(PPC_srawi | GPR(rs)<<21 | GPR(rd)<<16 | (n)<<11,\
596 "srawi %s,%s,%d", gpn(rd), gpn(rs), (n))
598 } // namespace nanojit
600 #endif // __nanojit_NativePPC__