< prev index next >

src/cpu/aarch64/vm/assembler_aarch64.hpp

Print this page




 955   }
 956 
 957 #define INSN(NAME, opc, op2, LL)                \
 958   void NAME(unsigned imm) {                     \
 959     generate_exception(opc, op2, LL, imm);      \
 960   }
 961 
 962   INSN(svc, 0b000, 0, 0b01);
 963   INSN(hvc, 0b000, 0, 0b10);
 964   INSN(smc, 0b000, 0, 0b11);
 965   INSN(brk, 0b001, 0, 0b00);
 966   INSN(hlt, 0b010, 0, 0b00);
 967   INSN(dpcs1, 0b101, 0, 0b01);
 968   INSN(dpcs2, 0b101, 0, 0b10);
 969   INSN(dpcs3, 0b101, 0, 0b11);
 970 
 971 #undef INSN
 972 
 973   // System
 974   void system(int op0, int op1, int CRn, int CRm, int op2,
 975               Register rt = (Register)0b11111)
 976   {
 977     starti;
 978     f(0b11010101000, 31, 21);
 979     f(op0, 20, 19);
 980     f(op1, 18, 16);
 981     f(CRn, 15, 12);
 982     f(CRm, 11, 8);
 983     f(op2, 7, 5);
 984     rf(rt, 0);
 985   }
 986 
 987   void hint(int imm) {
 988     system(0b00, 0b011, 0b0010, imm, 0b000);
 989   }
 990 
 991   void nop() {
 992     hint(0);
 993   }
 994   // we only provide mrs and msr for the special purpose system
 995   // registers where op1 (instr[20:19]) == 11 and, (currently) only


1065     f(0b11111000000, 20, 10);
1066     rf(R, 5);
1067     f(0b00000, 4, 0);
1068   }
1069 
1070 #define INSN(NAME, opc)                         \
1071   void NAME(Register R) {                       \
1072     branch_reg(R, opc);                         \
1073   }
1074 
1075   INSN(br, 0b0000);
1076   INSN(blr, 0b0001);
1077   INSN(ret, 0b0010);
1078 
1079   void ret(void *p); // This forces a compile-time error for ret(0)
1080 
1081 #undef INSN
1082 
1083 #define INSN(NAME, opc)                         \
1084   void NAME() {                 \
1085     branch_reg((Register)0b11111, opc);         \
1086   }
1087 
1088   INSN(eret, 0b0100);
1089   INSN(drps, 0b0101);
1090 
1091 #undef INSN
1092 
1093   // Load/store exclusive
1094   enum operand_size { byte, halfword, word, xword };
1095 
1096   void load_store_exclusive(Register Rs, Register Rt1, Register Rt2,
1097     Register Rn, enum operand_size sz, int op, int o0) {
1098     starti;
1099     f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21);
1100     rf(Rs, 16), f(o0, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0);












