Bug 607719 followup: deep tests that do not match the current config will run in...
[tamarin-stm.git] / nanojit / NativeMIPS.h
blobdf158b82a964e701ab84604425c059a6cac904d4
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
14 * License.
16 * The Original Code is [Open Source Virtual Machine].
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.
23 * Contributor(s):
24 * Chris Dearman <chris@mips.com>
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_NativeMIPS__
41 #define __nanojit_NativeMIPS__
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)
56 namespace nanojit
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;
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))
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 },
83 T0 = { 8 },
84 T1 = { 9 },
85 T2 = { 10 },
86 T3 = { 11 },
87 T4 = { 12 },
88 T5 = { 13 },
89 T6 = { 14 },
90 T7 = { 15 },
92 S0 = { 16 },
93 S1 = { 17 },
94 S2 = { 18 },
95 S3 = { 19 },
96 S4 = { 20 },
97 S5 = { 21 },
98 S6 = { 22 },
99 S7 = { 23 },
101 T8 = { 24 },
102 T9 = { 25 },
103 K0 = { 26 },
104 K1 = { 27 },
105 GP = { 28 },
106 SP = { 29 },
107 FP = { 30 },
108 RA = { 31 },
110 F0 = { 32 },
111 F1 = { 33 },
112 F2 = { 34 },
113 F3 = { 35 },
114 F4 = { 36 },
115 F5 = { 37 },
116 F6 = { 38 },
117 F7 = { 39 },
119 F8 = { 40 },
120 F9 = { 41 },
121 F10 = { 42 },
122 F11 = { 43 },
123 F12 = { 44 },
124 F13 = { 45 },
125 F14 = { 46 },
126 F15 = { 47 },
128 F16 = { 48 },
129 F17 = { 49 },
130 F18 = { 50 },
131 F19 = { 51 },
132 F20 = { 52 },
133 F21 = { 53 },
134 F22 = { 54 },
135 F23 = { 55 },
137 F24 = { 56 },
138 F25 = { 57 },
139 F26 = { 58 },
140 F27 = { 59 },
141 F28 = { 60 },
142 F29 = { 61 },
143 F30 = { 62 },
144 F31 = { 63 },
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,
164 deprecated_UnknownReg = { 127 }; // XXX: remove eventually, see bug 538924
166 static const uint32_t FirstRegNum = ZERO;
167 static const uint32_t LastRegNum = F31;
170 #define NJ_USE_UINT32_REGISTER 1
171 #include "NativeCommon.h"
173 namespace nanojit {
174 // REQ: register names
175 verbose_only(extern const char* regNames[];)
177 // REQ: Bytes of icache to flush after Assembler::patch
178 const size_t LARGEST_BRANCH_PATCH = 2 * sizeof(NIns);
180 // REQ: largest value passed to underrunProtect
181 static const int LARGEST_UNDERRUN_PROT = 32;
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
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);
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);
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);
220 static const RegisterMask AllowableFlagRegs = GpRegs; // REQ: Registers that can hold flag results FIXME
222 static inline bool IsFpReg(Register r)
224 return (_rmask_(r) & FpRegs) != 0;
227 static inline bool IsGpReg(Register r)
229 return (_rmask_(r) & GpRegs) != 0;
232 #define GPR(r) ((r)&31)
233 #define FPR(r) ((r)&31)
235 // REQ: Platform specific declarations to include in Stats structure
236 #define DECLARE_PLATFORM_STATS()
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; \
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*);
267 // REQ: Platform specific declarations to include in RegAlloc class
268 #define DECLARE_PLATFORM_REGALLOC()
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)
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
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)
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; \
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; \
305 } while (0)
307 #define MR(d, s) asm_move(d, s)
309 // underrun guarantees that there is always room to insert a jump and branch delay slot
310 #define JMP(t) asm_j(t, true)
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
341 // REGIMM: bits 20..16
342 #define REGIMM_BLTZ 0x00
343 #define REGIMM_BGEZ 0x01
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
356 // COP1X: bits 5..0
357 #define COP1X_LDXC1 0x01
358 #define COP1X_SDXC1 0x09
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
383 // SPECIAL2: bits 5..0
384 #define SPECIAL2_MUL 0x02
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
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
411 // Helper definitions to encode different classes of MIPS instructions
412 // Parameters are in instruction order
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))
417 #define I_FORMAT(op, rs, rt, simm) \
418 (((op)<<26)|(GPR(rs)<<21)|(GPR(rt)<<16)|((simm)&0xffff))
420 #define J_FORMAT(op, index) \
421 (((op)<<26)|(index))
423 #define U_FORMAT(op, rs, rt, uimm) \
424 (((op)<<26)|(GPR(rs)<<21)|(GPR(rt)<<16)|((uimm)&0xffff))
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))
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)
434 #define BOFFSET(targ) (uint32_t(targ - (_nIns+1)))
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)
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)
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)
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)
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)
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)
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)
466 #define BC1F(targ) \
467 do { count_br(); EMIT(I_FORMAT(OP_COP1, COP1_BC, 0, BOFFSET(targ)), \
468 "bc1f %p", targ); } while (0)
470 #define BC1T(targ) \
471 do { count_br(); EMIT(I_FORMAT(OP_COP1, COP1_BC, 1, BOFFSET(targ)), \
472 "bc1t %p", targ); } while (0)
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)
482 #define JINDEX(dest) ((uint32_t(dest)>>2)&0x03ffffff)
484 #define J(dest) \
485 do { count_jmp(); EMIT(J_FORMAT(OP_J, JINDEX(dest)), \
486 "j %p", dest); } while (0)
488 #define trampJ(dest) \
489 do { count_jmp(); TRAMP(J_FORMAT(OP_J, JINDEX(dest)), \
490 "j %p", dest); } while (0)
492 #define JAL(dest) \
493 do { count_jmp(); EMIT(J_FORMAT(OP_JAL, JINDEX(dest)), \
494 "jal %p", dest); } while (0)
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)
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)
507 #define LB(rt, offset, base) \
508 LDST(OP_LB, rt, offset, base)
510 #define LH(rt, offset, base) \
511 LDST(OP_LH, rt, offset, base)
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)
517 #define LW(rt, offset, base) \
518 LDST(OP_LW, rt, offset, base)
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)
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)
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)
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)
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)
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)
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)
548 #define NOP() \
549 do { count_misc(); EMIT(R_FORMAT(OP_SPECIAL, 0, 0, 0, 0, SPECIAL_SLL), \
550 "nop"); } while (0)
552 #define trampNOP() \
553 do { count_misc(); TRAMP(R_FORMAT(OP_SPECIAL, 0, 0, 0, 0, SPECIAL_SLL), \
554 "nop"); } while (0)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
612 #define SW(rt, offset, base) \
613 LDST(OP_SW, rt, offset, base)
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)
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)
624 /* FPU instructions */
625 #ifdef NJ_SOFTFLOAT_SUPPORTED
627 #if !defined(__mips_soft_float) || __mips_soft_float != 1
628 #error NJ_SOFTFLOAT_SUPPORTED defined but not compiled with -msoft-float
629 #endif
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")
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")
653 #else
655 #if defined(__mips_soft_float) && __mips_soft_float != 0
656 #error compiled with -msoft-float but NJ_SOFTFLOAT_SUPPORTED not defined
657 #endif
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
715 #endif // __nanojit_NativeMIPS__