History

arm-asm: Add and, eor, sub, rsb, add, adc, sbc, rsc, tst, teq, cmp, cmn, orr, mov, bic, mvn

Danny Milosavljevic committed 5 years ago

Commit 3b1f06c1 parent c7682dd2 files · +200 −0Browse files

Unified · Split

2 files
  1. arm-asm.c +165 −0
  2. arm-tok.h +35 −0
arm-asm.c+165−0
@@ -347,6 +347,137 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) · 346 unmodified lines
347 }347 }
348}348}
349 349
350static void asm_data_processing_opcode(TCCState *s1, int token)
351{
352 Operand ops[3];
353 int nb_ops;
354
355 /* 16 entries per instruction for the different condition codes */
356 uint32_t opcode_idx = (ARM_INSTRUCTION_GROUP(token) - TOK_ASM_andeq) >> 4;
357
358 for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
359 parse_operand(s1, &ops[nb_ops]);
360 if (tok != ',') {
361 ++nb_ops;
362 break;
363 }
364 next(); // skip ','
365 }
366 if (nb_ops < 2)
367 expect("at least two operands");
368 else if (nb_ops == 2) {
369 memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2]
370 memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit
371 nb_ops = 3;
372 }
373 if (nb_ops != 3) {
374 expect("two or three operands");
375 return;
376 } else {
377 uint32_t opcode = 0;
378 uint32_t operands = 0;
379
380 // data processing (general case):
381 // operands:
382 // Rn: bits 19...16 (first operand)
383 // Rd: bits 15...12 (destination)
384 // Operand2: bits 11...0 (second operand); depending on I that's either a register or an immediate
385 // operator:
386 // bits 24...21: "OpCode"--see below
387
388 /* operations in the token list are ordered by opcode */
389 opcode = (opcode_idx >> 1) << 21; // drop "s"
390 if (ops[0].type != OP_REG32)
391 expect("(destination operand) register");
392 else if (opcode == 0xa << 21 || opcode == 0xb << 21 || opcode == 0x8 << 21 || opcode == 0x9 << 21 ) // cmp, cmn, tst, teq
393 operands |= ENCODE_SET_CONDITION_CODES; // force S set, otherwise it's a completely different instruction.
394 else
395 operands |= ENCODE_RD(ops[0].reg);
396 if (ops[1].type != OP_REG32)
397 expect("(first source operand) register");
398 else if (!(opcode == 0xd << 21 || opcode == 0xf << 21)) // not: mov, mvn (those have only one source operand)
399 operands |= ENCODE_RN(ops[1].reg);
400 switch (ops[2].type) {
401 case OP_REG32:
402 // TODO: Parse and encode shift.
403 operands |= ops[2].reg;
404 break;
405 case OP_IM8:
406 // TODO: Parse and encode rotation.
407 operands |= ENCODE_IMMEDIATE_FLAG;
408 operands |= ops[2].e.v;
409 break;
410 case OP_IM8N: // immediate negative value
411 // TODO: Parse and encode rotation.
412 operands |= ENCODE_IMMEDIATE_FLAG;
413 /* Instruction swapping:
414 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult
415 0011 = RSB - Rd:= Op2 - Op1 -> difficult
416 0111 = RSC - Rd:= Op2 - Op1 + C -> difficult
417 1000 = TST - CC on: Op1 AND Op2 -> difficult
418 1001 = TEQ - CC on: Op1 EOR Op2 -> difficult
419 1100 = ORR - Rd:= Op1 OR Op2 -> difficult
420 */
421 switch (opcode_idx >> 1) { // "OpCode" in ARM docs
422#if 0
423 case 0x0: // AND - Rd:= Op1 AND Op2
424 opcode = 0xe << 21; // BIC
425 operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
426 break;
427 case 0x2: // SUB - Rd:= Op1 - Op2
428 opcode = 0x4 << 21; // ADD
429 operands |= (-ops[2].e.v) & 0xFF;
430 break;
431 case 0x4: // ADD - Rd:= Op1 + Op2
432 opcode = 0x2 << 21; // SUB
433 operands |= (-ops[2].e.v) & 0xFF;
434 break;
435 case 0x5: // ADC - Rd:= Op1 + Op2 + C
436 opcode = 0x6 << 21; // SBC
437 operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
438 break;
439 case 0x6: // SBC - Rd:= Op1 - Op2 + C
440 opcode = 0x5 << 21; // ADC
441 operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
442 break;
443#endif
444 case 0xa: // CMP - CC on: Op1 - Op2
445 opcode = 0xb << 21; // CMN
446 operands |= (-ops[2].e.v) & 0xFF;
447 break;
448 case 0xb: // CMN - CC on: Op1 + Op2
449 opcode = 0xa << 21; // CMP
450 operands |= (-ops[2].e.v) & 0xFF;
451 break;
452 // moveq r1, r3: 0x01a01003; mov Rd, Op2
453 case 0xd: // MOV - Rd:= Op2
454 opcode = 0xf << 21; // MVN
455 operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
456 break;
457#if 0
458 case 0xe: // BIC - Rd:= Op1 AND NOT Op2
459 opcode = 0x0 << 21; // AND
460 operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
461 break;
462#endif
463 case 0xf: // MVN - Rd:= NOT Op2
464 opcode = 0xd << 21; // MOV
465 operands |= (ops[2].e.v ^ 0xFF) & 0xFF;
466 break;
467 default:
468 tcc_error("cannot use '%s' with a negative immediate value", get_tok_str(token, NULL));
469 }
470 break;
471 default:
472 expect("(second source operand) register or immediate value");
473 }
474
475 /* S=0 and S=1 entries alternate one after another, in that order */
476 opcode |= (opcode_idx & 1) ? ENCODE_SET_CONDITION_CODES : 0;
477 asm_emit_opcode(token, opcode | operands);
478 }
479}
480
350static void asm_multiplication_opcode(TCCState *s1, int token)481static void asm_multiplication_opcode(TCCState *s1, int token)
351{482{
352 Operand ops[4];483 Operand ops[4];
@@ -669,6 +800,40 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 316 unmodified lines
669 case TOK_ASM_strbeq:800 case TOK_ASM_strbeq:
670 return asm_single_data_transfer_opcode(s1, token);801 return asm_single_data_transfer_opcode(s1, token);
671 802
803 case TOK_ASM_andeq:
804 case TOK_ASM_eoreq:
805 case TOK_ASM_subeq:
806 case TOK_ASM_rsbeq:
807 case TOK_ASM_addeq:
808 case TOK_ASM_adceq:
809 case TOK_ASM_sbceq:
810 case TOK_ASM_rsceq:
811 case TOK_ASM_tsteq:
812 case TOK_ASM_teqeq:
813 case TOK_ASM_cmpeq:
814 case TOK_ASM_cmneq:
815 case TOK_ASM_orreq:
816 case TOK_ASM_moveq:
817 case TOK_ASM_biceq:
818 case TOK_ASM_mvneq:
819 case TOK_ASM_andseq:
820 case TOK_ASM_eorseq:
821 case TOK_ASM_subseq:
822 case TOK_ASM_rsbseq:
823 case TOK_ASM_addseq:
824 case TOK_ASM_adcseq:
825 case TOK_ASM_sbcseq:
826 case TOK_ASM_rscseq:
827// case TOK_ASM_tstseq:
828// case TOK_ASM_teqseq:
829// case TOK_ASM_cmpseq:
830// case TOK_ASM_cmnseq:
831 case TOK_ASM_orrseq:
832 case TOK_ASM_movseq:
833 case TOK_ASM_bicseq:
834 case TOK_ASM_mvnseq:
835 return asm_data_processing_opcode(s1, token);
836
672 case TOK_ASM_muleq:837 case TOK_ASM_muleq:
673 case TOK_ASM_mulseq:838 case TOK_ASM_mulseq:
674 case TOK_ASM_mlaeq:839 case TOK_ASM_mlaeq:
arm-tok.h+35−0
@@ -103,3 +103,38 @@ · 102 unmodified lines
103 103
104 DEF_ASM_CONDED(push)104 DEF_ASM_CONDED(push)
105 DEF_ASM_CONDED(pop)105 DEF_ASM_CONDED(pop)
106
107 /* data processing instructions; order is important */
108
109 DEF_ASM_CONDED(and)
110 DEF_ASM_CONDED(ands)
111 DEF_ASM_CONDED(eor)
112 DEF_ASM_CONDED(eors)
113 DEF_ASM_CONDED(sub)
114 DEF_ASM_CONDED(subs)
115 DEF_ASM_CONDED(rsb)
116 DEF_ASM_CONDED(rsbs)
117 DEF_ASM_CONDED(add)
118 DEF_ASM_CONDED(adds)
119 DEF_ASM_CONDED(adc)
120 DEF_ASM_CONDED(adcs)
121 DEF_ASM_CONDED(sbc)
122 DEF_ASM_CONDED(sbcs)
123 DEF_ASM_CONDED(rsc)
124 DEF_ASM_CONDED(rscs)
125 DEF_ASM_CONDED(tst)
126 DEF_ASM_CONDED(tsts) // necessary here--but not useful to the user
127 DEF_ASM_CONDED(teq)
128 DEF_ASM_CONDED(teqs) // necessary here--but not useful to the user
129 DEF_ASM_CONDED(cmp)
130 DEF_ASM_CONDED(cmps) // necessary here--but not useful to the user
131 DEF_ASM_CONDED(cmn)
132 DEF_ASM_CONDED(cmns) // necessary here--but not useful to the user
133 DEF_ASM_CONDED(orr)
134 DEF_ASM_CONDED(orrs)
135 DEF_ASM_CONDED(mov)
136 DEF_ASM_CONDED(movs)
137 DEF_ASM_CONDED(bic)
138 DEF_ASM_CONDED(bics)
139 DEF_ASM_CONDED(mvn)
140 DEF_ASM_CONDED(mvns)

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