| @@ -413,18 +413,55 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 412 unmodified lines |
| 413 | 413 | { |
| 414 | 414 | Operand ops[3]; |
| 415 | 415 | int nb_ops; |
| 416 | + Operand shift = {}; |
| 417 | + int nb_shift = 0; |
| 418 | + uint32_t operands = 0; |
| 416 | 419 | |
| 417 | 420 | /* 16 entries per instruction for the different condition codes */ |
| 418 | 421 | uint32_t opcode_idx = (ARM_INSTRUCTION_GROUP(token) - TOK_ASM_andeq) >> 4; |
| 419 | 422 | |
| 420 | | − for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) { |
| 423 | + for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ) { |
| 424 | + if (tok == TOK_ASM_asl || tok == TOK_ASM_lsl || tok == TOK_ASM_lsr || tok == TOK_ASM_asr || tok == TOK_ASM_ror || tok == TOK_ASM_rrx) |
| 425 | + break; |
| 421 | 426 | parse_operand(s1, &ops[nb_ops]); |
| 422 | | − if (tok != ',') { |
| 423 | | − ++nb_ops; |
| 427 | + ++nb_ops; |
| 428 | + if (tok != ',') |
| 424 | 429 | break; |
| 425 | | − } |
| 426 | 430 | next(); // skip ',' |
| 427 | 431 | } |
| 432 | + if (tok == ',') |
| 433 | + next(); |
| 434 | + switch (tok) { |
| 435 | + case TOK_ASM_asl: |
| 436 | + case TOK_ASM_lsl: |
| 437 | + case TOK_ASM_asr: |
| 438 | + case TOK_ASM_lsr: |
| 439 | + case TOK_ASM_ror: |
| 440 | + switch (tok) { |
| 441 | + case TOK_ASM_asl: |
| 442 | + /* fallthrough */ |
| 443 | + case TOK_ASM_lsl: |
| 444 | + operands |= ENCODE_BARREL_SHIFTER_MODE_LSL; |
| 445 | + break; |
| 446 | + case TOK_ASM_asr: |
| 447 | + operands |= ENCODE_BARREL_SHIFTER_MODE_ASR; |
| 448 | + break; |
| 449 | + case TOK_ASM_lsr: |
| 450 | + operands |= ENCODE_BARREL_SHIFTER_MODE_LSR; |
| 451 | + break; |
| 452 | + case TOK_ASM_ror: |
| 453 | + operands |= ENCODE_BARREL_SHIFTER_MODE_ROR; |
| 454 | + break; |
| 455 | + } |
| 456 | + next(); |
| 457 | + parse_operand(s1, &shift); |
| 458 | + nb_shift = 1; |
| 459 | + break; |
| 460 | + case TOK_ASM_rrx: |
| 461 | + next(); |
| 462 | + operands |= ENCODE_BARREL_SHIFTER_MODE_ROR; |
| 463 | + break; |
| 464 | + } |
| 428 | 465 | if (nb_ops < 2) |
| 429 | 466 | expect("at least two operands"); |
| 430 | 467 | else if (nb_ops == 2) { |
| @@ -437,7 +474,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 6 unmodified lines |
| 437 | 474 | return; |
| 438 | 475 | } else { |
| 439 | 476 | uint32_t opcode = 0; |
| 440 | | − uint32_t operands = 0; |
| 441 | 477 | |
| 442 | 478 | // data processing (general case): |
| 443 | 479 | // operands: |
| @@ -461,16 +497,13 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 17 unmodified lines |
| 461 | 497 | operands |= ENCODE_RN(ops[1].reg); |
| 462 | 498 | switch (ops[2].type) { |
| 463 | 499 | case OP_REG32: |
| 464 | | − // TODO: Parse and encode shift. |
| 465 | 500 | operands |= ops[2].reg; |
| 466 | 501 | break; |
| 467 | 502 | case OP_IM8: |
| 468 | | − // TODO: Parse and encode rotation. |
| 469 | 503 | operands |= ENCODE_IMMEDIATE_FLAG; |
| 470 | 504 | operands |= ops[2].e.v; |
| 471 | 505 | break; |
| 472 | 506 | case OP_IM8N: // immediate negative value |
| 473 | | − // TODO: Parse and encode rotation. |
| 474 | 507 | operands |= ENCODE_IMMEDIATE_FLAG; |
| 475 | 508 | /* Instruction swapping: |
| 476 | 509 | 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult |
| @@ -534,6 +567,13 @@ static void asm_data_processing_opcode(TCCState *s1, int token) · 57 unmodified lines |
| 534 | 567 | expect("(second source operand) register or immediate value"); |
| 535 | 568 | } |
| 536 | 569 | |
| 570 | + if (nb_shift) { |
| 571 | + if (operands & ENCODE_IMMEDIATE_FLAG) |
| 572 | + tcc_error("immediate rotation not implemented"); |
| 573 | + else |
| 574 | + operands |= asm_encode_shift(&shift); |
| 575 | + } |
| 576 | + |
| 537 | 577 | /* S=0 and S=1 entries alternate one after another, in that order */ |
| 538 | 578 | opcode |= (opcode_idx & 1) ? ENCODE_SET_CONDITION_CODES : 0; |
| 539 | 579 | asm_emit_opcode(token, opcode | operands); |