1101   }
1102 
1103 #define INSN4(NAME, sz, op, o0) /* Four registers */                    \
1104   void NAME(Register Rs, Register Rt1, Register Rt2, Register Rn) {     \
1105     guarantee(Rs != Rn && Rs != Rt1 && Rs != Rt2, "unpredictable instruction"); \
1106     load_store_exclusive(Rs, Rt1, Rt2, Rn, sz, op, o0);                 \
1107   }
1108 
1109 #define INSN3(NAME, sz, op, o0) /* Three registers */                   \
1110   void NAME(Register Rs, Register Rt, Register Rn) {                    \
1111     guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction");       \
1112     load_store_exclusive(Rs, Rt, (Register)0b11111, Rn, sz, op, o0);    \
1113   }
1114 
1115 #define INSN2(NAME, sz, op, o0) /* Two registers */                     \
1116   void NAME(Register Rt, Register Rn) {                                 \
1117     load_store_exclusive((Register)0b11111, Rt, (Register)0b11111,      \
1118                          Rn, sz, op, o0);                               \
1119   }
1120 
1121 #define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \
1122   void NAME(Register Rt1, Register Rt2, Register Rn) {                  \
1123     guarantee(Rt1 != Rt2, "unpredictable instruction");                 \
1124     load_store_exclusive((Register)0b11111, Rt1, Rt2, Rn, sz, op, o0);  \
1125   }
1126 
1127   // bytes
1128   INSN3(stxrb, byte, 0b000, 0);
1129   INSN3(stlxrb, byte, 0b000, 1);
1130   INSN2(ldxrb, byte, 0b010, 0);
1131   INSN2(ldaxrb, byte, 0b010, 1);
1132   INSN2(stlrb, byte, 0b100, 1);
1133   INSN2(ldarb, byte, 0b110, 1);
1134 
1135   // halfwords
1136   INSN3(stxrh, halfword, 0b000, 0);
1137   INSN3(stlxrh, halfword, 0b000, 1);
1138   INSN2(ldxrh, halfword, 0b010, 0);
1139   INSN2(ldaxrh, halfword, 0b010, 1);
1140   INSN2(stlrh, halfword, 0b100, 1);
1141   INSN2(ldarh, halfword, 0b110, 1);
1142 
1143   // words
1144   INSN3(stxrw, word, 0b000, 0);


1151   INSN_FOO(ldaxpw, word, 0b011, 1);
1152   INSN2(stlrw, word, 0b100, 1);
1153   INSN2(ldarw, word, 0b110, 1);
1154 
1155   // xwords
1156   INSN3(stxr, xword, 0b000, 0);
1157   INSN3(stlxr, xword, 0b000, 1);
1158   INSN4(stxp, xword, 0b001, 0);
1159   INSN4(stlxp, xword, 0b001, 1);
1160   INSN2(ldxr, xword, 0b010, 0);
1161   INSN2(ldaxr, xword, 0b010, 1);
1162   INSN_FOO(ldxp, xword, 0b011, 0);
1163   INSN_FOO(ldaxp, xword, 0b011, 1);
1164   INSN2(stlr, xword, 0b100, 1);
1165   INSN2(ldar, xword, 0b110, 1);
1166 
1167 #undef INSN2
1168 #undef INSN3
1169 #undef INSN4
1170 #undef INSN_FOO








































1171 
1172   // Load register (literal)
1173 #define INSN(NAME, opc, V)                                              \
1174   void NAME(Register Rt, address dest) {                                \
1175     long offset = (dest - pc()) >> 2;                                   \
1176     starti;                                                             \
1177     f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24),        \
1178       sf(offset, 23, 5);                                                \
1179     rf(Rt, 0);                                                          \
1180   }                                                                     \
1181   void NAME(Register Rt, address dest, relocInfo::relocType rtype) {    \
1182     InstructionMark im(this);                                           \
1183     guarantee(rtype == relocInfo::internal_word_type,                   \
1184               "only internal_word_type relocs make sense here");        \
1185     code_section()->relocate(inst_mark(), InternalAddress(dest).rspec()); \
1186     NAME(Rt, dest);                                                     \
1187   }                                                                     \
1188   void NAME(Register Rt, Label &L) {                                    \
1189     wrap_label(Rt, L, &Assembler::NAME);                                \
1190   }




 955   }
 956 
 957 #define INSN(NAME, opc, op2, LL)                \
 958   void NAME(unsigned imm) {                     \
 959     generate_exception(opc, op2, LL, imm);      \
 960   }
 961 
 962   INSN(svc, 0b000, 0, 0b01);
 963   INSN(hvc, 0b000, 0, 0b10);
 964   INSN(smc, 0b000, 0, 0b11);
 965   INSN(brk, 0b001, 0, 0b00);
 966   INSN(hlt, 0b010, 0, 0b00);
 967   INSN(dpcs1, 0b101, 0, 0b01);
 968   INSN(dpcs2, 0b101, 0, 0b10);
 969   INSN(dpcs3, 0b101, 0, 0b11);
 970 
 971 #undef INSN
 972 
 973   // System
 974   void system(int op0, int op1, int CRn, int CRm, int op2,
 975               Register rt = dummy_reg)
 976   {
 977     starti;
 978     f(0b11010101000, 31, 21);
 979     f(op0, 20, 19);
 980     f(op1, 18, 16);
 981     f(CRn, 15, 12);
 982     f(CRm, 11, 8);
 983     f(op2, 7, 5);
 984     rf(rt, 0);
 985   }
 986 
 987   void hint(int imm) {
 988     system(0b00, 0b011, 0b0010, imm, 0b000);
 989   }
 990 
 991   void nop() {
 992     hint(0);
 993   }
 994   // we only provide mrs and msr for the special purpose system
 995   // registers where op1 (instr[20:19]) == 11 and, (currently) only


