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
248248 Note: For single data transfer instructions, "0" means immediate. */
249249 #define ENCODE_IMMEDIATE_FLAG (1 << 25)
250250
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+
251259 static void asm_block_data_transfer_opcode(TCCState *s1, int token)
252260 {
253261 uint32_t opcode;
@@ -355,6 +363,52 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) · 101 unmodified lines
355363 }
356364 }
357365
366+static 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+
386+static 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+
358412 static void asm_data_processing_opcode(TCCState *s1, int token)
359413 {
360414 Operand ops[3];
@@ -486,6 +540,102 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 125 unmodified lines
486540 }
487541 }
488542
543+static 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+
489639 static void asm_multiplication_opcode(TCCState *s1, int token)
490640 {
491641 Operand ops[4];
@@ -902,6 +1052,18 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 410 unmodified lines
9021052 case TOK_ASM_mvnseq:
9031053 return asm_data_processing_opcode(s1, token);
9041054
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+
9051067 case TOK_ASM_muleq:
9061068 case TOK_ASM_mulseq:
9071069 case TOK_ASM_mlaeq:
arm-tok.h+11−0
@@ -145,3 +145,14 @@ · 144 unmodified lines
145145 DEF_ASM_CONDED(bics)
146146 DEF_ASM_CONDED(mvn)
147147 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