History

arm-asm: Add lsl, lsr, asr, ror, rrx

Danny Milosavljevic committed 5 years ago

Commit abef8f61 parent b940d8e2 files · +173 −0Browse files

Unified · Split

2 files
  1. arm-asm.c +162 −0
  2. arm-tok.h +11 −0
arm-asm.c+162−0
@@ -248,6 +248,14 @@ static void asm_binary_opcode(TCCState *s1, int token) · 247 unmodified lines
248 Note: For single data transfer instructions, "0" means immediate. */248 Note: For single data transfer instructions, "0" means immediate. */
249#define ENCODE_IMMEDIATE_FLAG (1 << 25)249#define ENCODE_IMMEDIATE_FLAG (1 << 25)
250 250
251#define ENCODE_BARREL_SHIFTER_SHIFT_BY_REGISTER (1 << 4)
252#define ENCODE_BARREL_SHIFTER_MODE_LSL (0 << 5)
253#define ENCODE_BARREL_SHIFTER_MODE_LSR (1 << 5)
254#define ENCODE_BARREL_SHIFTER_MODE_ASR (2 << 5)
255#define ENCODE_BARREL_SHIFTER_MODE_ROR (3 << 5)
256#define ENCODE_BARREL_SHIFTER_REGISTER(register_index) ((register_index) << 8)
257#define ENCODE_BARREL_SHIFTER_IMMEDIATE(value) ((value) << 7)
258
251static void asm_block_data_transfer_opcode(TCCState *s1, int token)259static void asm_block_data_transfer_opcode(TCCState *s1, int token)
252{260{
253 uint32_t opcode;261 uint32_t opcode;
@@ -355,6 +363,52 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) · 101 unmodified lines
355 }363 }
356}364}
357 365
366static uint32_t asm_encode_rotation(Operand* rotation)
367{
368 uint64_t amount;
369 switch (rotation->type) {
370 case OP_REG32:
371 tcc_error("cannot rotate immediate value by register");
372 return 0;
373 case OP_IM8:
374 amount = rotation->e.v;
375 if (amount >= 0 && amount < 32 && (amount & 1) == 0)
376 return (amount >> 1) << 8;
377 else
378 tcc_error("rotating is only possible by a multiple of 2");
379 break;
380 default:
381 tcc_error("unknown rotation amount");
382 return 0;
383 }
384}
385
386static uint32_t asm_encode_shift(Operand* shift)
387{
388 uint64_t amount;
389 uint32_t operands = 0;
390 switch (shift->type) {
391 case OP_REG32:
392 if (shift->reg == 15)
393 tcc_error("r15 cannot be used as a shift count");
394 else {
395 operands = ENCODE_BARREL_SHIFTER_SHIFT_BY_REGISTER;
396 operands |= ENCODE_BARREL_SHIFTER_REGISTER(shift->reg);
397 }
398 break;
399 case OP_IM8:
400 amount = shift->e.v;
401 if (amount > 0 && amount < 32)
402 operands = ENCODE_BARREL_SHIFTER_IMMEDIATE(amount);
403 else
404 tcc_error("shift count out of range");
405 break;
406 default:
407 tcc_error("unknown shift amount");
408 }
409 return operands;
410}
411
358static void asm_data_processing_opcode(TCCState *s1, int token)412static void asm_data_processing_opcode(TCCState *s1, int token)
359{413{
360 Operand ops[3];414 Operand ops[3];
@@ -486,6 +540,102 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 125 unmodified lines
486 }540 }
487}541}
488 542
543static void asm_shift_opcode(TCCState *s1, int token)
544{
545 Operand ops[3];
546 int nb_ops;
547 uint32_t opcode = 0xd << 21; // MOV
548 uint32_t operands = 0;
549
550 for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
551 parse_operand(s1, &ops[nb_ops]);
552 if (tok != ',') {
553 ++nb_ops;
554 break;
555 }
556 next(); // skip ','
557 }
558 if (nb_ops < 2) {
559 expect("at least two operands");
560 return;
561 }
562
563 if (ops[0].type != OP_REG32)
564 expect("(destination operand) register");
565 else
566 operands |= ENCODE_RD(ops[0].reg);
567
568 if (nb_ops == 2) {
569 switch (ARM_INSTRUCTION_GROUP(token)) {
570 case TOK_ASM_rrxseq:
571 opcode |= ENCODE_SET_CONDITION_CODES;
572 /* fallthrough */
573 case TOK_ASM_rrxeq:
574 if (ops[1].type == OP_REG32) {
575 operands |= ops[1].reg;
576 operands |= ENCODE_BARREL_SHIFTER_MODE_ROR;
577 asm_emit_opcode(token, opcode | operands);
578 } else
579 tcc_error("(first source operand) register");
580 return;
581 default:
582 memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2]
583 memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit
584 nb_ops = 3;
585 }
586 }
587 if (nb_ops != 3) {
588 expect("two or three operands");
589 return;
590 }
591
592 switch (ops[1].type) {
593 case OP_REG32:
594 operands |= ops[1].reg;
595 break;
596 case OP_IM8:
597 operands |= ENCODE_IMMEDIATE_FLAG;
598 operands |= ops[1].e.v;
599 break;
600 }
601
602 if (operands & ENCODE_IMMEDIATE_FLAG)
603 operands |= asm_encode_rotation(&ops[2]);
604 else
605 operands |= asm_encode_shift(&ops[2]);
606
607 switch (ARM_INSTRUCTION_GROUP(token)) {
608 case TOK_ASM_lslseq:
609 opcode |= ENCODE_SET_CONDITION_CODES;
610 /* fallthrough */
611 case TOK_ASM_lsleq:
612 operands |= ENCODE_BARREL_SHIFTER_MODE_LSL;
613 break;
614 case TOK_ASM_lsrseq:
615 opcode |= ENCODE_SET_CONDITION_CODES;
616 /* fallthrough */
617 case TOK_ASM_lsreq:
618 operands |= ENCODE_BARREL_SHIFTER_MODE_LSR;
619 break;
620 case TOK_ASM_asrseq:
621 opcode |= ENCODE_SET_CONDITION_CODES;
622 /* fallthrough */
623 case TOK_ASM_asreq:
624 operands |= ENCODE_BARREL_SHIFTER_MODE_ASR;
625 break;
626 case TOK_ASM_rorseq:
627 opcode |= ENCODE_SET_CONDITION_CODES;
628 /* fallthrough */
629 case TOK_ASM_roreq:
630 operands |= ENCODE_BARREL_SHIFTER_MODE_ROR;
631 break;
632 default:
633 expect("shift instruction");
634 return;
635 }
636 asm_emit_opcode(token, opcode | operands);
637}
638
489static void asm_multiplication_opcode(TCCState *s1, int token)639static void asm_multiplication_opcode(TCCState *s1, int token)
490{640{
491 Operand ops[4];641 Operand ops[4];
@@ -902,6 +1052,18 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 410 unmodified lines
902 case TOK_ASM_mvnseq:1052 case TOK_ASM_mvnseq:
903 return asm_data_processing_opcode(s1, token);1053 return asm_data_processing_opcode(s1, token);
904 1054
1055 case TOK_ASM_lsleq:
1056 case TOK_ASM_lslseq:
1057 case TOK_ASM_lsreq:
1058 case TOK_ASM_lsrseq:
1059 case TOK_ASM_asreq:
1060 case TOK_ASM_asrseq:
1061 case TOK_ASM_roreq:
1062 case TOK_ASM_rorseq:
1063 case TOK_ASM_rrxseq:
1064 case TOK_ASM_rrxeq:
1065 return asm_shift_opcode(s1, token);
1066
905 case TOK_ASM_muleq:1067 case TOK_ASM_muleq:
906 case TOK_ASM_mulseq:1068 case TOK_ASM_mulseq:
907 case TOK_ASM_mlaeq:1069 case TOK_ASM_mlaeq:
arm-tok.h+11−0
@@ -145,3 +145,14 @@ · 144 unmodified lines
145 DEF_ASM_CONDED(bics)145 DEF_ASM_CONDED(bics)
146 DEF_ASM_CONDED(mvn)146 DEF_ASM_CONDED(mvn)
147 DEF_ASM_CONDED(mvns)147 DEF_ASM_CONDED(mvns)
148
149 DEF_ASM_CONDED(lsl)
150 DEF_ASM_CONDED(lsls)
151 DEF_ASM_CONDED(lsr)
152 DEF_ASM_CONDED(lsrs)
153 DEF_ASM_CONDED(asr)
154 DEF_ASM_CONDED(asrs)
155 DEF_ASM_CONDED(ror)
156 DEF_ASM_CONDED(rors)
157 DEF_ASM_CONDED(rrx)
158 DEF_ASM_CONDED(rrxs)

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