History

arm-asm: Add ldc, ldcl, stc, stcl

Danny Milosavljevic committed 5 years ago

Commit 7900a6b1 parent d1a6c4a3 files · +188 −1Browse files

Unified · Split

3 files
  1. arm-asm.c +177 −1
  2. arm-tok.h +5 −0
  3. tests/arm-asm-testsuite.sh +6 −0
arm-asm.c+177−1
@@ -165,6 +165,10 @@ static void asm_emit_opcode(int token, uint32_t opcode) { · 164 unmodified lines
165 gen_le32((condition_code_of_token(token) << 28) | opcode);165 gen_le32((condition_code_of_token(token) << 28) | opcode);
166}166}
167 167
168static void asm_emit_unconditional_opcode(uint32_t opcode) {
169 gen_le32(opcode);
170}
171
168static void asm_emit_coprocessor_opcode(uint32_t high_nibble, uint8_t cp_number, uint8_t cp_opcode, uint8_t cp_destination_register, uint8_t cp_n_operand_register, uint8_t cp_m_operand_register, uint8_t cp_opcode2, int inter_processor_transfer)172static void asm_emit_coprocessor_opcode(uint32_t high_nibble, uint8_t cp_number, uint8_t cp_opcode, uint8_t cp_destination_register, uint8_t cp_n_operand_register, uint8_t cp_m_operand_register, uint8_t cp_opcode2, int inter_processor_transfer)
169{173{
170 uint32_t opcode = 0xe000000;174 uint32_t opcode = 0xe000000;
@@ -182,7 +186,7 @@ static void asm_emit_coprocessor_opcode(uint32_t high_nibble, uint8_t cp_number, · 11 unmodified lines
182 opcode |= cp_opcode2 << 5;186 opcode |= cp_opcode2 << 5;
183 //assert(cp_m_operand_register < 16);187 //assert(cp_m_operand_register < 16);
184 opcode |= cp_m_operand_register;188 opcode |= cp_m_operand_register;
185 gen_le32((high_nibble << 28) | opcode);189 asm_emit_unconditional_opcode((high_nibble << 28) | opcode);
186}190}
187 191
188static void asm_nullary_opcode(int token)192static void asm_nullary_opcode(int token)
@@ -1260,6 +1264,171 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token) · 1071 unmodified lines
1260 }1264 }
1261}1265}
1262 1266
1267static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_number, uint8_t CRd, const Operand* Rn, const Operand* offset, int offset_minus, int preincrement, int writeback, int long_transfer, int load) {
1268 uint32_t opcode = 0x0;
1269 opcode |= 1 << 26; // Load/Store
1270 opcode |= 1 << 27; // coprocessor
1271
1272 if (long_transfer)
1273 opcode |= 1 << 22; // long transfer
1274
1275 if (load)
1276 opcode |= 1 << 20; // L
1277
1278 opcode |= cp_number << 8;
1279
1280 opcode |= ENCODE_RD(CRd);
1281
1282 if (Rn->type != OP_REG32) {
1283 expect("register");
1284 return;
1285 }
1286 opcode |= ENCODE_RN(Rn->reg);
1287 if (preincrement)
1288 opcode |= 1 << 24; // add offset before transfer
1289
1290 if (writeback)
1291 opcode |= 1 << 21; // write offset back into register
1292
1293 if (offset->type == OP_IM8 || offset->type == OP_IM8N || offset->type == OP_IM32) {
1294 int v = offset->e.v;
1295 if (offset_minus)
1296 tcc_error("minus before '#' not supported for immediate values");
1297 if (offset->type == OP_IM8N || v < 0)
1298 v = -v;
1299 else
1300 opcode |= 1 << 23; // up
1301 if (v & 3) {
1302 tcc_error("immediate offset must be a multiple of 4");
1303 return;
1304 }
1305 v >>= 2;
1306 if (v > 255) {
1307 tcc_error("immediate offset must be between -1020 and 1020");
1308 return;
1309 }
1310 opcode |= v;
1311 } else if (offset->type == OP_REG32) {
1312 if (!offset_minus)
1313 opcode |= 1 << 23; // up
1314 opcode |= ENCODE_IMMEDIATE_FLAG; /* if set, it means it's NOT immediate */
1315 opcode |= offset->reg;
1316 tcc_error("Using register offset to register address is not possible here");
1317 return;
1318 } else
1319 expect("immediate or register");
1320
1321 asm_emit_unconditional_opcode((high_nibble << 28) | opcode);
1322}
1323
1324// Almost exactly the same as asm_single_data_transfer_opcode.
1325// Difference: Offsets are smaller and multiples of 4; no shifts, no STREX, ENCODE_IMMEDIATE_FLAG is inverted again.
1326static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token)
1327{
1328 Operand ops[3];
1329 uint8_t coprocessor;
1330 uint8_t coprocessor_destination_register;
1331 int preincrement = 0;
1332 int exclam = 0;
1333 int closed_bracket = 0;
1334 int op2_minus = 0;
1335 int long_transfer = 0;
1336 // Note: ldc p1, c0, [r4, #4] ; simple offset: r0 = *(int*)(r4+4); r4 unchanged
1337 // Note: ldc p2, c0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+4
1338 // Note: ldc p3, c0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+4
1339
1340 if (tok >= TOK_ASM_p0 && tok <= TOK_ASM_p15) {
1341 coprocessor = tok - TOK_ASM_p0;
1342 next();
1343 } else {
1344 expect("'c<number>'");
1345 return;
1346 }
1347
1348 if (tok == ',')
1349 next();
1350 else
1351 expect("','");
1352
1353 if (tok >= TOK_ASM_c0 && tok <= TOK_ASM_c15) {
1354 coprocessor_destination_register = tok - TOK_ASM_c0;
1355 next();
1356 } else {
1357 expect("'c<number>'");
1358 return;
1359 }
1360
1361 if (tok == ',')
1362 next();
1363 else
1364 expect("','");
1365
1366 if (tok != '[')
1367 expect("'['");
1368 else
1369 next(); // skip '['
1370
1371 parse_operand(s1, &ops[1]);
1372 if (ops[1].type != OP_REG32) {
1373 expect("(first source operand) register");
1374 return;
1375 }
1376 if (tok == ']') {
1377 next();
1378 closed_bracket = 1;
1379 // exclam = 1; // implicit in hardware; don't do it in software
1380 }
1381 if (tok == ',') {
1382 next(); // skip ','
1383 if (tok == '-') {
1384 op2_minus = 1;
1385 next();
1386 }
1387 parse_operand(s1, &ops[2]);
1388 if (ops[2].type == OP_REG32) {
1389 if (ops[2].reg == 15) {
1390 tcc_error("Using 'pc' for register offset in '%s' is not implemented by ARM", get_tok_str(token, NULL));
1391 return;
1392 }
1393 }
1394 } else {
1395 // end of input expression in brackets--assume 0 offset
1396 ops[2].type = OP_IM8;
1397 ops[2].e.v = 0;
1398 preincrement = 1; // add offset before transfer
1399 }
1400 if (!closed_bracket) {
1401 if (tok != ']')
1402 expect("']'");
1403 else
1404 next(); // skip ']'
1405 preincrement = 1; // add offset before transfer
1406 if (tok == '!') {
1407 exclam = 1;
1408 next(); // skip '!'
1409 }
1410 }
1411
1412 // TODO: Support options.
1413
1414 switch (ARM_INSTRUCTION_GROUP(token)) {
1415 case TOK_ASM_stcleq:
1416 long_transfer = 1;
1417 /* fallthrough */
1418 case TOK_ASM_stceq:
1419 asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, coprocessor_destination_register, &ops[1], &ops[2], op2_minus, preincrement, exclam, long_transfer, 0);
1420 break;
1421 case TOK_ASM_ldcleq:
1422 long_transfer = 1;
1423 /* fallthrough */
1424 case TOK_ASM_ldceq:
1425 asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, coprocessor_destination_register, &ops[1], &ops[2], op2_minus, preincrement, exclam, long_transfer, 1);
1426 break;
1427 default:
1428 expect("coprocessor data transfer instruction");
1429 }
1430}
1431
1263static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)1432static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
1264{1433{
1265 Operand ops[3];1434 Operand ops[3];
@@ -1589,6 +1758,13 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 323 unmodified lines
1589 case TOK_ASM_mcreq:1758 case TOK_ASM_mcreq:
1590 case TOK_ASM_mrceq:1759 case TOK_ASM_mrceq:
1591 return asm_coprocessor_opcode(s1, token);1760 return asm_coprocessor_opcode(s1, token);
1761
1762 case TOK_ASM_ldceq:
1763 case TOK_ASM_ldcleq:
1764 case TOK_ASM_stceq:
1765 case TOK_ASM_stcleq:
1766 return asm_coprocessor_data_transfer_opcode(s1, token);
1767
1592 default:1768 default:
1593 expect("known instruction");1769 expect("known instruction");
1594 }1770 }
arm-tok.h+5−0
@@ -155,6 +155,11 @@ · 154 unmodified lines
155 DEF_ASM_CONDED(stmib)155 DEF_ASM_CONDED(stmib)
156 DEF_ASM_CONDED(ldmib)156 DEF_ASM_CONDED(ldmib)
157 157
158 DEF_ASM_CONDED(ldc)
159 DEF_ASM_CONDED(ldcl)
160 DEF_ASM_CONDED(stc)
161 DEF_ASM_CONDED(stcl)
162
158 /* instruction macros */163 /* instruction macros */
159 164
160 DEF_ASM_CONDED(push)165 DEF_ASM_CONDED(push)
tests/arm-asm-testsuite.sh+6−0
@@ -97,6 +97,12 @@ do · 96 unmodified lines
97 "p10, #7, r2, c0, c1, #4" \97 "p10, #7, r2, c0, c1, #4" \
98 "#4" \98 "#4" \
99 "#-4" \99 "#-4" \
100 "p5, c2, [r3]" \
101 "p5, c3, [r4]" \
102 "p5, c2, [r3, #4]" \
103 "p5, c2, [r3, #-4]" \
104 "p5, c2, [r3, #0x45]" \
105 "p5, c2, [r3, #-0x45]" \
100 ""106 ""
101 do107 do
102 #echo ".syntax unified" > a.s108 #echo ".syntax unified" > a.s

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t