1065     f(0b11111000000, 20, 10);
1066     rf(R, 5);
1067     f(0b00000, 4, 0);
1068   }
1069 
1070 #define INSN(NAME, opc)                         \
1071   void NAME(Register R) {                       \
1072     branch_reg(R, opc);                         \
1073   }
1074 
1075   INSN(br, 0b0000);
1076   INSN(blr, 0b0001);
1077   INSN(ret, 0b0010);
1078 
1079   void ret(void *p); // This forces a compile-time error for ret(0)
1080 
1081 #undef INSN
1082 
1083 #define INSN(NAME, opc)                         \
1084   void NAME() {                 \
1085     branch_reg(dummy_reg, opc);         \
1086   }
1087 
1088   INSN(eret, 0b0100);
1089   INSN(drps, 0b0101);
1090 
1091 #undef INSN
1092 
1093   // Load/store exclusive
1094   enum operand_size { byte, halfword, word, xword };
1095 
1096   void load_store_exclusive(Register Rs, Register Rt1, Register Rt2,
1097     Register Rn, enum operand_size sz, int op, bool ordered) {
1098     starti;
1099     f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21);
1100     rf(Rs, 16), f(ordered, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0);
1101   }
1102 
1103   void load_exclusive(Register dst, Register addr,
1104                       enum operand_size sz, bool ordered) {
1105     load_store_exclusive(dummy_reg, dst, dummy_reg, addr,
1106                          sz, 0b010, ordered);
1107   }
1108 
1109   void store_exclusive(Register status, Register new_val, Register addr,
1110                        enum operand_size sz, bool ordered) {
1111     load_store_exclusive(status, new_val, dummy_reg, addr,
1112                          sz, 0b000, ordered);
1113   }
1114 
1115 #define INSN4(NAME, sz, op, o0) /* Four registers */                    \
1116   void NAME(Register Rs, Register Rt1, Register Rt2, Register Rn) {     \
1117     guarantee(Rs != Rn && Rs != Rt1 && Rs != Rt2, "unpredictable instruction"); \
1118     load_store_exclusive(Rs, Rt1, Rt2, Rn, sz, op, o0);                 \
1119   }
1120 
1121 #define INSN3(NAME, sz, op, o0) /* Three registers */                   \
1122   void NAME(Register Rs, Register Rt, Register Rn) {                    \
1123     guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction");       \
1124     load_store_exclusive(Rs, Rt, dummy_reg, Rn, sz, op, o0); \
1125   }
1126 
1127 #define INSN2(NAME, sz, op, o0) /* Two registers */                     \
1128   void NAME(Register Rt, Register Rn) {                                 \
1129     load_store_exclusive(dummy_reg, Rt, dummy_reg, \
1130                          Rn, sz, op, o0);                               \
1131   }
1132 
1133 #define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \
1134   void NAME(Register Rt1, Register Rt2, Register Rn) {                  \
1135     guarantee(Rt1 != Rt2, "unpredictable instruction");                 \
1136     load_store_exclusive(dummy_reg, Rt1, Rt2, Rn, sz, op, o0);          \
1137   }
1138 
1139   // bytes
1140   INSN3(stxrb, byte, 0b000, 0);
1141   INSN3(stlxrb, byte, 0b000, 1);
1142   INSN2(ldxrb, byte, 0b010, 0);
1143   INSN2(ldaxrb, byte, 0b010, 1);
1144   INSN2(stlrb, byte, 0b100, 1);
1145   INSN2(ldarb, byte, 0b110, 1);
1146 
1147   // halfwords
1148   INSN3(stxrh, halfword, 0b000, 0);
1149   INSN3(stlxrh, halfword, 0b000, 1);
1150   INSN2(ldxrh, halfword, 0b010, 0);
1151   INSN2(ldaxrh, halfword, 0b010, 1);
1152   INSN2(stlrh, halfword, 0b100, 1);
1153   INSN2(ldarh, halfword, 0b110, 1);
1154 
1155   // words
1156   INSN3(stxrw, word, 0b000, 0);


1163   INSN_FOO(ldaxpw, word, 0b011, 1);
1164   INSN2(stlrw, word, 0b100, 1);
1165   INSN2(ldarw, word, 0b110, 1);
1166 
1167   // xwords
1168   INSN3(stxr, xword, 0b000, 0);
1169   INSN3(stlxr, xword, 0b000, 1);
1170   INSN4(stxp, xword, 0b001, 0);
1171   INSN4(stlxp, xword, 0b001, 1);
1172   INSN2(ldxr, xword, 0b010, 0);
1173   INSN2(ldaxr, xword, 0b010, 1);
1174   INSN_FOO(ldxp, xword, 0b011, 0);
1175   INSN_FOO(ldaxp, xword, 0b011, 1);
1176   INSN2(stlr, xword, 0b100, 1);
1177   INSN2(ldar, xword, 0b110, 1);
1178 
1179 #undef INSN2
1180 #undef INSN3
1181 #undef INSN4
1182 #undef INSN_FOO
1183 
1184   // 8.1 Compare and swap extensions
1185   void lse_cas(Register Rs, Register Rt, Register Rn,
1186                         enum operand_size sz, bool a, bool r, bool not_pair) {
1187     starti;
1188     if (! not_pair) { // Pair
1189       assert(sz == word || sz == xword, "invalid size");
1190       /* The size bit is in bit 30, not 31 */
1191       sz = (operand_size)(sz == word ? 0b00:0b01);
1192     }
1193     f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21);
1194     rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0);
1195   }
1196 
1197   // CAS
1198 #define INSN(NAME, a, r)                                                \
1199   void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) {   \
1200     assert(Rs != Rn && Rs != Rt, "unpredictable instruction");          \
1201     lse_cas(Rs, Rt, Rn, sz, a, r, true);                                \
1202   }
1203   INSN(cas,    false, false)
1204   INSN(casa,   true,  false)
1205   INSN(casl,   false, true)
1206   INSN(casal,  true,  true)
1207 #undef INSN
1208 
1209   // CASP
1210 #define INSN(NAME, a, r)                                                \
1211   void NAME(operand_size sz, Register Rs, Register Rs1,                 \
1212             Register Rt, Register Rt1, Register Rn) {                   \
1213     assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 &&    \
1214            Rs->successor() == Rs1 && Rt->successor() == Rt1 &&          \
1215            Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers");     \
1216     lse_cas(Rs, Rt, Rn, sz, a, r, false);                               \
1217   }
1218   INSN(casp,    false, false)
1219   INSN(caspa,   true,  false)
1220   INSN(caspl,   false, true)
1221   INSN(caspal,  true,  true)
1222 #undef INSN
1223 
1224   // Load register (literal)
1225 #define INSN(NAME, opc, V)                                              \
1226   void NAME(Register Rt, address dest) {                                \
1227     long offset = (dest - pc()) >> 2;                                   \
1228     starti;                                                             \
1229     f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24),        \
1230       sf(offset, 23, 5);                                                \
1231     rf(Rt, 0);                                                          \
1232   }                                                                     \
1233   void NAME(Register Rt, address dest, relocInfo::relocType rtype) {    \
1234     InstructionMark im(this);                                           \
1235     guarantee(rtype == relocInfo::internal_word_type,                   \
1236               "only internal_word_type relocs make sense here");        \
1237     code_section()->relocate(inst_mark(), InternalAddress(dest).rspec()); \
1238     NAME(Rt, dest);                                                     \
1239   }                                                                     \
1240   void NAME(Register Rt, Label &L) {                                    \
1241     wrap_label(Rt, L, &Assembler::NAME);                                \
1242   }


< prev index next >