/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.ppc; import org.jikesrvm.VM; import org.jikesrvm.architecture.MachineRegister; import org.vmmagic.pragma.Pure; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.pragma.UninterruptibleNoWarn; /** * Register Usage Conventions for PowerPC. */ public final class RegisterConstants { // Machine instructions. // /** log2 of instruction width in bytes, powerPC */ public static final int LG_INSTRUCTION_WIDTH = 2; /** instruction width in bytes, powerPC */ public static final int INSTRUCTION_WIDTH = 1 << LG_INSTRUCTION_WIDTH; /** * Representation of general purpose registers */ public enum GPR implements MachineRegister { R0(0), R1(1), R2(2), R3(3), R4(4), R5(5), R6(6), R7(7), R8(8), R9(9), R10(10), R11(11), R12(12), R13(13), R14(14), R15(15), R16(16), R17(17), R18(18), R19(19), R20(20), R21(21), R22(22), R23(23), R24(24), R25(25), R26(26), R27(27), R28(28), R29(29), R30(30), R31(31); /** Local copy of the backing array. Copied here to avoid calls to clone */ private static final GPR[] vals = values(); GPR(int v) { if (v != ordinal()) { throw new Error("Invalid register ordinal"); } } /** @return encoded value of this register */ @UninterruptibleNoWarn("Interruptible code only called during boot image creation") @Pure @Override public byte value() { byte result; if (!org.jikesrvm.VM.runningVM) { result = (byte)ordinal(); } else { result = (byte)java.lang.JikesRVMSupport.getEnumOrdinal(this); } if (VM.VerifyAssertions) { VM._assert(result >= 0 && result <= 31); } return result; } /** * Converts encoded value into the GPR it represents * @param num encoded value * @return represented GPR */ @Uninterruptible @Pure public static GPR lookup(int num) { return vals[num]; } /** @return register next register to this one (e.g. R1 for R0) */ @Uninterruptible @Pure public GPR nextGPR() { return lookup(value() + 1); } } /** * Super interface for floating point registers */ public interface FloatingPointMachineRegister extends MachineRegister { } /** * Representation of floating point registers */ public enum FPR implements FloatingPointMachineRegister { FR0(0), FR1(1), FR2(2), FR3(3), FR4(4), FR5(5), FR6(6), FR7(7), FR8(8), FR9(9), FR10(10), FR11(11), FR12(12), FR13(13), FR14(14), FR15(15), FR16(16), FR17(17), FR18(18), FR19(19), FR20(20), FR21(21), FR22(22), FR23(23), FR24(24), FR25(25), FR26(26), FR27(27), FR28(28), FR29(29), FR30(30), FR31(31); /** Local copy of the backing array. Copied here to avoid calls to clone */ private static final FPR[] vals = values(); FPR(int v) { if (v != ordinal()) { throw new Error("Invalid register ordinal"); } } /** @return encoded value of this register */ @UninterruptibleNoWarn("Interruptible code only called during boot image creation") @Override @Pure public byte value() { byte result; if (!org.jikesrvm.VM.runningVM) { result = (byte)ordinal(); } else { result = (byte)java.lang.JikesRVMSupport.getEnumOrdinal(this); } if (VM.VerifyAssertions) { VM._assert(result >= 0 && result <= 31); } return result; } /** * Converts encoded value into the FPR it represents * @param num encoded value * @return represented GPR */ @Pure public static FPR lookup(int num) { return vals[num]; } } /** * Representation of condition registers */ public enum CR implements MachineRegister { CR0(0), CR1(1), CR2(2), CR3(3), CR4(4), CR5(5), CR6(6), CR7(7); CR(int v) { if (v != ordinal()) { throw new Error("Invalid register ordinal"); } } /** @return encoded value of this register */ @Override @Pure public byte value() { return (byte)ordinal(); } } // OS register convention (for mapping parameters in JNI calls) // These constants encode conventions for Linux. // 0 is for function prologs, 1 is stack frame pointer, 2 is TOC pointer public static final GPR FIRST_OS_PARAMETER_GPR = GPR.R3; public static final GPR LAST_OS_PARAMETER_GPR = GPR.R10; public static final GPR FIRST_OS_VOLATILE_GPR = GPR.R3; public static final GPR LAST_OS_VOLATILE_GPR = GPR.R12; public static final GPR FIRST_OS_NONVOLATILE_GPR = (VM.BuildForPower64ELF_ABI) ? GPR.R14 : GPR.R13; public static final GPR LAST_OS_NONVOLATILE_GPR = GPR.R31; public static final FPR FIRST_OS_PARAMETER_FPR = FPR.FR1; public static final FPR LAST_OS_PARAMETER_FPR = VM.BuildForLinux ? FPR.FR8 : FPR.FR13; public static final FPR FIRST_OS_VOLATILE_FPR = FPR.FR1; public static final FPR LAST_OS_VOLATILE_FPR = FPR.FR13; public static final FPR FIRST_OS_NONVOLATILE_FPR = FPR.FR14; public static final FPR LAST_OS_NONVOLATILE_FPR = FPR.FR31; public static final FPR LAST_OS_VARARG_PARAMETER_FPR = FPR.FR8; // Jikes RVM's general purpose register usage (32 or 64 bits wide based on VM.BuildFor64Addr). // /** special instruction semantics on this register */ public static final GPR REGISTER_ZERO = GPR.R0; /** same as Linux */ public static final GPR FRAME_POINTER = GPR.R1; public static final GPR FIRST_VOLATILE_GPR = FIRST_OS_PARAMETER_GPR; // ... public static final GPR LAST_VOLATILE_GPR = LAST_OS_PARAMETER_GPR; public static final GPR FIRST_SCRATCH_GPR = GPR.lookup(LAST_VOLATILE_GPR.value() + 1); public static final GPR LAST_SCRATCH_GPR = LAST_OS_VOLATILE_GPR; // NOTE: the PPC-specific part of the bootloader that deals with starting of threads // makes assumptions about the register usage. You will need to update the code // there if you change the assignments for the JTOC pointer or the thread register. // PowerPC 64 ELF ABI reserves R13 for use by libpthread; therefore Jikes RVM doesn't touch it. public static final GPR FIRST_RVM_RESERVED_NV_GPR = VM.BuildFor64Addr ? GPR.R14 : GPR.R13; public static final GPR THREAD_REGISTER = FIRST_RVM_RESERVED_NV_GPR; // 2 is used by Linux for thread context and on OS X it's a scratch. public static final GPR JTOC_POINTER = (VM.BuildForLinux && VM.BuildFor32Addr) ? GPR.lookup(THREAD_REGISTER.value() + 1) : GPR.R2; // use TOC register on PowerPC 64-bit ELF ABI // Use THREAD_REGISTER + 2 for 32-bit Linux and THREAD_REGISTER + 1 for 64-bit Linux public static final GPR KLUDGE_TI_REG = GPR.lookup(THREAD_REGISTER.value() + (VM.BuildForLinux && VM.BuildFor32Addr ? 2 : 1)); public static final GPR LAST_RVM_RESERVED_NV_GPR = KLUDGE_TI_REG; public static final GPR FIRST_NONVOLATILE_GPR = GPR.values()[LAST_RVM_RESERVED_NV_GPR.value() + 1]; // ... public static final GPR LAST_NONVOLATILE_GPR = LAST_OS_NONVOLATILE_GPR; public static final int NUM_GPRS = 32; // Floating point register usage. (FPR's are 64 bits wide). /** Linux is 0 */ public static final FPR FIRST_SCRATCH_FPR = FPR.FR0; /** Linux is 0 */ public static final FPR LAST_SCRATCH_FPR = FPR.FR0; public static final FPR FIRST_VOLATILE_FPR = FIRST_OS_VOLATILE_FPR; // public static final FPR LAST_VOLATILE_FPR = LAST_OS_VOLATILE_FPR; public static final FPR FIRST_NONVOLATILE_FPR = FIRST_OS_NONVOLATILE_FPR; // ... public static final FPR LAST_NONVOLATILE_FPR = LAST_OS_NONVOLATILE_FPR; public static final int NUM_FPRS = 32; public static final int NUM_NONVOLATILE_GPRS = LAST_NONVOLATILE_GPR.value() - FIRST_NONVOLATILE_GPR.value() + 1; public static final int NUM_NONVOLATILE_FPRS = LAST_NONVOLATILE_FPR.value() - FIRST_NONVOLATILE_FPR.value() + 1; // condition registers // TODO: fill table public static final int NUM_CRS = 8; /** number of special registers (user visible) */ public static final int NUM_SPECIALS = 8; private RegisterConstants() { // prevent instantiation } }