Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / nanojit / NativeMIPS.h
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
5  *
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/
10  *
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
14  * License.
15  *
16  * The Original Code is [Open Source Virtual Machine].
17  *
18  * The Initial Developer of the Original Code is
19  * MIPS Technologies Inc
20  * Portions created by the Initial Developer are Copyright (C) 2009
21  * the Initial Developer. All Rights Reserved.
22  *
23  * Contributor(s):
24  *   Chris Dearman <chris@mips.com>
25  *
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.
37  *
38  * ***** END LICENSE BLOCK ***** */
39
40 #ifndef __nanojit_NativeMIPS__
41 #define __nanojit_NativeMIPS__
42
43 #include "../vprof/vprof.h"
44 #ifdef PERFM
45 #define DOPROF
46 #endif
47 #define count_instr()   _nvprof("mips", 1)
48 #define count_mov()     do { _nvprof("mips-mov", 1); count_instr(); } while (0)
49 #define count_jmp()     do { _nvprof("mips-jmp", 1); count_instr(); } while (0)
50 #define count_prolog()  do { _nvprof("mips-prolog", 1); count_instr(); } while (0)
51 #define count_alu()     do { _nvprof("mips-alu", 1); count_instr(); } while (0)
52 #define count_misc()    do { _nvprof("mips-misc", 1); count_instr(); } while (0)
53 #define count_fpu()     do { _nvprof("mips-fpu", 1); count_instr(); } while (0)
54 #define count_br()      do { _nvprof("mips-br", 1); count_instr(); } while (0)
55
56 namespace nanojit
57 {
58     // Req: NJ_MAX_STACK_ENTRY is number of instructions to hold in LIR stack
59 #if 0
60     // FIXME: Inconsistent use in signed/unsigned expressions makes this generate errors
61     static const uint32_t NJ_MAX_STACK_ENTRY = 4096;
62 #else
63 #define NJ_MAX_STACK_ENTRY 4096
64 #endif
65     static const int NJ_ALIGN_STACK = 8;
66
67     typedef uint32_t NIns;                // REQ: Instruction count
68     typedef uint64_t RegisterMask;        // REQ: Large enough to hold LastRegNum-FirstRegNum bits
69 #define _rmask_(r)        (1LL<<(r))
70
71     typedef uint32_t Register;            // REQ: Register identifiers
72     // Register numbers for Native code generator
73     static const Register
74         ZERO = { 0 },
75         AT = { 1 },
76         V0 = { 2 },
77         V1 = { 3 },
78         A0 = { 4 },
79         A1 = { 5 },
80         A2 = { 6 },
81         A3 = { 7 },
82
83         T0 = { 8 },
84         T1 = { 9 },
85         T2 = { 10 },
86         T3 = { 11 },
87         T4 = { 12 },
88         T5 = { 13 },
89         T6 = { 14 },
90         T7 = { 15 },
91
92         S0 = { 16 },
93         S1 = { 17 },
94         S2 = { 18 },
95         S3 = { 19 },
96         S4 = { 20 },
97         S5 = { 21 },
98         S6 = { 22 },
99         S7 = { 23 },
100
101         T8 = { 24 },
102         T9 = { 25 },
103         K0 = { 26 },
104         K1 = { 27 },
105         GP = { 28 },
106         SP = { 29 },
107         FP = { 30 },
108         RA = { 31 },
109
110         F0 = { 32 },
111         F1 = { 33 },
112         F2 = { 34 },
113         F3 = { 35 },
114         F4 = { 36 },
115         F5 = { 37 },
116         F6 = { 38 },
117         F7 = { 39 },
118
119         F8 = { 40 },
120         F9 = { 41 },
121         F10 = { 42 },
122         F11 = { 43 },
123         F12 = { 44 },
124         F13 = { 45 },
125         F14 = { 46 },
126         F15 = { 47 },
127
128         F16 = { 48 },
129         F17 = { 49 },
130         F18 = { 50 },
131         F19 = { 51 },
132         F20 = { 52 },
133         F21 = { 53 },
134         F22 = { 54 },
135         F23 = { 55 },
136
137         F24 = { 56 },
138         F25 = { 57 },
139         F26 = { 58 },
140         F27 = { 59 },
141         F28 = { 60 },
142         F29 = { 61 },
143         F30 = { 62 },
144         F31 = { 63 },
145
146         // FP register aliases
147         FV0 = F0,
148         FV1 = F2,
149         FA0 = F12,
150         FA1 = F14,
151         FT0 = F4,
152         FT1 = F6,
153         FT2 = F8,
154         FT3 = F10,
155         FT4 = F16,
156         FT5 = F18,
157         FS0 = F20,
158         FS1 = F22,
159         FS2 = F24,
160         FS3 = F26,
161         FS4 = F28,
162         FS5 = F30,
163
164         deprecated_UnknownReg = { 127 };    // XXX: remove eventually, see bug 538924
165
166     static const uint32_t FirstRegNum = ZERO;
167     static const uint32_t LastRegNum = F31;
168 }
169
170 #define NJ_USE_UINT32_REGISTER 1
171 #include "NativeCommon.h"
172
173 namespace nanojit {
174     // REQ: register names
175     verbose_only(extern const char* regNames[];)
176
177     // REQ: Bytes of icache to flush after Assembler::patch
178     const size_t LARGEST_BRANCH_PATCH = 2 * sizeof(NIns);
179
180     // REQ: largest value passed to underrunProtect
181     static const int LARGEST_UNDERRUN_PROT = 32;
182
183     // REQ: Number of callee saved registers
184 #ifdef FPCALLEESAVED
185     static const int NumSavedRegs = 14;
186 #else
187     static const int NumSavedRegs = 8;
188 #endif
189
190     // REQ: Callee saved registers
191     const RegisterMask SavedRegs =
192 #ifdef FPCALLEESAVED
193                     _rmask_(FS0) | _rmask_(FS1) | _rmask_(FS2) |
194                     _rmask_(FS3) | _rmask_(FS4) | _rmask_(FS5) |
195 #endif
196                     _rmask_(S0) | _rmask_(S1) | _rmask_(S2) | _rmask_(S3) |
197                     _rmask_(S4) | _rmask_(S5) | _rmask_(S6) | _rmask_(S7);
198
199     // REQ: General purpose registers
200     static const RegisterMask GpRegs =
201                     _rmask_(V0) | _rmask_(V1) |
202                     _rmask_(A0) | _rmask_(A1) | _rmask_(A2) | _rmask_(A3) |
203                     _rmask_(S0) | _rmask_(S1) | _rmask_(S2) | _rmask_(S3) |
204                     _rmask_(S4) | _rmask_(S5) | _rmask_(S6) | _rmask_(S7) |
205                     _rmask_(T0) | _rmask_(T1) | _rmask_(T2) | _rmask_(T3) |
206                     _rmask_(T4) | _rmask_(T5) | _rmask_(T6) | _rmask_(T7) |
207                     _rmask_(T8) | _rmask_(T9);
208
209     // REQ: Floating point registers
210     static const RegisterMask FpRegs =
211 #ifdef FPCALLEESAVED
212                     _rmask_(FS0) | _rmask_(FS1) | _rmask_(FS2) |
213                     _rmask_(FS3) | _rmask_(FS4) | _rmask_(FS5) |
214 #endif
215                     _rmask_(FV0) | _rmask_(FV1) |
216                     _rmask_(FA0) | _rmask_(FA1) |
217                     _rmask_(FT0) | _rmask_(FT1) | _rmask_(FT2) |
218                     _rmask_(FT3) | _rmask_(FT4) | _rmask_(FT5);
219
220     static const RegisterMask AllowableFlagRegs = GpRegs;        // REQ: Registers that can hold flag results FIXME
221
222     static inline bool IsFpReg(Register r)
223     {
224         return (_rmask_(r) & FpRegs) != 0;
225     }
226
227     static inline bool IsGpReg(Register r)
228     {
229         return (_rmask_(r) & GpRegs) != 0;
230     }
231
232 #define GPR(r) ((r)&31)
233 #define FPR(r) ((r)&31)
234
235 // REQ: Platform specific declarations to include in Stats structure
236 #define DECLARE_PLATFORM_STATS()
237
238 // REQ: Platform specific declarations to include in Assembler class
239 #define DECLARE_PLATFORM_ASSEMBLER()                                    \
240     const static Register argRegs[4];                                   \
241     const static Register retRegs[2];                                   \
242     void nativePageSetup(void);                                         \
243     void nativePageReset(void);                                         \
244     void underrunProtect(int bytes);                                    \
245     bool hardenNopInsertion(const Config& /*c*/) { return false; }      \
246     NIns *_nSlot;                                                       \
247     NIns *_nExitSlot;                                                   \
248     int max_out_args;                                                   \
249     Register ovreg;                                                     \
250                                                                         \
251     void asm_ldst(int op, Register r, int offset, Register b);          \
252     void asm_ldst64(bool store, Register fr, int offset, Register b);   \
253     void asm_store_imm64(LIns *value, int dr, Register rbase);          \
254     void asm_li32(Register r, int32_t imm);                             \
255     void asm_li_d(Register fr, int32_t msw, int32_t lsw);               \
256     void asm_li(Register r, int32_t imm);                               \
257     void asm_j(NIns*, bool bdelay);                                     \
258     void asm_cmp(LOpcode condop, LIns *a, LIns *b, Register cr);        \
259     void asm_move(Register d, Register s);                              \
260     void asm_regarg(ArgType ty, LIns* p, Register r);                   \
261     void asm_stkarg(LIns* arg, int stkd);                               \
262     void asm_arg(ArgType ty, LIns* arg, Register& r, Register& fr, int& stkd);     \
263     void asm_arg_64(LIns* arg, Register& r, Register& fr, int& stkd);   \
264     NIns *asm_branchtarget(NIns*);                                      \
265     NIns *asm_bxx(bool, LOpcode, Register, Register, NIns*);
266
267 // REQ: Platform specific declarations to include in RegAlloc class
268 #define DECLARE_PLATFORM_REGALLOC()
269
270 // REQ:
271 #define swapptrs()  do {                                                \
272         NIns* _tins = _nIns; _nIns = _nExitIns; _nExitIns = _tins;      \
273         NIns* _nslot = _nSlot; _nSlot = _nExitSlot; _nExitSlot = _nslot; \
274     } while (0)
275
276 #define TODO(x) do { verbose_only(avmplus::AvmLog(#x);) NanoAssertMsgf(false, "%s", #x); } while (0)
277 #ifdef MIPSDEBUG
278 #define TAG(fmt, ...) do { debug_only(verbose_outputf("             # MIPS: " fmt, ##__VA_ARGS__);) } while (0)
279 #else
280 #define TAG(fmt, ...) do { } while (0)
281 #endif
282
283 #define EMIT(ins, fmt, ...) do {                   \
284         underrunProtect(4);                        \
285         *(--_nIns) = (NIns) (ins);                 \
286         debug_only(codegenBreak(_nIns);)           \
287         asm_output(fmt, ##__VA_ARGS__);            \
288     } while (0)
289
290 // Emit code in trampoline/literal area
291 // Assume that underrunProtect has already been called
292 // This is a bit hacky...
293 #define TRAMP(ins, fmt, ...) do {                                       \
294         verbose_only(                                                   \
295                      NIns *save_nIns = _nIns; _nIns = _nSlot;           \
296                      )                                                  \
297         *_nSlot = (NIns)ins;                                            \
298         debug_only(codegenBreak(_nSlot);)                               \
299         _nSlot++;                                                       \
300         verbose_only(setOutputForEOL("<= trampoline");)                 \
301         asm_output(fmt, ##__VA_ARGS__);                                 \
302         verbose_only(                                                   \
303                      _nIns = save_nIns;                                 \
304                      )                                                  \
305     } while (0)
306
307 #define MR(d, s)        asm_move(d, s)
308
309 // underrun guarantees that there is always room to insert a jump and branch delay slot
310 #define JMP(t)          asm_j(t, true)
311
312 // Opcodes: bits 31..26
313 #define OP_SPECIAL      0x00
314 #define OP_REGIMM       0x01
315 #define OP_J            0x02
316 #define OP_JAL          0x03
317 #define OP_BEQ          0x04
318 #define OP_BNE          0x05
319 #define OP_ADDIU        0x09
320 #define OP_SLTIU        0x0b
321 #define OP_ANDI         0x0c
322 #define OP_ORI          0x0d
323 #define OP_XORI         0x0e
324 #define OP_LUI          0x0f
325 #define OP_COP1         0x11
326 #define OP_COP1X        0x13
327 #define OP_SPECIAL2     0x1c
328 #define OP_LB           0x20
329 #define OP_LH           0x21
330 #define OP_LW           0x23
331 #define OP_LBU          0x24
332 #define OP_LHU          0x25
333 #define OP_SB           0x28
334 #define OP_SH           0x29
335 #define OP_SW           0x2b
336 #define OP_LWC1         0x31
337 #define OP_LDC1         0x35
338 #define OP_SWC1         0x39
339 #define OP_SDC1         0x3d
340
341 // REGIMM: bits 20..16
342 #define REGIMM_BLTZ     0x00
343 #define REGIMM_BGEZ     0x01
344
345 // COP1: bits 25..21
346 #define COP1_ADD        0x00
347 #define COP1_SUB        0x01
348 #define COP1_MUL        0x02
349 #define COP1_DIV        0x03
350 #define COP1_MOV        0x06
351 #define COP1_NEG        0x07
352 #define COP1_BC         0x08
353 #define COP1_TRUNCW     0x0d
354 #define COP1_CVTD       0x21
355
356 // COP1X: bits 5..0
357 #define COP1X_LDXC1     0x01
358 #define COP1X_SDXC1     0x09
359
360 // SPECIAL: bits 5..0
361 #define SPECIAL_SLL     0x00
362 #define SPECIAL_MOVCI   0x01
363 #define SPECIAL_SRL     0x02
364 #define SPECIAL_SRA     0x03
365 #define SPECIAL_SLLV    0x04
366 #define SPECIAL_SRLV    0x06
367 #define SPECIAL_SRAV    0x07
368 #define SPECIAL_JR      0x08
369 #define SPECIAL_JALR    0x09
370 #define SPECIAL_MOVN    0x0b
371 #define SPECIAL_MFHI    0x10
372 #define SPECIAL_MFLO    0x12
373 #define SPECIAL_MULT    0x18
374 #define SPECIAL_ADDU    0x21
375 #define SPECIAL_SUBU    0x23
376 #define SPECIAL_AND     0x24
377 #define SPECIAL_OR      0x25
378 #define SPECIAL_XOR     0x26
379 #define SPECIAL_NOR     0x27
380 #define SPECIAL_SLT     0x2a
381 #define SPECIAL_SLTU    0x2b
382
383 // SPECIAL2: bits 5..0
384 #define SPECIAL2_MUL    0x02
385
386 // FORMAT: bits 25..21
387 #define FMT_S           0x10
388 #define FMT_D           0x11
389 #define FMT_W           0x14
390 #define FMT_L           0x15
391 #define FMT_PS          0x16
392
393 // CONDITION: bits 4..0
394 #define COND_F          0x0
395 #define COND_UN         0x1
396 #define COND_EQ         0x2
397 #define COND_UEQ        0x3
398 #define COND_OLT        0x4
399 #define COND_ULT        0x5
400 #define COND_OLE        0x6
401 #define COND_ULE        0x7
402 #define COND_SF         0x8
403 #define COND_NGLE       0x9
404 #define COND_SEQ        0xa
405 #define COND_NGL        0xb
406 #define COND_LT         0xc
407 #define COND_NGE        0xd
408 #define COND_LE         0xe
409 #define COND_NGT        0xf
410
411 // Helper definitions to encode different classes of MIPS instructions
412 // Parameters are in instruction order
413
414 #define R_FORMAT(op, rs, rt, rd, re, func)                              \
415     (((op)<<26)|(GPR(rs)<<21)|(GPR(rt)<<16)|(GPR(rd)<<11)|((re)<<6)|(func))
416
417 #define I_FORMAT(op, rs, rt, simm)                              \
418     (((op)<<26)|(GPR(rs)<<21)|(GPR(rt)<<16)|((simm)&0xffff))
419
420 #define J_FORMAT(op, index)                     \
421     (((op)<<26)|(index))
422
423 #define U_FORMAT(op, rs, rt, uimm)                              \
424     (((op)<<26)|(GPR(rs)<<21)|(GPR(rt)<<16)|((uimm)&0xffff))
425
426 #define F_FORMAT(op, ffmt, ft, fs, fd, func)                            \
427     (((op)<<26)|((ffmt)<<21)|(FPR(ft)<<16)|(FPR(fs)<<11)|(FPR(fd)<<6)|(func))
428
429 #define oname(op) Assembler::oname[op]
430 #define cname(cond) Assembler::cname[cond]
431 #define fname(ffmt) Assembler::fname[ffmt]
432 #define fpn(fr) gpn(fr)
433
434 #define BOFFSET(targ)    (uint32_t(targ - (_nIns+1)))
435
436 #define LDST(op, rt, offset, base)                                      \
437     do { count_misc(); EMIT(I_FORMAT(op, base, rt, offset),             \
438                             "%s %s, %d(%s)", oname[op], gpn(rt), offset, gpn(base)); } while (0)
439
440 #define BX(op, rs, rt, targ)                                            \
441     do { count_br(); EMIT(I_FORMAT(op, rs, rt, BOFFSET(targ)),          \
442                           "%s %s, %s, %p", oname[op], gpn(rt), gpn(rs), targ); } while (0)
443
444 // MIPS instructions
445 // Parameters are in "assembler" order
446 #define ADDIU(rt, rs, simm)                                             \
447     do { count_alu(); EMIT(I_FORMAT(OP_ADDIU, rs, rt, simm),            \
448                            "addiu %s, %s, %d", gpn(rt), gpn(rs), simm); } while (0)
449
450 #define trampADDIU(rt, rs, simm)                                        \
451     do { count_alu(); TRAMP(I_FORMAT(OP_ADDIU, rs, rt, simm),           \
452                             "addiu %s, %s, %d", gpn(rt), gpn(rs), simm); } while (0)
453
454 #define ADDU(rd, rs, rt)                                                \
455     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_ADDU), \
456                            "addu %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
457
458 #define AND(rd, rs, rt)                                                 \
459     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_AND), \
460                            "and %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
461
462 #define ANDI(rt, rs, uimm)                                              \
463     do { count_alu(); EMIT(U_FORMAT(OP_ANDI, rs, rt, uimm),             \
464                            "andi %s, %s, 0x%x", gpn(rt), gpn(rs), ((uimm)&0xffff)); } while (0)
465
466 #define BC1F(targ)                                                      \
467     do { count_br(); EMIT(I_FORMAT(OP_COP1, COP1_BC, 0, BOFFSET(targ)), \
468                           "bc1f %p", targ); } while (0)
469
470 #define BC1T(targ)                                                      \
471     do { count_br(); EMIT(I_FORMAT(OP_COP1, COP1_BC, 1, BOFFSET(targ)), \
472                           "bc1t %p", targ); } while (0)
473
474 #define B(targ)                 BX(OP_BEQ, ZERO, ZERO, targ)
475 #define BEQ(rs, rt, targ)       BX(OP_BEQ, rs, rt, targ)
476 #define BNE(rs, rt, targ)       BX(OP_BNE, rs, rt, targ)
477 #define BLEZ(rs, targ)          BX(OP_BLEZ, rs, ZERO, targ)
478 #define BGTZ(rs, targ)          BX(OP_BGTZ, rs, ZERO, targ)
479 #define BGEZ(rs, targ)          BX(OP_REGIMM, rs, REGIMM_BGEZ, targ)
480 #define BLTZ(rs, targ)          BX(OP_REGIMM, rs, REGIMM_BLTZ, targ)
481
482 #define JINDEX(dest) ((uint32_t(dest)>>2)&0x03ffffff)
483
484 #define J(dest)                                             \
485     do { count_jmp(); EMIT(J_FORMAT(OP_J, JINDEX(dest)),    \
486                            "j %p", dest); } while (0)
487
488 #define trampJ(dest)                                        \
489     do { count_jmp(); TRAMP(J_FORMAT(OP_J, JINDEX(dest)),   \
490                             "j %p", dest); } while (0)
491
492 #define JAL(dest)                                           \
493     do { count_jmp(); EMIT(J_FORMAT(OP_JAL, JINDEX(dest)),  \
494                            "jal %p", dest); } while (0)
495
496 #define JALR(rs)                                                        \
497     do { count_jmp(); EMIT(R_FORMAT(OP_SPECIAL, rs, 0, RA, 0, SPECIAL_JALR), \
498                            "jalr %s", gpn(rs)); } while (0)
499
500 #define JR(rs)                                                            \
501     do { count_jmp(); EMIT(R_FORMAT(OP_SPECIAL, rs, 0, 0, 0, SPECIAL_JR), \
502                            "jr %s", gpn(rs)); } while (0)
503 #define trampJR(rs)                                                     \
504     do { count_jmp(); TRAMP(R_FORMAT(OP_SPECIAL, rs, 0, 0, 0, SPECIAL_JR), \
505                             "jr %s", gpn(rs)); } while (0)
506
507 #define LB(rt, offset, base)                    \
508     LDST(OP_LB, rt, offset, base)
509
510 #define LH(rt, offset, base)                    \
511     LDST(OP_LH, rt, offset, base)
512
513 #define LUI(rt, uimm)                                                   \
514     do { count_alu(); EMIT(U_FORMAT(OP_LUI, 0, rt, uimm),               \
515                            "lui %s, 0x%x", gpn(rt), ((uimm)&0xffff)); } while (0)
516
517 #define LW(rt, offset, base)                    \
518     LDST(OP_LW, rt, offset, base)
519
520 #define MFHI(rd)                                                        \
521     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, 0, 0, rd, 0, SPECIAL_MFHI), \
522                            "mfhi %s", gpn(rd)); } while (0)
523
524 #define MFLO(rd)                                                        \
525     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, 0, 0, rd, 0, SPECIAL_MFLO), \
526                            "mflo %s", gpn(rd)); } while (0)
527
528 #define MUL(rd, rs, rt)                                                 \
529     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL2, rs, rt, rd, 0, SPECIAL2_MUL), \
530                            "mul %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
531
532 #define MULT(rs, rt)                                                    \
533     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, 0, 0, SPECIAL_MULT), \
534                            "mult %s, %s", gpn(rs), gpn(rt)); } while (0)
535
536 #define MOVE(rd, rs)                                                    \
537     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, ZERO, rd, 0, SPECIAL_ADDU), \
538                            "move %s, %s", gpn(rd), gpn(rs)); } while (0)
539
540 #define MOVN(rd, rs, rt)                                                \
541     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_MOVN), \
542                            "movn %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
543
544 #define NEGU(rd, rt)                                                    \
545     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, ZERO, rt, rd, 0, SPECIAL_SUBU), \
546                            "negu %s, %s", gpn(rd), gpn(rt)); } while (0)
547
548 #define NOP()                                                           \
549     do { count_misc(); EMIT(R_FORMAT(OP_SPECIAL, 0, 0, 0, 0, SPECIAL_SLL), \
550                             "nop"); } while (0)
551
552 #define trampNOP()                                                      \
553     do { count_misc(); TRAMP(R_FORMAT(OP_SPECIAL, 0, 0, 0, 0, SPECIAL_SLL), \
554                              "nop"); } while (0)
555
556 #define NOR(rd, rs, rt)                                                 \
557     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_NOR), \
558                            "nor %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
559
560 #define NOT(rd, rs)                                                     \
561     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, ZERO, rd, 0, SPECIAL_NOR), \
562                            "not %s, %s", gpn(rd), gpn(rs)); } while (0)
563
564 #define OR(rd, rs, rt)                                                  \
565     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_OR), \
566                            "or %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
567
568 #define ORI(rt, rs, uimm)                                               \
569     do { count_alu(); EMIT(U_FORMAT(OP_ORI, rs, rt, uimm),              \
570                            "ori %s, %s, 0x%x", gpn(rt), gpn(rs), ((uimm)&0xffff)); } while (0)
571
572 #define SLTIU(rt, rs, simm)                                             \
573     do { count_alu(); EMIT(I_FORMAT(OP_SLTIU, rs, rt, simm),            \
574                            "sltiu %s, %s, %d", gpn(rt), gpn(rs), simm); } while (0)
575
576 #define SLT(rd, rs, rt)                                                 \
577     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_SLT), \
578                            "slt %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
579
580 #define SLTU(rd, rs, rt)                                                \
581     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_SLTU), \
582                            "sltu %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
583
584 #define SLL(rd, rt, sa)                                                 \
585     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, 0, rt, rd, sa, SPECIAL_SLL), \
586                            "sll %s, %s, %d", gpn(rd), gpn(rt), sa); } while (0)
587
588 #define SLLV(rd, rt, rs)                                                \
589     do { count_misc(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_SLLV), \
590                             "sllv %s, %s, %s", gpn(rd), gpn(rt), gpn(rs)); } while (0)
591
592 #define SRA(rd, rt, sa)                                                 \
593     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, 0, rt, rd, sa, SPECIAL_SRA), \
594                            "sra %s, %s, %d", gpn(rd), gpn(rt), sa); } while (0)
595
596 #define SRAV(rd, rt, rs)                                                \
597     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_SRAV), \
598                            "srav %s, %s, %s", gpn(rd), gpn(rt), gpn(rs)); } while (0)
599
600 #define SRL(rd, rt, sa)                                                 \
601     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, 0, rt, rd, sa, SPECIAL_SRL), \
602                            "srl %s, %s, %d", gpn(rd), gpn(rt), sa); } while (0)
603
604 #define SRLV(rd, rt, rs)                                                \
605     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_SRLV), \
606                            "srlv %s, %s, %s", gpn(rd), gpn(rt), gpn(rs)); } while (0)
607
608 #define SUBU(rd, rs, rt)                                                \
609     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_SUBU), \
610                            "subu %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
611
612 #define SW(rt, offset, base)                    \
613     LDST(OP_SW, rt, offset, base)
614
615 #define XOR(rd, rs, rt)                                                 \
616     do { count_alu(); EMIT(R_FORMAT(OP_SPECIAL, rs, rt, rd, 0, SPECIAL_XOR), \
617                            "xor %s, %s, %s", gpn(rd), gpn(rs), gpn(rt)); } while (0)
618
619 #define XORI(rt, rs, uimm)                                              \
620     do { count_alu(); EMIT(U_FORMAT(OP_XORI, rs, rt, uimm),             \
621                            "xori %s, %s, 0x%x", gpn(rt), gpn(rs), ((uimm)&0xffff)); } while (0)
622
623
624 /* FPU instructions */
625 #ifdef NJ_SOFTFLOAT_SUPPORTED
626
627 #if !defined(__mips_soft_float) || __mips_soft_float != 1
628 #error NJ_SOFTFLOAT_SUPPORTED defined but not compiled with -msoft-float
629 #endif
630
631 #define LWC1(ft, offset, base)  NanoAssertMsg(0, "softfloat LWC1")
632 #define SWC1(ft, offset, base)  NanoAssertMsg(0, "softfloat SWC1")
633 #define LDC1(ft, offset, base)  NanoAssertMsg(0, "softfloat LDC1")
634 #define SDC1(ft, offset, base)  NanoAssertMsg(0, "softfloat SDC1")
635 #define LDXC1(fd, index, base)  NanoAssertMsg(0, "softfloat LDXC1")
636 #define SDXC1(fs, index, base)  NanoAssertMsg(0, "softfloat SDXC1")
637
638 #define MFC1(rt, fs)            NanoAssertMsg(0, "softfloat MFC1")
639 #define MTC1(rt, fs)            NanoAssertMsg(0, "softfloat MTC1")
640 #define MOVF(rt, fs, cc)        NanoAssertMsg(0, "softfloat MOVF")
641 #define CVT_D_W(fd, fs)         NanoAssertMsg(0, "softfloat CVT_D_W")
642 #define C_EQ_D(fs, ft)          NanoAssertMsg(0, "softfloat C_EQ_D")
643 #define C_LE_D(fs, ft)          NanoAssertMsg(0, "softfloat C_LE_D")
644 #define C_LT_D(fs, ft)          NanoAssertMsg(0, "softfloat C_LT_D")
645 #define ADD_D(fd, fs, ft)       NanoAssertMsg(0, "softfloat ADD_D")
646 #define DIV_D(fd, fs, ft)       NanoAssertMsg(0, "softfloat DIV_D")
647 #define MOV_D(fd, fs)           NanoAssertMsg(0, "softfloat MOV_D")
648 #define MUL_D(fd, fs, ft)       NanoAssertMsg(0, "softfloat MUL_D")
649 #define NEG_D(fd, fs)           NanoAssertMsg(0, "softfloat NEG_D")
650 #define SUB_D(fd, fs, ft)       NanoAssertMsg(0, "softfloat SUB_D")
651 #define TRUNC_W_D(fd,fs)        NanoAssertMsg(0, "softfloat TRUNC_W_D")
652
653 #else
654
655 #if defined(__mips_soft_float) && __mips_soft_float != 0
656 #error compiled with -msoft-float but NJ_SOFTFLOAT_SUPPORTED not defined
657 #endif
658
659 #define FOP_FMT2(ffmt, fd, fs, func, name)                              \
660     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, ffmt, 0, fs, fd, func),    \
661                            "%s.%s %s, %s", name, fname[ffmt], fpn(fd), fpn(fs)); } while (0)
662
663 #define FOP_FMT3(ffmt, fd, fs, ft, func, name)                          \
664     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, ffmt, ft, fs, fd, func),   \
665                            "%s.%s %s, %s, %s", name, fname[ffmt], fpn(fd), fpn(fs), fpn(ft)); } while (0)
666
667 #define C_COND_FMT(cond, ffmt, fs, ft)                                  \
668     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, ffmt, ft, fs, 0, 0x30|(cond)), \
669                            "c.%s.%s %s, %s", cname[cond], fname[ffmt], fpn(fs), fpn(ft)); } while (0)
670
671 #define MFC1(rt, fs)                                                    \
672     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, 0, rt, fs, 0, 0),          \
673                            "mfc1 %s, %s", gpn(rt), fpn(fs)); } while (0)
674
675 #define MTC1(rt, fs)                                                    \
676     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, 4, rt, fs, 0, 0),          \
677                            "mtc1 %s, %s", gpn(rt), fpn(fs)); } while (0)
678
679 #define MOVF(rd, rs, cc)                                                \
680     do { count_fpu(); EMIT(R_FORMAT(OP_SPECIAL, rs, (cc)<<2, rd, 0, SPECIAL_MOVCI), \
681                            "movf %s, %s, $fcc%d", gpn(rd), gpn(rs), cc); } while (0)
682
683 #define CVT_D_W(fd, fs)                                                 \
684     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, FMT_W, 0, fs, fd, COP1_CVTD), \
685                            "cvt.d.w %s, %s", fpn(fd), fpn(fs)); } while (0)
686
687 #define TRUNC_W_D(fd, fs)                                               \
688     do { count_fpu(); EMIT(F_FORMAT(OP_COP1, FMT_D, 0, fs, fd, COP1_TRUNCW), \
689                            "trunc.w.d %s, %s", fpn(fd), fpn(fs)); } while (0)
690
691
692 #define LWC1(ft, offset, base)  LDST(OP_LWC1, ft, offset, base)
693 #define SWC1(ft, offset, base)  LDST(OP_SWC1, ft, offset, base)
694 #define LDC1(ft, offset, base)  LDST(OP_LDC1, ft, offset, base)
695 #define SDC1(ft, offset, base)  LDST(OP_SDC1, ft, offset, base)
696 #define LDXC1(fd, index, base)                                          \
697     do { count_fpu(); EMIT(R_FORMAT(OP_COP1X, base, index, 0, fd, COP1X_LDXC1), \
698                            "ldxc1 %s, %s(%s)", fpn(fd), gpn(index), gpn(base)); } while (0)
699 #define SDXC1(fs, index, base)                                          \
700     do { count_fpu(); EMIT(R_FORMAT(OP_COP1X, base, index, fs, 0, COP1X_SDXC1), \
701                            "sdxc1 %s, %s(%s)", fpn(fs), gpn(index), gpn(base)); } while (0)
702
703 #define C_EQ_D(fs, ft)          C_COND_FMT(COND_EQ, FMT_D, fs, ft)
704 #define C_LE_D(fs, ft)          C_COND_FMT(COND_LE, FMT_D, fs, ft)
705 #define C_LT_D(fs, ft)          C_COND_FMT(COND_LT, FMT_D, fs, ft)
706 #define ADD_D(fd, fs, ft)       FOP_FMT3(FMT_D, fd, fs, ft, COP1_ADD, "add")
707 #define DIV_D(fd, fs, ft)       FOP_FMT3(FMT_D, fd, fs, ft, COP1_DIV, "div")
708 #define MOV_D(fd, fs)           FOP_FMT2(FMT_D, fd, fs, COP1_MOV, "mov")
709 #define MUL_D(fd, fs, ft)       FOP_FMT3(FMT_D, fd, fs, ft, COP1_MUL, "mul")
710 #define NEG_D(fd, fs)           FOP_FMT2(FMT_D, fd, fs, COP1_NEG, "neg")
711 #define SUB_D(fd, fs, ft)       FOP_FMT3(FMT_D, fd, fs, ft, COP1_SUB, "sub")
712 #endif
713
714 }
715 #endif // __nanojit_NativeMIPS__