5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.graalvm.compiler.asm.aarch64;
24
25 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD;
26 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS;
27 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR;
28 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.AND;
29 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ANDS;
30 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ASRV;
31 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BFM;
32 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BIC;
33 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BICS;
34 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BLR;
35 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BR;
36 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BRK;
37 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX;
38 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS;
39 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ;
40 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSEL;
41 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSINC;
42 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSNEG;
43 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.DMB;
44 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EON;
993 int transferSize = NumUtil.log2Ceil(srcSize / 8);
994 loadStoreInstruction(LDR, rt, address, General32, transferSize);
995 }
996
997 /**
998 * Loads a srcSize value from address into rt sign-extending it.
999 *
1000 * @param targetSize size of target register in bits. Must be 32 or 64.
1001 * @param srcSize size of memory read in bits. Must be 8, 16 or 32, but may not be equivalent to
1002 * targetSize.
1003 * @param rt general purpose register. May not be null or stackpointer.
1004 * @param address all addressing modes allowed. May not be null.
1005 */
1006 protected void ldrs(int targetSize, int srcSize, Register rt, AArch64Address address) {
1007 assert rt.getRegisterCategory().equals(CPU);
1008 assert (srcSize == 8 || srcSize == 16 || srcSize == 32) && srcSize != targetSize;
1009 int transferSize = NumUtil.log2Ceil(srcSize / 8);
1010 loadStoreInstruction(LDRS, rt, address, generalFromSize(targetSize), transferSize);
1011 }
1012
1013 /**
1014 * Stores register rt into memory pointed by address.
1015 *
1016 * @param destSize number of bits written to memory. Must be 8, 16, 32 or 64.
1017 * @param rt general purpose register. May not be null or stackpointer.
1018 * @param address all addressing modes allowed. May not be null.
1019 */
1020 public void str(int destSize, Register rt, AArch64Address address) {
1021 assert rt.getRegisterCategory().equals(CPU);
1022 assert destSize == 8 || destSize == 16 || destSize == 32 || destSize == 64;
1023 int transferSize = NumUtil.log2Ceil(destSize / 8);
1024 loadStoreInstruction(STR, rt, address, General64, transferSize);
1025 }
1026
1027 private void loadStoreInstruction(Instruction instr, Register reg, AArch64Address address, InstructionType type, int log2TransferSize) {
1028 assert log2TransferSize >= 0 && log2TransferSize < 4;
1029 int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
1030 int is32Bit = type.width == 32 ? 1 << ImmediateSizeOffset : 0;
1031 int isFloat = !type.isGeneral ? 1 << LoadStoreFpFlagOffset : 0;
1032 int memop = instr.encoding | transferSizeEncoding | is32Bit | isFloat | rt(reg);
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.graalvm.compiler.asm.aarch64;
24
25 import static jdk.vm.ci.aarch64.AArch64.cpuRegisters;
26 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD;
27 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS;
28 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR;
29 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.AND;
30 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ANDS;
31 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ASRV;
32 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BFM;
33 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BIC;
34 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BICS;
35 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BLR;
36 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BR;
37 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BRK;
38 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX;
39 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS;
40 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ;
41 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSEL;
42 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSINC;
43 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CSNEG;
44 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.DMB;
45 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.EON;
994 int transferSize = NumUtil.log2Ceil(srcSize / 8);
995 loadStoreInstruction(LDR, rt, address, General32, transferSize);
996 }
997
998 /**
999 * Loads a srcSize value from address into rt sign-extending it.
1000 *
1001 * @param targetSize size of target register in bits. Must be 32 or 64.
1002 * @param srcSize size of memory read in bits. Must be 8, 16 or 32, but may not be equivalent to
1003 * targetSize.
1004 * @param rt general purpose register. May not be null or stackpointer.
1005 * @param address all addressing modes allowed. May not be null.
1006 */
1007 protected void ldrs(int targetSize, int srcSize, Register rt, AArch64Address address) {
1008 assert rt.getRegisterCategory().equals(CPU);
1009 assert (srcSize == 8 || srcSize == 16 || srcSize == 32) && srcSize != targetSize;
1010 int transferSize = NumUtil.log2Ceil(srcSize / 8);
1011 loadStoreInstruction(LDRS, rt, address, generalFromSize(targetSize), transferSize);
1012 }
1013
1014 public enum PrefetchMode {
1015 PLDL1KEEP(0b00000),
1016 PLDL1STRM(0b00001),
1017 PLDL2KEEP(0b00010),
1018 PLDL2STRM(0b00011),
1019 PLDL3KEEP(0b00100),
1020 PLDL3STRM(0b00101),
1021
1022 PLIL1KEEP(0b01000),
1023 PLIL1STRM(0b01001),
1024 PLIL2KEEP(0b01010),
1025 PLIL2STRM(0b01011),
1026 PLIL3KEEP(0b01100),
1027 PLIL3STRM(0b01101),
1028
1029 PSTL1KEEP(0b10000),
1030 PSTL1STRM(0b10001),
1031 PSTL2KEEP(0b10010),
1032 PSTL2STRM(0b10011),
1033 PSTL3KEEP(0b10100),
1034 PSTL3STRM(0b10101);
1035
1036 private final int encoding;
1037
1038 PrefetchMode(int encoding) {
1039 this.encoding = encoding;
1040 }
1041
1042 private static PrefetchMode[] modes = {
1043 PLDL1KEEP,
1044 PLDL1STRM,
1045 PLDL2KEEP,
1046 PLDL2STRM,
1047 PLDL3KEEP,
1048 PLDL3STRM,
1049
1050 null,
1051 null,
1052
1053 PLIL1KEEP,
1054 PLIL1STRM,
1055 PLIL2KEEP,
1056 PLIL2STRM,
1057 PLIL3KEEP,
1058 PLIL3STRM,
1059
1060 null,
1061 null,
1062
1063 PSTL1KEEP,
1064 PSTL1STRM,
1065 PSTL2KEEP,
1066 PSTL2STRM,
1067 PSTL3KEEP,
1068 PSTL3STRM
1069 };
1070
1071 public static PrefetchMode lookup(int enc) {
1072 assert enc >= 00 && enc < modes.length;
1073 return modes[enc];
1074 }
1075
1076 public Register toRegister() {
1077 return cpuRegisters.get(encoding);
1078 }
1079 }
1080
1081 /*
1082 * implements a prefetch at a 64-bit aligned address using a scaled 12 bit or unscaled 9 bit
1083 * displacement addressing mode
1084 *
1085 * @param rt general purpose register. May not be null, zr or stackpointer.
1086 *
1087 * @param address only displacement addressing modes allowed. May not be null.
1088 */
1089 public void prfm(AArch64Address address, PrefetchMode mode) {
1090 assert (address.getAddressingMode() == AddressingMode.IMMEDIATE_SCALED ||
1091 address.getAddressingMode() == AddressingMode.IMMEDIATE_UNSCALED ||
1092 address.getAddressingMode() == AddressingMode.REGISTER_OFFSET);
1093 assert mode != null;
1094 final int srcSize = 64;
1095 final int transferSize = NumUtil.log2Ceil(srcSize / 8);
1096 final Register rt = mode.toRegister();
1097 // this looks weird but that's because loadStoreInstruction is weird
1098 // instruction select fields are size [31:30], v [26] and opc [25:24]
1099 // prfm requires size == 0b11, v == 0b0 and opc == 0b11
1100 // passing LDRS ensures opc[1] == 0b1
1101 // (n.b. passing LDR/STR makes no difference to opc[1:0]!!)
1102 // passing General64 ensures opc[0] == 0b1 and v = 0b0
1103 // (n.b. passing General32 ensures opc[0] == 0b0 and v = 0b0)
1104 // srcSize 64 ensures size == 0b11
1105 loadStoreInstruction(LDRS, rt, address, General64, transferSize);
1106 }
1107
1108 /**
1109 * Stores register rt into memory pointed by address.
1110 *
1111 * @param destSize number of bits written to memory. Must be 8, 16, 32 or 64.
1112 * @param rt general purpose register. May not be null or stackpointer.
1113 * @param address all addressing modes allowed. May not be null.
1114 */
1115 public void str(int destSize, Register rt, AArch64Address address) {
1116 assert rt.getRegisterCategory().equals(CPU);
1117 assert destSize == 8 || destSize == 16 || destSize == 32 || destSize == 64;
1118 int transferSize = NumUtil.log2Ceil(destSize / 8);
1119 loadStoreInstruction(STR, rt, address, General64, transferSize);
1120 }
1121
1122 private void loadStoreInstruction(Instruction instr, Register reg, AArch64Address address, InstructionType type, int log2TransferSize) {
1123 assert log2TransferSize >= 0 && log2TransferSize < 4;
1124 int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
1125 int is32Bit = type.width == 32 ? 1 << ImmediateSizeOffset : 0;
1126 int isFloat = !type.isGeneral ? 1 << LoadStoreFpFlagOffset : 0;
1127 int memop = instr.encoding | transferSizeEncoding | is32Bit | isFloat | rt(reg);
|