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) 2004-2007
21 * the Initial Developer. All Rights Reserved.
26 * ginn.chen@oracle.com
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
43 #ifndef __nanojit_NativeSparc__
44 #define __nanojit_NativeSparc__
46 #include "NativeCommon.h"
58 #define count_prolog()
67 #define count_pushld()
72 const int NJ_MAX_REGISTERS = 30; // L0 - L7, I0 - I5, F2 - F14
74 const int LARGEST_UNDERRUN_PROT = 32; // largest value passed to underrunProtect
76 #define NJ_MAX_STACK_ENTRY 8192
77 #define NJ_MAX_PARAMETERS 1
79 #define NJ_JTBL_SUPPORTED 0
80 #define NJ_EXPANDED_LOADSTORE_SUPPORTED 1
81 #define NJ_F2I_SUPPORTED 1
82 #define NJ_SOFTFLOAT_SUPPORTED 0
83 #define NJ_DIVI_SUPPORTED 0
85 const int NJ_ALIGN_STACK = 16;
87 typedef uint32_t NIns;
89 // Bytes of icache to flush after Assembler::patch
90 const size_t LARGEST_BRANCH_PATCH = 2 * sizeof(NIns);
92 // These are used as register numbers in various parts of the code
99 G5 = { 5 }, // Reserved for system
100 G6 = { 6 }, // Reserved for system
101 G7 = { 7 }, // Reserved for system
110 O7 = { 15 }, // Not used.
128 I7 = { 31 }, // Not used
169 deprecated_UnknownReg = { 64 }; // XXX: remove eventually, see bug 538924
171 static const uint32_t FirstRegNum = 0;
172 static const uint32_t LastRegNum = 63;
177 // We only use 32 registers to be managed.
178 // So we choose some of them.
179 // And other unmanaged registers we can use them directly.
180 // The registers that can be used directly are G0-G4, L0, L2, L4, L6
181 // SP, FP, F8-F12, F24-F28
182 typedef uint64_t RegisterMask;
183 #define _rmask_(r) ((RegisterMask)1<<(REGNUM(r)))
184 #define _reg_(r) (REGNUM(r) & 0x1F)
185 // Assembler::savedRegs[] is not needed for sparc because the
186 // registers are already saved automatically by "save" instruction.
187 static const int NumSavedRegs = 0;
189 static const RegisterMask SavedRegs = _rmask_(L1) | _rmask_(L3) | _rmask_(L5) | _rmask_(L7) |
190 _rmask_(I0) | _rmask_(I1) | _rmask_(I2) | _rmask_(I3) |
191 _rmask_(I4) | _rmask_(I5);
192 static const RegisterMask GpRegs = SavedRegs | _rmask_(O0) | _rmask_(O1) | _rmask_(O2) |
193 _rmask_(O3) | _rmask_(O4) | _rmask_(O5);
194 static const RegisterMask FpRegs = _rmask_(F0) | _rmask_(F2) | _rmask_(F4) |
195 _rmask_(F6) | _rmask_(F14) | _rmask_(F16) |
196 _rmask_(F18) | _rmask_(F20) | _rmask_(F22);
197 static const RegisterMask AllowableFlagRegs = GpRegs;
199 verbose_only( extern const char* regNames[]; )
201 #define DECLARE_PLATFORM_STATS()
203 #define DECLARE_PLATFORM_REGALLOC()
205 #define DECLARE_PLATFORM_ASSEMBLER() \
206 const static Register argRegs[6], retRegs[1]; \
208 void nativePageReset(); \
209 void nativePageSetup(); \
210 void underrunProtect(int bytes); \
211 bool hardenNopInsertion(const Config& /*c*/) { return false; } \
212 void asm_align_code(); \
213 void asm_cmp(LIns *cond); \
214 void asm_cmpd(LIns *cond); \
215 NIns* asm_branchd(bool, LIns*, NIns*); \
216 void IMM32(int32_t i) { \
218 *((int32_t*)_nIns) = i; \
220 void CALL(const CallInfo* ci); \
221 void Format_2(int32_t x, int32_t op2, int32_t imm22) { \
222 int32_t i = x << 25 | op2 << 22 | imm22 & 0x3FFFFF; \
225 void Format_2A(Register rd, int32_t op2, int32_t imm22) { \
226 Format_2(_reg_(rd), op2, imm22); \
228 void Format_2_2(int32_t a, int32_t cond, int32_t op2, int32_t disp22) { \
229 Format_2((a & 0x1) << 4 | cond & 0xF, op2, disp22); \
231 void Format_2_3(int32_t a, int32_t cond, int32_t op2, int32_t cc1, int32_t cc0, int32_t p, int32_t disp19) { \
232 Format_2_2(a, cond, op2, (cc1 & 0x1) << 21 | (cc0 & 0x1) << 20 | (p & 0x1) << 19 | disp19 & 0x7FFFF); \
234 void Format_2_4(int32_t a, int32_t rcond, int32_t op2, int32_t d16hi, int32_t p, int32_t rs1, int32_t d16lo) { \
235 Format_2_2(a, rcond & 0x7, op2, (d16hi & 0x3) << 20 | (p & 0x1) << 19 | rs1 << 14 | d16lo & 0x3FFF); \
237 void Format_3(int32_t op1, int32_t x, int32_t op3, int32_t bits19) { \
238 int32_t i = op1 << 30 | x << 25 | op3 << 19 | bits19 & 0x7FFFF; \
241 void Format_3A(int32_t op1, Register rd, int32_t op3, int32_t bits19) { \
242 Format_3(op1, _reg_(rd), op3, bits19); \
244 void Format_3_1(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t bit8, Register rs2) { \
245 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (bit8 & 0xFF) << 5 | _reg_(rs2)); \
247 void Format_3_1I(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t simm13) { \
248 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | simm13 & 0x1FFF); \
250 void Format_3_2(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t rcond, Register rs2) { \
251 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (rcond & 0x3) << 10 | _reg_(rs2)); \
253 void Format_3_2I(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t rcond, int32_t simm10) { \
254 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (rcond & 0x3) << 10 | simm10 & 0x1FFF); \
256 void Format_3_3(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t cmask, int32_t mmask) { \
257 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (cmask & 0x7) << 5 | mmask & 0xF); \
259 void Format_3_4(int32_t op1, Register rd, int32_t op3, int32_t bits19) { \
260 Format_3A(op1, rd, op3, bits19); \
262 void Format_3_5(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t x, Register rs2) { \
263 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (x & 0x1) << 12 | _reg_(rs2)); \
265 void Format_3_6(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t shcnt32) { \
266 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (shcnt32 & 0x3F)); \
268 void Format_3_7(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t shcnt64) { \
269 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | 1 << 13 | 1 << 12 | (shcnt64 & 0x7F)); \
271 void Format_3_8(int32_t op1, Register rd, int32_t op3, Register rs1, int32_t bits9, Register rs2) { \
272 Format_3A(op1, rd, op3, _reg_(rs1) << 14 | (bits9 & 0x1FF) << 5 | _reg_(rs2)); \
274 void Format_3_9(int32_t op1, int32_t cc1, int32_t cc0, int32_t op3, Register rs1, int32_t bits9, Register rs2) { \
275 Format_3(op1, (cc1 & 0x1) << 1 | (cc0 & 0x1), op3, _reg_(rs1) << 14 | (bits9 & 0x1FF) << 5 | _reg_(rs2)); \
277 void Format_4_1(Register rd, int32_t op3, Register rs1, int32_t cc1, int32_t cc0, Register rs2) { \
278 Format_3A(2, rd, op3, _reg_(rs1) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | _reg_(rs2)); \
280 void Format_4_1I(Register rd, int32_t op3, Register rs1, int32_t cc1, int32_t cc0, int32_t simm11) { \
281 Format_3A(2, rd, op3, _reg_(rs1) << 14 | (cc1 & 0x1) << 12 | 1 << 13 |(cc0 & 0x1) << 11 | simm11 & 0x7FF); \
283 void Format_4_2(Register rd, int32_t op3, int32_t cc2, int32_t cond, int32_t cc1, int32_t cc0, Register rs2) { \
284 Format_3A(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | _reg_(rs2)); \
286 void Format_4_2I(Register rd, int32_t op3, int32_t cc2, int32_t cond, int32_t cc1, int32_t cc0, int32_t simm11) { \
287 Format_3A(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (simm11 & 0x7FF)); \
289 void Format_4_3(Register rd, int32_t op3, Register rs1, int32_t cc1, int32_t cc0, int32_t swap_trap) { \
290 Format_3A(2, rd, op3, _reg_(rs1) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | swap_trap & 0x7F); \
292 void Format_4_4(Register rd, int32_t op3, Register rs1, int32_t rcond, int32_t opf_low, Register rs2) { \
293 Format_3A(2, rd, op3, _reg_(rs1) << 14 | (rcond & 0x7) << 10 | (opf_low & 0x1F) << 5 | _reg_(rs2)); \
295 void Format_4_5(Register rd, int32_t op3, int32_t cond, int32_t opf_cc, int32_t opf_low, Register rs2) { \
296 Format_3A(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | _reg_(rs2)); \
298 void IntegerOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode); \
299 void IntegerOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char *opcode); \
300 void FloatOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode); \
301 void Bicc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode); \
302 void FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode); \
303 void LoadOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \
304 void LoadOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode); \
305 void MOVcc(Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \
306 void MOVccI(int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \
307 void FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char *opcode); \
308 void ShiftOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \
309 void ShiftOperationI(Register rs1, int32_t shcnt32, Register rd, int32_t op3, const char* opcode); \
310 void Store(Register rd, Register rs1, Register rs2, int32_t op3, const char* opcode); \
311 void StoreI(Register rd, int32_t simm13, Register rs1, int32_t op3, const char* opcode); \
312 void ADD(Register rs1, Register rs2, Register rd); \
313 void ADDCC(Register rs1, Register rs2, Register rd); \
314 void AND(Register rs1, Register rs2, Register rd); \
315 void ANDCC(Register rs1, Register rs2, Register rd); \
316 void OR(Register rs1, Register rs2, Register rd); \
317 void ORI(Register rs1, int32_t simm13, Register rd); \
318 void ORN(Register rs1, Register rs2, Register rd); \
319 void SMULCC(Register rs1, Register rs2, Register rd); \
320 void SUB(Register rs1, Register rs2, Register rd); \
321 void SUBCC(Register rs1, Register rs2, Register rd); \
322 void SUBI(Register rs1, int32_t simm13, Register rd); \
323 void XOR(Register rs1, Register rs2, Register rd); \
324 void BA(int32_t a, int32_t dsp22); \
325 void BE(int32_t a, int32_t dsp22); \
326 void BNE(int32_t a, int32_t dsp22); \
327 void BG(int32_t a, int32_t dsp22); \
328 void BGU(int32_t a, int32_t dsp22); \
329 void BGE(int32_t a, int32_t dsp22); \
330 void BL(int32_t a, int32_t dsp22); \
331 void BLE(int32_t a, int32_t dsp22); \
332 void BLEU(int32_t a, int32_t dsp22); \
333 void BCC(int32_t a, int32_t dsp22); \
334 void BCS(int32_t a, int32_t dsp22); \
335 void BVC(int32_t a, int32_t dsp22); \
336 void BVS(int32_t a, int32_t dsp22); \
337 void FABSS(Register rs2, Register rd); \
338 void FADDD(Register rs1, Register rs2, Register rd); \
339 void FBE(int32_t a, int32_t dsp22); \
340 void FBNE(int32_t a, int32_t dsp22); \
341 void FBUE(int32_t a, int32_t dsp22); \
342 void FBG(int32_t a, int32_t dsp22); \
343 void FBUG(int32_t a, int32_t dsp22); \
344 void FBGE(int32_t a, int32_t dsp22); \
345 void FBUGE(int32_t a, int32_t dsp22); \
346 void FBL(int32_t a, int32_t dsp22); \
347 void FBUL(int32_t a, int32_t dsp22); \
348 void FBLE(int32_t a, int32_t dsp22); \
349 void FBULE(int32_t a, int32_t dsp22); \
350 void FCMPD(Register rs1, Register rs2); \
351 void FSUBD(Register rs1, Register rs2, Register rd); \
352 void FMULD(Register rs1, Register rs2, Register rd); \
353 void FDTOI(Register rs2, Register rd); \
354 void FDIVD(Register rs1, Register rs2, Register rd); \
355 void FMOVD(Register rs2, Register rd); \
356 void FNEGD(Register rs2, Register rd); \
357 void FITOD(Register rs2, Register rd); \
358 void FDTOS(Register rs2, Register rd); \
359 void FSTOD(Register rs2, Register rd); \
360 void JMPL(Register rs1, Register rs2, Register rd); \
361 void JMPLI(Register rs1, int32_t simm13, Register rd); \
362 void LDF(Register rs1, Register rs2, Register rd); \
363 void LDFI(Register rs1, int32_t simm13, Register rd); \
364 void LDF32(Register rs1, int32_t immI, Register rd); \
365 void LDDF32(Register rs1, int32_t immI, Register rd); \
366 void LDUB(Register rs1, Register rs2, Register rd); \
367 void LDUBI(Register rs1, int32_t simm13, Register rd); \
368 void LDUB32(Register rs1, int32_t immI, Register rd); \
369 void LDSB(Register rs1, Register rs2, Register rd); \
370 void LDSBI(Register rs1, int32_t simm13, Register rd); \
371 void LDSB32(Register rs1, int32_t immI, Register rd); \
372 void LDUH(Register rs1, Register rs2, Register rd); \
373 void LDUHI(Register rs1, int32_t simm13, Register rd); \
374 void LDUH32(Register rs1, int32_t immI, Register rd); \
375 void LDSH(Register rs1, Register rs2, Register rd); \
376 void LDSHI(Register rs1, int32_t simm13, Register rd); \
377 void LDSH32(Register rs1, int32_t immI, Register rd); \
378 void LDSW(Register rs1, Register rs2, Register rd); \
379 void LDSWI(Register rs1, int32_t simm13, Register rd); \
380 void LDSW32(Register rs1, int32_t immI, Register rd); \
381 void MOVE(Register rs, Register rd); \
382 void MOVNE(Register rs, Register rd); \
383 void MOVL(Register rs, Register rd); \
384 void MOVLE(Register rs, Register rd); \
385 void MOVG(Register rs, Register rd); \
386 void MOVGE(Register rs, Register rd); \
387 void MOVLEU(Register rs, Register rd); \
388 void MOVGU(Register rs, Register rd); \
389 void MOVCC(Register rs, Register rd); \
390 void MOVCS(Register rs, Register rd); \
391 void MOVVC(Register rs, Register rd); \
392 void MOVEI(int32_t simm11, Register rd); \
393 void MOVNEI(int32_t simm11, Register rd); \
394 void MOVLI(int32_t simm11, Register rd); \
395 void MOVLEI(int32_t simm11, Register rd); \
396 void MOVGI(int32_t simm11, Register rd); \
397 void MOVGEI(int32_t simm11, Register rd); \
398 void MOVLEUI(int32_t simm11, Register rd); \
399 void MOVGUI(int32_t simm11, Register rd); \
400 void MOVCCI(int32_t simm11, Register rd); \
401 void MOVCSI(int32_t simm11, Register rd); \
402 void MOVVSI(int32_t simm11, Register rd); \
403 void MOVFEI(int32_t simm11, Register rd); \
404 void MOVFLI(int32_t simm11, Register rd); \
405 void MOVFLEI(int32_t simm11, Register rd); \
406 void MOVFGI(int32_t simm11, Register rd); \
407 void MOVFGEI(int32_t simm11, Register rd); \
408 void FMOVDNE(Register rs, Register rd); \
409 void FMOVDL(Register rs, Register rd); \
410 void FMOVDLE(Register rs, Register rd); \
411 void FMOVDLEU(Register rs, Register rd); \
412 void FMOVDG(Register rs, Register rd); \
413 void FMOVDGU(Register rs, Register rd); \
414 void FMOVDGE(Register rs, Register rd); \
415 void FMOVDCC(Register rs, Register rd); \
416 void FMOVDCS(Register rs, Register rd); \
417 void FMOVDFNE(Register rs, Register rd); \
418 void FMOVDFUG(Register rs, Register rd); \
419 void FMOVDFUGE(Register rs, Register rd); \
420 void FMOVDFUL(Register rs, Register rd); \
421 void FMOVDFULE(Register rs, Register rd); \
423 void RDY(Register rd); \
424 void RESTORE(Register rs1, Register rs2, Register rd); \
425 void SAVE(Register rs1, Register rs2, Register rd); \
426 void SAVEI(Register rs1, int32_t simm13, Register rd); \
427 void SETHI(int32_t immI, Register rd); \
428 void SET32(int32_t immI, Register rd); \
429 void SLL(Register rs1, Register rs2, Register rd); \
430 void SRA(Register rs1, Register rs2, Register rd); \
431 void SRAI(Register rs1, int32_t shcnt32, Register rd); \
432 void SRL(Register rs1, Register rs2, Register rd); \
433 void STF(Register rd, Register rs1, Register rs2); \
434 void STFI(Register rd, int32_t simm13, Register rs1); \
435 void STF32(Register rd, int32_t immI, Register rs1); \
436 void STDF32(Register rd, int32_t immI, Register rs1); \
437 void STW(Register rd, Register rs1, Register rs2); \
438 void STWI(Register rd, int32_t simm13, Register rs1); \
439 void STW32(Register rd, int32_t immI, Register rs1); \
440 void STH(Register rd, Register rs1, Register rs2); \
441 void STHI(Register rd, int32_t simm13, Register rs1); \
442 void STH32(Register rd, int32_t immI, Register rs1); \
443 void STB(Register rd, Register rs1, Register rs2); \
444 void STBI(Register rd, int32_t simm13, Register rs1); \
445 void STB32(Register rd, int32_t immI, Register rs1); \
446 bool isIMM13(int32_t imm) { return (imm) <= 0xfff && (imm) >= -0x1000; } \
447 bool isIMM19(int32_t imm) { return (imm) <= 0x3ffff && (imm) >= -0x40000; } \
448 bool isIMM22(int32_t imm) { return (imm) <= 0x1fffff && (imm) >= -0x200000; } \
449 void JMP_long_nocheck(int32_t t); \
450 void JMP_long(int32_t t); \
451 void JMP_long_placeholder(); \
452 int32_t JCC(void *t); \
454 void MR(Register rd, Register rs);
456 #endif // __nanojit_NativeSparc__