Revision 67dcab73 tcg/arm/tcg-target.c
b/tcg/arm/tcg-target.c | ||
---|---|---|
151 | 151 |
break; |
152 | 152 |
|
153 | 153 |
case 'r': |
154 |
#ifndef CONFIG_SOFTMMU |
|
155 |
case 'd': |
|
156 |
case 'D': |
|
157 |
case 'x': |
|
158 |
case 'X': |
|
159 |
#endif |
|
160 | 154 |
ct->ct |= TCG_CT_REG; |
161 | 155 |
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); |
162 | 156 |
break; |
163 | 157 |
|
164 |
#ifdef CONFIG_SOFTMMU |
|
165 |
/* qemu_ld/st inputs (unless 'X', 'd' or 'D') */ |
|
166 |
case 'x': |
|
158 |
/* qemu_ld address */ |
|
159 |
case 'l': |
|
167 | 160 |
ct->ct |= TCG_CT_REG; |
168 | 161 |
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); |
162 |
#ifdef CONFIG_SOFTMMU |
|
163 |
/* r0 and r1 will be overwritten when reading the tlb entry, |
|
164 |
so don't use these. */ |
|
169 | 165 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); |
170 | 166 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); |
167 |
#endif |
|
171 | 168 |
break; |
172 |
|
|
173 |
/* qemu_ld64 data_reg */ |
|
174 |
case 'd': |
|
169 |
case 'L': |
|
175 | 170 |
ct->ct |= TCG_CT_REG; |
176 | 171 |
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); |
177 |
/* r1 is still needed to load data_reg2, so don't use it. */ |
|
172 |
#ifdef CONFIG_SOFTMMU |
|
173 |
/* r1 is still needed to load data_reg or data_reg2, |
|
174 |
so don't use it. */ |
|
178 | 175 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); |
176 |
#endif |
|
179 | 177 |
break; |
180 | 178 |
|
181 |
/* qemu_ld/st64 data_reg2 */
|
|
182 |
case 'D':
|
|
179 |
/* qemu_st address & data_reg */
|
|
180 |
case 's':
|
|
183 | 181 |
ct->ct |= TCG_CT_REG; |
184 | 182 |
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); |
185 |
/* r0, r1 and optionally r2 will be overwritten by the address |
|
186 |
* and the low word of data, so don't use these. */ |
|
183 |
/* r0 and r1 will be overwritten when reading the tlb entry |
|
184 |
(softmmu only) and doing the byte swapping, so don't |
|
185 |
use these. */ |
|
187 | 186 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); |
188 | 187 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); |
189 |
# if TARGET_LONG_BITS == 64 |
|
190 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); |
|
191 |
# endif |
|
192 | 188 |
break; |
193 |
|
|
194 |
# if TARGET_LONG_BITS == 64 |
|
195 |
/* qemu_ld/st addr_reg2 */ |
|
196 |
case 'X': |
|
189 |
/* qemu_st64 data_reg2 */ |
|
190 |
case 'S': |
|
197 | 191 |
ct->ct |= TCG_CT_REG; |
198 | 192 |
tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); |
199 |
/* r0 will be overwritten by the low word of base, so don't use it. */ |
|
193 |
/* r0 and r1 will be overwritten when reading the tlb entry |
|
194 |
(softmmu only) and doing the byte swapping, so don't |
|
195 |
use these. */ |
|
200 | 196 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); |
201 | 197 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); |
202 |
break; |
|
203 |
# endif |
|
198 |
#ifdef CONFIG_SOFTMMU |
|
199 |
/* r2 is still needed to load data_reg, so don't use it. */ |
|
200 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); |
|
204 | 201 |
#endif |
202 |
break; |
|
205 | 203 |
|
206 | 204 |
default: |
207 | 205 |
return -1; |
... | ... | |
533 | 531 |
} |
534 | 532 |
} |
535 | 533 |
|
534 |
static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn) |
|
535 |
{ |
|
536 |
if (use_armv6_instructions) { |
|
537 |
/* revsh */ |
|
538 |
tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn); |
|
539 |
} else { |
|
540 |
tcg_out_dat_reg(s, cond, ARITH_MOV, |
|
541 |
TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24)); |
|
542 |
tcg_out_dat_reg(s, cond, ARITH_MOV, |
|
543 |
TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16)); |
|
544 |
tcg_out_dat_reg(s, cond, ARITH_ORR, |
|
545 |
rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8)); |
|
546 |
} |
|
547 |
} |
|
548 |
|
|
536 | 549 |
static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn) |
537 | 550 |
{ |
538 | 551 |
if (use_armv6_instructions) { |
... | ... | |
912 | 925 |
|
913 | 926 |
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) |
914 | 927 |
{ |
915 |
int addr_reg, data_reg, data_reg2; |
|
928 |
int addr_reg, data_reg, data_reg2, bswap;
|
|
916 | 929 |
#ifdef CONFIG_SOFTMMU |
917 | 930 |
int mem_index, s_bits; |
918 | 931 |
# if TARGET_LONG_BITS == 64 |
... | ... | |
921 | 934 |
uint32_t *label_ptr; |
922 | 935 |
#endif |
923 | 936 |
|
937 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
938 |
bswap = 1; |
|
939 |
#else |
|
940 |
bswap = 0; |
|
941 |
#endif |
|
924 | 942 |
data_reg = *args++; |
925 | 943 |
if (opc == 3) |
926 | 944 |
data_reg2 = *args++; |
... | ... | |
987 | 1005 |
break; |
988 | 1006 |
case 1: |
989 | 1007 |
tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
1008 |
if (bswap) { |
|
1009 |
tcg_out_bswap16(s, COND_EQ, data_reg, data_reg); |
|
1010 |
} |
|
990 | 1011 |
break; |
991 | 1012 |
case 1 | 4: |
992 |
tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1013 |
if (bswap) { |
|
1014 |
tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1015 |
tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg); |
|
1016 |
} else { |
|
1017 |
tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1018 |
} |
|
993 | 1019 |
break; |
994 | 1020 |
case 2: |
995 | 1021 |
default: |
996 | 1022 |
tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
1023 |
if (bswap) { |
|
1024 |
tcg_out_bswap32(s, COND_EQ, data_reg, data_reg); |
|
1025 |
} |
|
997 | 1026 |
break; |
998 | 1027 |
case 3: |
999 |
tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg); |
|
1000 |
tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4); |
|
1028 |
if (bswap) { |
|
1029 |
tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg); |
|
1030 |
tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4); |
|
1031 |
tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2); |
|
1032 |
tcg_out_bswap32(s, COND_EQ, data_reg, data_reg); |
|
1033 |
} else { |
|
1034 |
tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg); |
|
1035 |
tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4); |
|
1036 |
} |
|
1001 | 1037 |
break; |
1002 | 1038 |
} |
1003 | 1039 |
|
... | ... | |
1075 | 1111 |
break; |
1076 | 1112 |
case 1: |
1077 | 1113 |
tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0); |
1114 |
if (bswap) { |
|
1115 |
tcg_out_bswap16(s, COND_AL, data_reg, data_reg); |
|
1116 |
} |
|
1078 | 1117 |
break; |
1079 | 1118 |
case 1 | 4: |
1080 |
tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0); |
|
1119 |
if (bswap) { |
|
1120 |
tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0); |
|
1121 |
tcg_out_bswap16s(s, COND_AL, data_reg, data_reg); |
|
1122 |
} else { |
|
1123 |
tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0); |
|
1124 |
} |
|
1081 | 1125 |
break; |
1082 | 1126 |
case 2: |
1083 | 1127 |
default: |
1084 | 1128 |
tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0); |
1129 |
if (bswap) { |
|
1130 |
tcg_out_bswap32(s, COND_AL, data_reg, data_reg); |
|
1131 |
} |
|
1085 | 1132 |
break; |
1086 | 1133 |
case 3: |
1087 | 1134 |
/* TODO: use block load - |
1088 | 1135 |
* check that data_reg2 > data_reg or the other way */ |
1089 | 1136 |
if (data_reg == addr_reg) { |
1090 |
tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4); |
|
1091 |
tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0); |
|
1137 |
tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
|
|
1138 |
tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
|
|
1092 | 1139 |
} else { |
1093 |
tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0); |
|
1094 |
tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4); |
|
1140 |
tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0); |
|
1141 |
tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4); |
|
1142 |
} |
|
1143 |
if (bswap) { |
|
1144 |
tcg_out_bswap32(s, COND_AL, data_reg, data_reg); |
|
1145 |
tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2); |
|
1095 | 1146 |
} |
1096 | 1147 |
break; |
1097 | 1148 |
} |
... | ... | |
1100 | 1151 |
|
1101 | 1152 |
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) |
1102 | 1153 |
{ |
1103 |
int addr_reg, data_reg, data_reg2; |
|
1154 |
int addr_reg, data_reg, data_reg2, bswap;
|
|
1104 | 1155 |
#ifdef CONFIG_SOFTMMU |
1105 | 1156 |
int mem_index, s_bits; |
1106 | 1157 |
# if TARGET_LONG_BITS == 64 |
... | ... | |
1109 | 1160 |
uint32_t *label_ptr; |
1110 | 1161 |
#endif |
1111 | 1162 |
|
1163 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
1164 |
bswap = 1; |
|
1165 |
#else |
|
1166 |
bswap = 0; |
|
1167 |
#endif |
|
1112 | 1168 |
data_reg = *args++; |
1113 | 1169 |
if (opc == 3) |
1114 | 1170 |
data_reg2 = *args++; |
... | ... | |
1168 | 1224 |
tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
1169 | 1225 |
break; |
1170 | 1226 |
case 1: |
1171 |
tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1227 |
if (bswap) { |
|
1228 |
tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg); |
|
1229 |
tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1); |
|
1230 |
} else { |
|
1231 |
tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1232 |
} |
|
1172 | 1233 |
break; |
1173 | 1234 |
case 2: |
1174 | 1235 |
default: |
1175 |
tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1236 |
if (bswap) { |
|
1237 |
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg); |
|
1238 |
tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1); |
|
1239 |
} else { |
|
1240 |
tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1); |
|
1241 |
} |
|
1176 | 1242 |
break; |
1177 | 1243 |
case 3: |
1178 |
tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg); |
|
1179 |
tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4); |
|
1244 |
if (bswap) { |
|
1245 |
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2); |
|
1246 |
tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg); |
|
1247 |
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg); |
|
1248 |
tcg_out_st32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4); |
|
1249 |
} else { |
|
1250 |
tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg); |
|
1251 |
tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4); |
|
1252 |
} |
|
1180 | 1253 |
break; |
1181 | 1254 |
} |
1182 | 1255 |
|
... | ... | |
1271 | 1344 |
i = ctz32(offset) & ~1; |
1272 | 1345 |
rot = ((32 - i) << 7) & 0xf00; |
1273 | 1346 |
|
1274 |
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
|
|
1347 |
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
|
|
1275 | 1348 |
((offset >> i) & 0xff) | rot); |
1276 |
addr_reg = TCG_REG_R8;
|
|
1349 |
addr_reg = TCG_REG_R1;
|
|
1277 | 1350 |
offset &= ~(0xff << i); |
1278 | 1351 |
} |
1279 | 1352 |
} |
... | ... | |
1282 | 1355 |
tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0); |
1283 | 1356 |
break; |
1284 | 1357 |
case 1: |
1285 |
tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0); |
|
1358 |
if (bswap) { |
|
1359 |
tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg); |
|
1360 |
tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0); |
|
1361 |
} else { |
|
1362 |
tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0); |
|
1363 |
} |
|
1286 | 1364 |
break; |
1287 | 1365 |
case 2: |
1288 | 1366 |
default: |
1289 |
tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0); |
|
1367 |
if (bswap) { |
|
1368 |
tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg); |
|
1369 |
tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0); |
|
1370 |
} else { |
|
1371 |
tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0); |
|
1372 |
} |
|
1290 | 1373 |
break; |
1291 | 1374 |
case 3: |
1292 | 1375 |
/* TODO: use block store - |
1293 | 1376 |
* check that data_reg2 > data_reg or the other way */ |
1294 |
tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0); |
|
1295 |
tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4); |
|
1377 |
if (bswap) { |
|
1378 |
tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2); |
|
1379 |
tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0); |
|
1380 |
tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg); |
|
1381 |
tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4); |
|
1382 |
} else { |
|
1383 |
tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0); |
|
1384 |
tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4); |
|
1385 |
} |
|
1296 | 1386 |
break; |
1297 | 1387 |
} |
1298 | 1388 |
#endif |
... | ... | |
1637 | 1727 |
{ INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } }, |
1638 | 1728 |
|
1639 | 1729 |
#if TARGET_LONG_BITS == 32 |
1640 |
{ INDEX_op_qemu_ld8u, { "r", "x" } },
|
|
1641 |
{ INDEX_op_qemu_ld8s, { "r", "x" } },
|
|
1642 |
{ INDEX_op_qemu_ld16u, { "r", "x" } },
|
|
1643 |
{ INDEX_op_qemu_ld16s, { "r", "x" } },
|
|
1644 |
{ INDEX_op_qemu_ld32, { "r", "x" } },
|
|
1645 |
{ INDEX_op_qemu_ld64, { "d", "r", "x" } },
|
|
1646 |
|
|
1647 |
{ INDEX_op_qemu_st8, { "x", "x" } },
|
|
1648 |
{ INDEX_op_qemu_st16, { "x", "x" } },
|
|
1649 |
{ INDEX_op_qemu_st32, { "x", "x" } },
|
|
1650 |
{ INDEX_op_qemu_st64, { "x", "D", "x" } },
|
|
1730 |
{ INDEX_op_qemu_ld8u, { "r", "l" } },
|
|
1731 |
{ INDEX_op_qemu_ld8s, { "r", "l" } },
|
|
1732 |
{ INDEX_op_qemu_ld16u, { "r", "l" } },
|
|
1733 |
{ INDEX_op_qemu_ld16s, { "r", "l" } },
|
|
1734 |
{ INDEX_op_qemu_ld32, { "r", "l" } },
|
|
1735 |
{ INDEX_op_qemu_ld64, { "L", "L", "l" } },
|
|
1736 |
|
|
1737 |
{ INDEX_op_qemu_st8, { "s", "s" } },
|
|
1738 |
{ INDEX_op_qemu_st16, { "s", "s" } },
|
|
1739 |
{ INDEX_op_qemu_st32, { "s", "s" } },
|
|
1740 |
{ INDEX_op_qemu_st64, { "s", "S", "s" } },
|
|
1651 | 1741 |
#else |
1652 |
{ INDEX_op_qemu_ld8u, { "r", "x", "X" } },
|
|
1653 |
{ INDEX_op_qemu_ld8s, { "r", "x", "X" } },
|
|
1654 |
{ INDEX_op_qemu_ld16u, { "r", "x", "X" } },
|
|
1655 |
{ INDEX_op_qemu_ld16s, { "r", "x", "X" } },
|
|
1656 |
{ INDEX_op_qemu_ld32, { "r", "x", "X" } },
|
|
1657 |
{ INDEX_op_qemu_ld64, { "d", "r", "x", "X" } },
|
|
1658 |
|
|
1659 |
{ INDEX_op_qemu_st8, { "x", "x", "X" } },
|
|
1660 |
{ INDEX_op_qemu_st16, { "x", "x", "X" } },
|
|
1661 |
{ INDEX_op_qemu_st32, { "x", "x", "X" } },
|
|
1662 |
{ INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
|
|
1742 |
{ INDEX_op_qemu_ld8u, { "r", "l", "l" } },
|
|
1743 |
{ INDEX_op_qemu_ld8s, { "r", "l", "l" } },
|
|
1744 |
{ INDEX_op_qemu_ld16u, { "r", "l", "l" } },
|
|
1745 |
{ INDEX_op_qemu_ld16s, { "r", "l", "l" } },
|
|
1746 |
{ INDEX_op_qemu_ld32, { "r", "l", "l" } },
|
|
1747 |
{ INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
|
|
1748 |
|
|
1749 |
{ INDEX_op_qemu_st8, { "s", "s", "s" } },
|
|
1750 |
{ INDEX_op_qemu_st16, { "s", "s", "s" } },
|
|
1751 |
{ INDEX_op_qemu_st32, { "s", "s", "s" } },
|
|
1752 |
{ INDEX_op_qemu_st64, { "s", "S", "s", "s" } },
|
|
1663 | 1753 |
#endif |
1664 | 1754 |
|
1665 | 1755 |
{ INDEX_op_bswap16_i32, { "r", "r" } }, |
Also available in: Unified diff