diff mbox series

[v37,10/17] target/avr: Add instruction disassembly function

Message ID 20191127175257.23480-11-mrolnik@gmail.com (mailing list archive)
State New, archived
Headers show
Series QEMU AVR 8 bit cores | expand

Commit Message

Michael Rolnik Nov. 27, 2019, 5:52 p.m. UTC
Provide function disassembles executed instruction when `-d in_asm` is
provided

Example:
`./avr-softmmu/qemu-system-avr -bios free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf -d in_asm` will produce something like the following

```
    ...
    IN:
    0x0000014a:  CALL      0x3808

    IN: main
    0x00003808:  CALL      0x4b4

    IN: vParTestInitialise
    0x000004b4:  LDI       r24, 255
    0x000004b6:  STS       r24, 0
    0x000004b8:  MULS      r16, r20
    0x000004ba:  OUT       $1, r24
    0x000004bc:  LDS       r24, 0
    0x000004be:  MULS      r16, r20
    0x000004c0:  OUT       $2, r24
    0x000004c2:  RET
    ...
```

Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 target/avr/cpu.h       |   1 +
 target/avr/cpu.c       |   2 +-
 target/avr/disas.c     | 228 +++++++++++++++++++++++++++++++++++++++++
 target/avr/translate.c |  11 ++
 4 files changed, 241 insertions(+), 1 deletion(-)
 create mode 100644 target/avr/disas.c

Comments

Aleksandar Markovic Dec. 2, 2019, 12:28 a.m. UTC | #1
On Wednesday, November 27, 2019, Michael Rolnik <mrolnik@gmail.com> wrote:

> Provide function disassembles executed instruction when `-d in_asm` is
> provided
>
> Example:
> `./avr-softmmu/qemu-system-avr -bios free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf
> -d in_asm` will produce something like the following
>
> ```
>     ...
>     IN:
>     0x0000014a:  CALL      0x3808
>
>     IN: main
>     0x00003808:  CALL      0x4b4
>
>     IN: vParTestInitialise
>     0x000004b4:  LDI       r24, 255
>     0x000004b6:  STS       r24, 0
>     0x000004b8:  MULS      r16, r20
>     0x000004ba:  OUT       $1, r24
>     0x000004bc:  LDS       r24, 0
>     0x000004be:  MULS      r16, r20
>     0x000004c0:  OUT       $2, r24
>     0x000004c2:  RET
>     ...
> ```
>
> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
>  target/avr/cpu.h       |   1 +
>  target/avr/cpu.c       |   2 +-
>  target/avr/disas.c     | 228 +++++++++++++++++++++++++++++++++++++++++
>  target/avr/translate.c |  11 ++
>  4 files changed, 241 insertions(+), 1 deletion(-)
>  create mode 100644 target/avr/disas.c
>
> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
> index 9ea5260165..a3e615a1eb 100644
> --- a/target/avr/cpu.h
> +++ b/target/avr/cpu.h
> @@ -157,6 +157,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu, int
> int_req);
>  hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
>  int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
>  int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
> +int avr_print_insn(bfd_vma addr, disassemble_info *info);
>
>  static inline int avr_feature(CPUAVRState *env, int feature)
>  {
> diff --git a/target/avr/cpu.c b/target/avr/cpu.c
> index dae56d7845..52ec21dd16 100644
> --- a/target/avr/cpu.c
> +++ b/target/avr/cpu.c
> @@ -83,7 +83,7 @@ static void avr_cpu_reset(CPUState *cs)
>  static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
>  {
>      info->mach = bfd_arch_avr;
> -    info->print_insn = NULL;
> +    info->print_insn = avr_print_insn;
>  }
>
>  static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
> diff --git a/target/avr/disas.c b/target/avr/disas.c
> new file mode 100644
> index 0000000000..a51ade7c2a
> --- /dev/null
> +++ b/target/avr/disas.c
> @@ -0,0 +1,228 @@
> +/*
> + * AVR disassembler
> + *
> + * Copyright (c) 2018 Richard Henderson <rth@twiddle.net>


Just a detail: since this file is created in 2019, the copyright year
should be 2019 too.

+ * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "disas/dis-asm.h"
> +#include "qemu/bitops.h"
> +#include "cpu.h"
> +
> +typedef struct {
> +    disassemble_info *info;
> +    uint16_t next_word;
> +    bool next_word_used;
> +} DisasContext;
> +
> +static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
> +{
> +    return 16 + (indx % 16);
> +}
> +
> +static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
> +{
> +    return 16 + (indx % 8);
> +}
> +static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
> +{
> +    return 24 + (indx % 4) * 2;
> +}
> +static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
> +{
> +    return (indx % 16) * 2;
> +}
> +
> +static uint16_t next_word(DisasContext *ctx)
> +{
> +    ctx->next_word_used = true;
> +    return ctx->next_word;
> +}
> +
> +static int append_16(DisasContext *ctx, int x)
> +{
> +    return x << 16 | next_word(ctx);
> +}
> +
> +
> +/* Include the auto-generated decoder.  */
> +static bool decode_insn(DisasContext *ctx, uint16_t insn);
> +#include "decode_insn.inc.c"
> +
> +#define output(mnemonic, format, ...) \
> +    (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
> +                        mnemonic, ##__VA_ARGS__))
> +
> +int avr_print_insn(bfd_vma addr, disassemble_info *info)
> +{
> +    DisasContext ctx;
> +    DisasContext *pctx = &ctx;
> +    bfd_byte buffer[4];
> +    uint16_t insn;
> +    int status;
> +
> +    ctx.info = info;
> +
> +    status = info->read_memory_func(addr, buffer, 4, info);
> +    if (status != 0) {
> +        info->memory_error_func(status, addr, info);
> +        return -1;
> +    }
> +    insn = bfd_getl16(buffer);
> +    ctx.next_word = bfd_getl16(buffer + 2);
> +    ctx.next_word_used = false;
> +
> +    if (!decode_insn(&ctx, insn)) {
> +        output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
> +    }
> +
> +    return ctx.next_word_used ? 4 : 2;
> +}
> +
> +
> +#define INSN(opcode, format, ...)                                       \
> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)        \
> +{                                                                       \
> +    output(#opcode, format, ##__VA_ARGS__);                             \
> +    return true;                                                        \
> +}
> +
> +#define INSN_MNEMONIC(opcode, mnemonic, format, ...)                    \
> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)        \
> +{                                                                       \
> +    output(mnemonic, format, ##__VA_ARGS__);                            \
> +    return true;                                                        \
> +}
> +
> +/*
> + *   C       Z       N       V       S       H       T       I
> + *   0       1       2       3       4       5       6       7
> + */
> +static const char *brbc[] = {
> +    "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
> +};
> +
> +static const char *brbs[] = {
> +    "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
> +};
> +
> +static const char *bset[] = {
> +    "SEC",  "SEZ",  "SEN",  "SEZ",  "SES",  "SEH",  "SET",  "SEI"
> +};
> +
> +static const char *bclr[] = {
> +    "CLC",  "CLZ",  "CLN",  "CLZ",  "CLS",  "CLH",  "CLT",  "CLI"
> +};
> +
> +INSN(ADC,    "r%d, r%d", a->rd, a->rr)
> +INSN(ADD,    "r%d, r%d", a->rd, a->rr)
> +INSN(ADIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
> +INSN(AND,    "r%d, r%d", a->rd, a->rr)
> +INSN(ANDI,   "r%d, %d", a->rd, a->imm)
> +INSN(ASR,    "r%d", a->rd)
> +INSN_MNEMONIC(BCLR,  bclr[a->bit], "")
> +INSN(BLD,    "r%d, %d", a->rd, a->bit)
> +INSN_MNEMONIC(BRBC,  brbc[a->bit], ".%+d", a->imm * 2)
> +INSN_MNEMONIC(BRBS,  brbs[a->bit], ".%+d", a->imm * 2)
> +INSN(BREAK,  "")
> +INSN_MNEMONIC(BSET,  bset[a->bit], "")
> +INSN(BST,    "r%d, %d", a->rd, a->bit)
> +INSN(CALL,   "0x%x", a->imm * 2)
> +INSN(CBI,    "%d, %d", a->reg, a->bit)
> +INSN(COM,    "r%d", a->rd)
> +INSN(CP,     "r%d, r%d", a->rd, a->rr)
> +INSN(CPC,    "r%d, r%d", a->rd, a->rr)
> +INSN(CPI,    "r%d, %d", a->rd, a->imm)
> +INSN(CPSE,   "r%d, r%d", a->rd, a->rr)
> +INSN(DEC,    "r%d", a->rd)
> +INSN(DES,    "%d", a->imm)
> +INSN(EICALL, "")
> +INSN(EIJMP,  "")
> +INSN(ELPM1,  "")
> +INSN(ELPM2,  "r%d, Z", a->rd)
> +INSN(ELPMX,  "r%d, Z+", a->rd)
> +INSN(EOR,    "r%d, r%d", a->rd, a->rr)
> +INSN(FMUL,   "r%d, r%d", a->rd, a->rr)
> +INSN(FMULS,  "r%d, r%d", a->rd, a->rr)
> +INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
> +INSN(ICALL,  "")
> +INSN(IJMP,   "")
> +INSN(IN,     "r%d, $%d", a->rd, a->imm)
> +INSN(INC,    "r%d", a->rd)
> +INSN(JMP,    "0x%x", a->imm * 2)
> +INSN(LAC,    "Z, r%d", a->rd)
> +INSN(LAS,    "Z, r%d", a->rd)
> +INSN(LAT,    "Z, r%d", a->rd)
> +INSN(LDDY,   "r%d, Y+%d", a->rd, a->imm)
> +INSN(LDDZ,   "r%d, Z+%d", a->rd, a->imm)
> +INSN(LDI,    "r%d, %d", a->rd, a->imm)
> +INSN(LDS,    "r%d, %d", a->rd, a->imm)
> +INSN(LDX1,   "r%d, X", a->rd)
> +INSN(LDX2,   "r%d, X+", a->rd)
> +INSN(LDX3,   "r%d, -X", a->rd)
> +INSN(LDY2,   "r%d, Y+", a->rd)
> +INSN(LDY3,   "r%d, -Y", a->rd)
> +INSN(LDZ2,   "r%d, Z+", a->rd)
> +INSN(LDZ3,   "r%d, -Z", a->rd)
> +INSN(LPM1,   "")
> +INSN(LPM2,   "r%d, Z", a->rd)
> +INSN(LPMX,   "r%d, Z+", a->rd)
> +INSN(LSR,    "r%d", a->rd)
> +INSN(MOV,    "r%d, r%d", a->rd, a->rr)
> +INSN(MOVW,   "r%d:r%d, r%d,r:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
> +INSN(MUL,    "r%d, r%d", a->rd, a->rr)
> +INSN(MULS,   "r%d, r%d", a->rd, a->rr)
> +INSN(MULSU,  "r%d, r%d", a->rd, a->rr)
> +INSN(NEG,    "r%d", a->rd)
> +INSN(NOP,    "")
> +INSN(OR,     "r%d, r%d", a->rd, a->rr)
> +INSN(ORI,    "r%d, %d", a->rd, a->imm)
> +INSN(OUT,    "$%d, r%d", a->imm, a->rd)
> +INSN(POP,    "r%d", a->rd)
> +INSN(PUSH,   "r%d", a->rd)
> +INSN(RCALL,  ".%+d", a->imm * 2)
> +INSN(RET,    "")
> +INSN(RETI,   "")
> +INSN(RJMP,   ".%+d", a->imm * 2)
> +INSN(ROR,    "r%d", a->rd)
> +INSN(SBC,    "r%d, r%d", a->rd, a->rr)
> +INSN(SBCI,   "r%d, %d", a->rd, a->imm)
> +INSN(SBI,    "$%d, %d", a->reg, a->bit)
> +INSN(SBIC,   "$%d, %d", a->reg, a->bit)
> +INSN(SBIS,   "$%d, %d", a->reg, a->bit)
> +INSN(SBIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
> +INSN(SBRC,   "r%d, %d", a->rr, a->bit)
> +INSN(SBRS,   "r%d, %d", a->rr, a->bit)
> +INSN(SLEEP,  "")
> +INSN(SPM,    "")
> +INSN(SPMX,   "Z+")
> +INSN(STDY,   "r%d, Y+%d", a->rd, a->imm)
> +INSN(STDZ,   "r%d, Z+%d", a->rd, a->imm)
> +INSN(STS,    "r%d, %d", a->rd, a->imm)
> +INSN(STX1,   "r%d, X", a->rr)
> +INSN(STX2,   "r%d, X+", a->rr)
> +INSN(STX3,   "r%d, -X", a->rr)
> +INSN(STY2,   "r%d, Y+", a->rd)
> +INSN(STY3,   "r%d, -Y", a->rd)
> +INSN(STZ2,   "r%d, Z+", a->rd)
> +INSN(STZ3,   "r%d, -Z", a->rd)
> +INSN(SUB,    "r%d, r%d", a->rd, a->rr)
> +INSN(SUBI,   "r%d, %d", a->rd, a->imm)
> +INSN(SWAP,   "r%d", a->rd)
> +INSN(WDR,    "")
> +INSN(XCH,    "Z, r%d", a->rd)
> +
> diff --git a/target/avr/translate.c b/target/avr/translate.c
> index 941db8e168..e562e68d88 100644
> --- a/target/avr/translate.c
> +++ b/target/avr/translate.c
> @@ -3032,6 +3032,17 @@ done_generating:
>
>      tb->size = (ctx.npc - pc_start) * 2;
>      tb->icount = num_insns;
> +
> +#ifdef DEBUG_DISAS
> +    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
> +        && qemu_log_in_addr_range(tb->pc)) {
> +        qemu_log_lock();
> +        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
> +        log_target_disas(cs, tb->pc, tb->size);
> +        qemu_log("\n");
> +        qemu_log_unlock();
> +    }
> +#endif
>  }
>
>  void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
> --
> 2.17.2 (Apple Git-113)
>
>
Michael Rolnik Dec. 2, 2019, 7:04 a.m. UTC | #2
Aleksandar.

If this code is going to be merge in 2019 I should modify al the
copyrights, right. or should I put 2020 in?

Regards,
Michael Rolnik

On Mon, Dec 2, 2019 at 2:28 AM Aleksandar Markovic <
aleksandar.m.mail@gmail.com> wrote:

>
>
> On Wednesday, November 27, 2019, Michael Rolnik <mrolnik@gmail.com> wrote:
>
>> Provide function disassembles executed instruction when `-d in_asm` is
>> provided
>>
>> Example:
>> `./avr-softmmu/qemu-system-avr -bios
>> free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf -d in_asm` will produce
>> something like the following
>>
>> ```
>>     ...
>>     IN:
>>     0x0000014a:  CALL      0x3808
>>
>>     IN: main
>>     0x00003808:  CALL      0x4b4
>>
>>     IN: vParTestInitialise
>>     0x000004b4:  LDI       r24, 255
>>     0x000004b6:  STS       r24, 0
>>     0x000004b8:  MULS      r16, r20
>>     0x000004ba:  OUT       $1, r24
>>     0x000004bc:  LDS       r24, 0
>>     0x000004be:  MULS      r16, r20
>>     0x000004c0:  OUT       $2, r24
>>     0x000004c2:  RET
>>     ...
>> ```
>>
>> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
>> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
>> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
>> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>> ---
>>  target/avr/cpu.h       |   1 +
>>  target/avr/cpu.c       |   2 +-
>>  target/avr/disas.c     | 228 +++++++++++++++++++++++++++++++++++++++++
>>  target/avr/translate.c |  11 ++
>>  4 files changed, 241 insertions(+), 1 deletion(-)
>>  create mode 100644 target/avr/disas.c
>>
>> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
>> index 9ea5260165..a3e615a1eb 100644
>> --- a/target/avr/cpu.h
>> +++ b/target/avr/cpu.h
>> @@ -157,6 +157,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu, int
>> int_req);
>>  hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
>>  int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
>>  int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
>> +int avr_print_insn(bfd_vma addr, disassemble_info *info);
>>
>>  static inline int avr_feature(CPUAVRState *env, int feature)
>>  {
>> diff --git a/target/avr/cpu.c b/target/avr/cpu.c
>> index dae56d7845..52ec21dd16 100644
>> --- a/target/avr/cpu.c
>> +++ b/target/avr/cpu.c
>> @@ -83,7 +83,7 @@ static void avr_cpu_reset(CPUState *cs)
>>  static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
>>  {
>>      info->mach = bfd_arch_avr;
>> -    info->print_insn = NULL;
>> +    info->print_insn = avr_print_insn;
>>  }
>>
>>  static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
>> diff --git a/target/avr/disas.c b/target/avr/disas.c
>> new file mode 100644
>> index 0000000000..a51ade7c2a
>> --- /dev/null
>> +++ b/target/avr/disas.c
>> @@ -0,0 +1,228 @@
>> +/*
>> + * AVR disassembler
>> + *
>> + * Copyright (c) 2018 Richard Henderson <rth@twiddle.net>
>
>
> Just a detail: since this file is created in 2019, the copyright year
> should be 2019 too.
>
> + * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com>
>> + *
>> + * This program is free software: you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "disas/dis-asm.h"
>> +#include "qemu/bitops.h"
>> +#include "cpu.h"
>> +
>> +typedef struct {
>> +    disassemble_info *info;
>> +    uint16_t next_word;
>> +    bool next_word_used;
>> +} DisasContext;
>> +
>> +static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
>> +{
>> +    return 16 + (indx % 16);
>> +}
>> +
>> +static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
>> +{
>> +    return 16 + (indx % 8);
>> +}
>> +static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
>> +{
>> +    return 24 + (indx % 4) * 2;
>> +}
>> +static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
>> +{
>> +    return (indx % 16) * 2;
>> +}
>> +
>> +static uint16_t next_word(DisasContext *ctx)
>> +{
>> +    ctx->next_word_used = true;
>> +    return ctx->next_word;
>> +}
>> +
>> +static int append_16(DisasContext *ctx, int x)
>> +{
>> +    return x << 16 | next_word(ctx);
>> +}
>> +
>> +
>> +/* Include the auto-generated decoder.  */
>> +static bool decode_insn(DisasContext *ctx, uint16_t insn);
>> +#include "decode_insn.inc.c"
>> +
>> +#define output(mnemonic, format, ...) \
>> +    (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
>> +                        mnemonic, ##__VA_ARGS__))
>> +
>> +int avr_print_insn(bfd_vma addr, disassemble_info *info)
>> +{
>> +    DisasContext ctx;
>> +    DisasContext *pctx = &ctx;
>> +    bfd_byte buffer[4];
>> +    uint16_t insn;
>> +    int status;
>> +
>> +    ctx.info = info;
>> +
>> +    status = info->read_memory_func(addr, buffer, 4, info);
>> +    if (status != 0) {
>> +        info->memory_error_func(status, addr, info);
>> +        return -1;
>> +    }
>> +    insn = bfd_getl16(buffer);
>> +    ctx.next_word = bfd_getl16(buffer + 2);
>> +    ctx.next_word_used = false;
>> +
>> +    if (!decode_insn(&ctx, insn)) {
>> +        output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
>> +    }
>> +
>> +    return ctx.next_word_used ? 4 : 2;
>> +}
>> +
>> +
>> +#define INSN(opcode, format, ...)                                       \
>> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)        \
>> +{                                                                       \
>> +    output(#opcode, format, ##__VA_ARGS__);                             \
>> +    return true;                                                        \
>> +}
>> +
>> +#define INSN_MNEMONIC(opcode, mnemonic, format, ...)                    \
>> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)        \
>> +{                                                                       \
>> +    output(mnemonic, format, ##__VA_ARGS__);                            \
>> +    return true;                                                        \
>> +}
>> +
>> +/*
>> + *   C       Z       N       V       S       H       T       I
>> + *   0       1       2       3       4       5       6       7
>> + */
>> +static const char *brbc[] = {
>> +    "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
>> +};
>> +
>> +static const char *brbs[] = {
>> +    "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
>> +};
>> +
>> +static const char *bset[] = {
>> +    "SEC",  "SEZ",  "SEN",  "SEZ",  "SES",  "SEH",  "SET",  "SEI"
>> +};
>> +
>> +static const char *bclr[] = {
>> +    "CLC",  "CLZ",  "CLN",  "CLZ",  "CLS",  "CLH",  "CLT",  "CLI"
>> +};
>> +
>> +INSN(ADC,    "r%d, r%d", a->rd, a->rr)
>> +INSN(ADD,    "r%d, r%d", a->rd, a->rr)
>> +INSN(ADIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
>> +INSN(AND,    "r%d, r%d", a->rd, a->rr)
>> +INSN(ANDI,   "r%d, %d", a->rd, a->imm)
>> +INSN(ASR,    "r%d", a->rd)
>> +INSN_MNEMONIC(BCLR,  bclr[a->bit], "")
>> +INSN(BLD,    "r%d, %d", a->rd, a->bit)
>> +INSN_MNEMONIC(BRBC,  brbc[a->bit], ".%+d", a->imm * 2)
>> +INSN_MNEMONIC(BRBS,  brbs[a->bit], ".%+d", a->imm * 2)
>> +INSN(BREAK,  "")
>> +INSN_MNEMONIC(BSET,  bset[a->bit], "")
>> +INSN(BST,    "r%d, %d", a->rd, a->bit)
>> +INSN(CALL,   "0x%x", a->imm * 2)
>> +INSN(CBI,    "%d, %d", a->reg, a->bit)
>> +INSN(COM,    "r%d", a->rd)
>> +INSN(CP,     "r%d, r%d", a->rd, a->rr)
>> +INSN(CPC,    "r%d, r%d", a->rd, a->rr)
>> +INSN(CPI,    "r%d, %d", a->rd, a->imm)
>> +INSN(CPSE,   "r%d, r%d", a->rd, a->rr)
>> +INSN(DEC,    "r%d", a->rd)
>> +INSN(DES,    "%d", a->imm)
>> +INSN(EICALL, "")
>> +INSN(EIJMP,  "")
>> +INSN(ELPM1,  "")
>> +INSN(ELPM2,  "r%d, Z", a->rd)
>> +INSN(ELPMX,  "r%d, Z+", a->rd)
>> +INSN(EOR,    "r%d, r%d", a->rd, a->rr)
>> +INSN(FMUL,   "r%d, r%d", a->rd, a->rr)
>> +INSN(FMULS,  "r%d, r%d", a->rd, a->rr)
>> +INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
>> +INSN(ICALL,  "")
>> +INSN(IJMP,   "")
>> +INSN(IN,     "r%d, $%d", a->rd, a->imm)
>> +INSN(INC,    "r%d", a->rd)
>> +INSN(JMP,    "0x%x", a->imm * 2)
>> +INSN(LAC,    "Z, r%d", a->rd)
>> +INSN(LAS,    "Z, r%d", a->rd)
>> +INSN(LAT,    "Z, r%d", a->rd)
>> +INSN(LDDY,   "r%d, Y+%d", a->rd, a->imm)
>> +INSN(LDDZ,   "r%d, Z+%d", a->rd, a->imm)
>> +INSN(LDI,    "r%d, %d", a->rd, a->imm)
>> +INSN(LDS,    "r%d, %d", a->rd, a->imm)
>> +INSN(LDX1,   "r%d, X", a->rd)
>> +INSN(LDX2,   "r%d, X+", a->rd)
>> +INSN(LDX3,   "r%d, -X", a->rd)
>> +INSN(LDY2,   "r%d, Y+", a->rd)
>> +INSN(LDY3,   "r%d, -Y", a->rd)
>> +INSN(LDZ2,   "r%d, Z+", a->rd)
>> +INSN(LDZ3,   "r%d, -Z", a->rd)
>> +INSN(LPM1,   "")
>> +INSN(LPM2,   "r%d, Z", a->rd)
>> +INSN(LPMX,   "r%d, Z+", a->rd)
>> +INSN(LSR,    "r%d", a->rd)
>> +INSN(MOV,    "r%d, r%d", a->rd, a->rr)
>> +INSN(MOVW,   "r%d:r%d, r%d,r:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
>> +INSN(MUL,    "r%d, r%d", a->rd, a->rr)
>> +INSN(MULS,   "r%d, r%d", a->rd, a->rr)
>> +INSN(MULSU,  "r%d, r%d", a->rd, a->rr)
>> +INSN(NEG,    "r%d", a->rd)
>> +INSN(NOP,    "")
>> +INSN(OR,     "r%d, r%d", a->rd, a->rr)
>> +INSN(ORI,    "r%d, %d", a->rd, a->imm)
>> +INSN(OUT,    "$%d, r%d", a->imm, a->rd)
>> +INSN(POP,    "r%d", a->rd)
>> +INSN(PUSH,   "r%d", a->rd)
>> +INSN(RCALL,  ".%+d", a->imm * 2)
>> +INSN(RET,    "")
>> +INSN(RETI,   "")
>> +INSN(RJMP,   ".%+d", a->imm * 2)
>> +INSN(ROR,    "r%d", a->rd)
>> +INSN(SBC,    "r%d, r%d", a->rd, a->rr)
>> +INSN(SBCI,   "r%d, %d", a->rd, a->imm)
>> +INSN(SBI,    "$%d, %d", a->reg, a->bit)
>> +INSN(SBIC,   "$%d, %d", a->reg, a->bit)
>> +INSN(SBIS,   "$%d, %d", a->reg, a->bit)
>> +INSN(SBIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
>> +INSN(SBRC,   "r%d, %d", a->rr, a->bit)
>> +INSN(SBRS,   "r%d, %d", a->rr, a->bit)
>> +INSN(SLEEP,  "")
>> +INSN(SPM,    "")
>> +INSN(SPMX,   "Z+")
>> +INSN(STDY,   "r%d, Y+%d", a->rd, a->imm)
>> +INSN(STDZ,   "r%d, Z+%d", a->rd, a->imm)
>> +INSN(STS,    "r%d, %d", a->rd, a->imm)
>> +INSN(STX1,   "r%d, X", a->rr)
>> +INSN(STX2,   "r%d, X+", a->rr)
>> +INSN(STX3,   "r%d, -X", a->rr)
>> +INSN(STY2,   "r%d, Y+", a->rd)
>> +INSN(STY3,   "r%d, -Y", a->rd)
>> +INSN(STZ2,   "r%d, Z+", a->rd)
>> +INSN(STZ3,   "r%d, -Z", a->rd)
>> +INSN(SUB,    "r%d, r%d", a->rd, a->rr)
>> +INSN(SUBI,   "r%d, %d", a->rd, a->imm)
>> +INSN(SWAP,   "r%d", a->rd)
>> +INSN(WDR,    "")
>> +INSN(XCH,    "Z, r%d", a->rd)
>> +
>> diff --git a/target/avr/translate.c b/target/avr/translate.c
>> index 941db8e168..e562e68d88 100644
>> --- a/target/avr/translate.c
>> +++ b/target/avr/translate.c
>> @@ -3032,6 +3032,17 @@ done_generating:
>>
>>      tb->size = (ctx.npc - pc_start) * 2;
>>      tb->icount = num_insns;
>> +
>> +#ifdef DEBUG_DISAS
>> +    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
>> +        && qemu_log_in_addr_range(tb->pc)) {
>> +        qemu_log_lock();
>> +        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
>> +        log_target_disas(cs, tb->pc, tb->size);
>> +        qemu_log("\n");
>> +        qemu_log_unlock();
>> +    }
>> +#endif
>>  }
>>
>>  void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
>> --
>> 2.17.2 (Apple Git-113)
>>
>>
Aleksandar Markovic Dec. 2, 2019, 10:12 a.m. UTC | #3
On Monday, December 2, 2019, Michael Rolnik <mrolnik@gmail.com> wrote:

> Aleksandar.
>
> If this code is going to be merge in 2019 I should modify al the
> copyrights, right. or should I put 2020 in?
>
>
I don't have a better answer other than:

:))))))



> Regards,
> Michael Rolnik
>
> On Mon, Dec 2, 2019 at 2:28 AM Aleksandar Markovic <
> aleksandar.m.mail@gmail.com> wrote:
>
>>
>>
>> On Wednesday, November 27, 2019, Michael Rolnik <mrolnik@gmail.com>
>> wrote:
>>
>>> Provide function disassembles executed instruction when `-d in_asm` is
>>> provided
>>>
>>> Example:
>>> `./avr-softmmu/qemu-system-avr -bios free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf
>>> -d in_asm` will produce something like the following
>>>
>>> ```
>>>     ...
>>>     IN:
>>>     0x0000014a:  CALL      0x3808
>>>
>>>     IN: main
>>>     0x00003808:  CALL      0x4b4
>>>
>>>     IN: vParTestInitialise
>>>     0x000004b4:  LDI       r24, 255
>>>     0x000004b6:  STS       r24, 0
>>>     0x000004b8:  MULS      r16, r20
>>>     0x000004ba:  OUT       $1, r24
>>>     0x000004bc:  LDS       r24, 0
>>>     0x000004be:  MULS      r16, r20
>>>     0x000004c0:  OUT       $2, r24
>>>     0x000004c2:  RET
>>>     ...
>>> ```
>>>
>>> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
>>> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
>>> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
>>> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>>> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>>> ---
>>>  target/avr/cpu.h       |   1 +
>>>  target/avr/cpu.c       |   2 +-
>>>  target/avr/disas.c     | 228 +++++++++++++++++++++++++++++++++++++++++
>>>  target/avr/translate.c |  11 ++
>>>  4 files changed, 241 insertions(+), 1 deletion(-)
>>>  create mode 100644 target/avr/disas.c
>>>
>>> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
>>> index 9ea5260165..a3e615a1eb 100644
>>> --- a/target/avr/cpu.h
>>> +++ b/target/avr/cpu.h
>>> @@ -157,6 +157,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu, int
>>> int_req);
>>>  hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
>>>  int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
>>>  int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
>>> +int avr_print_insn(bfd_vma addr, disassemble_info *info);
>>>
>>>  static inline int avr_feature(CPUAVRState *env, int feature)
>>>  {
>>> diff --git a/target/avr/cpu.c b/target/avr/cpu.c
>>> index dae56d7845..52ec21dd16 100644
>>> --- a/target/avr/cpu.c
>>> +++ b/target/avr/cpu.c
>>> @@ -83,7 +83,7 @@ static void avr_cpu_reset(CPUState *cs)
>>>  static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info
>>> *info)
>>>  {
>>>      info->mach = bfd_arch_avr;
>>> -    info->print_insn = NULL;
>>> +    info->print_insn = avr_print_insn;
>>>  }
>>>
>>>  static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
>>> diff --git a/target/avr/disas.c b/target/avr/disas.c
>>> new file mode 100644
>>> index 0000000000..a51ade7c2a
>>> --- /dev/null
>>> +++ b/target/avr/disas.c
>>> @@ -0,0 +1,228 @@
>>> +/*
>>> + * AVR disassembler
>>> + *
>>> + * Copyright (c) 2018 Richard Henderson <rth@twiddle.net>
>>
>>
>> Just a detail: since this file is created in 2019, the copyright year
>> should be 2019 too.
>>
>> + * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com>
>>> + *
>>> + * This program is free software: you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation, either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>
>>> .
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "disas/dis-asm.h"
>>> +#include "qemu/bitops.h"
>>> +#include "cpu.h"
>>> +
>>> +typedef struct {
>>> +    disassemble_info *info;
>>> +    uint16_t next_word;
>>> +    bool next_word_used;
>>> +} DisasContext;
>>> +
>>> +static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
>>> +{
>>> +    return 16 + (indx % 16);
>>> +}
>>> +
>>> +static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
>>> +{
>>> +    return 16 + (indx % 8);
>>> +}
>>> +static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
>>> +{
>>> +    return 24 + (indx % 4) * 2;
>>> +}
>>> +static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
>>> +{
>>> +    return (indx % 16) * 2;
>>> +}
>>> +
>>> +static uint16_t next_word(DisasContext *ctx)
>>> +{
>>> +    ctx->next_word_used = true;
>>> +    return ctx->next_word;
>>> +}
>>> +
>>> +static int append_16(DisasContext *ctx, int x)
>>> +{
>>> +    return x << 16 | next_word(ctx);
>>> +}
>>> +
>>> +
>>> +/* Include the auto-generated decoder.  */
>>> +static bool decode_insn(DisasContext *ctx, uint16_t insn);
>>> +#include "decode_insn.inc.c"
>>> +
>>> +#define output(mnemonic, format, ...) \
>>> +    (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
>>> +                        mnemonic, ##__VA_ARGS__))
>>> +
>>> +int avr_print_insn(bfd_vma addr, disassemble_info *info)
>>> +{
>>> +    DisasContext ctx;
>>> +    DisasContext *pctx = &ctx;
>>> +    bfd_byte buffer[4];
>>> +    uint16_t insn;
>>> +    int status;
>>> +
>>> +    ctx.info = info;
>>> +
>>> +    status = info->read_memory_func(addr, buffer, 4, info);
>>> +    if (status != 0) {
>>> +        info->memory_error_func(status, addr, info);
>>> +        return -1;
>>> +    }
>>> +    insn = bfd_getl16(buffer);
>>> +    ctx.next_word = bfd_getl16(buffer + 2);
>>> +    ctx.next_word_used = false;
>>> +
>>> +    if (!decode_insn(&ctx, insn)) {
>>> +        output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
>>> +    }
>>> +
>>> +    return ctx.next_word_used ? 4 : 2;
>>> +}
>>> +
>>> +
>>> +#define INSN(opcode, format, ...)
>>>  \
>>> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)
>>> \
>>> +{
>>>  \
>>> +    output(#opcode, format, ##__VA_ARGS__);
>>>  \
>>> +    return true;
>>> \
>>> +}
>>> +
>>> +#define INSN_MNEMONIC(opcode, mnemonic, format, ...)
>>> \
>>> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)
>>> \
>>> +{
>>>  \
>>> +    output(mnemonic, format, ##__VA_ARGS__);
>>> \
>>> +    return true;
>>> \
>>> +}
>>> +
>>> +/*
>>> + *   C       Z       N       V       S       H       T       I
>>> + *   0       1       2       3       4       5       6       7
>>> + */
>>> +static const char *brbc[] = {
>>> +    "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
>>> +};
>>> +
>>> +static const char *brbs[] = {
>>> +    "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
>>> +};
>>> +
>>> +static const char *bset[] = {
>>> +    "SEC",  "SEZ",  "SEN",  "SEZ",  "SES",  "SEH",  "SET",  "SEI"
>>> +};
>>> +
>>> +static const char *bclr[] = {
>>> +    "CLC",  "CLZ",  "CLN",  "CLZ",  "CLS",  "CLH",  "CLT",  "CLI"
>>> +};
>>> +
>>> +INSN(ADC,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(ADD,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(ADIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
>>> +INSN(AND,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(ANDI,   "r%d, %d", a->rd, a->imm)
>>> +INSN(ASR,    "r%d", a->rd)
>>> +INSN_MNEMONIC(BCLR,  bclr[a->bit], "")
>>> +INSN(BLD,    "r%d, %d", a->rd, a->bit)
>>> +INSN_MNEMONIC(BRBC,  brbc[a->bit], ".%+d", a->imm * 2)
>>> +INSN_MNEMONIC(BRBS,  brbs[a->bit], ".%+d", a->imm * 2)
>>> +INSN(BREAK,  "")
>>> +INSN_MNEMONIC(BSET,  bset[a->bit], "")
>>> +INSN(BST,    "r%d, %d", a->rd, a->bit)
>>> +INSN(CALL,   "0x%x", a->imm * 2)
>>> +INSN(CBI,    "%d, %d", a->reg, a->bit)
>>> +INSN(COM,    "r%d", a->rd)
>>> +INSN(CP,     "r%d, r%d", a->rd, a->rr)
>>> +INSN(CPC,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(CPI,    "r%d, %d", a->rd, a->imm)
>>> +INSN(CPSE,   "r%d, r%d", a->rd, a->rr)
>>> +INSN(DEC,    "r%d", a->rd)
>>> +INSN(DES,    "%d", a->imm)
>>> +INSN(EICALL, "")
>>> +INSN(EIJMP,  "")
>>> +INSN(ELPM1,  "")
>>> +INSN(ELPM2,  "r%d, Z", a->rd)
>>> +INSN(ELPMX,  "r%d, Z+", a->rd)
>>> +INSN(EOR,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(FMUL,   "r%d, r%d", a->rd, a->rr)
>>> +INSN(FMULS,  "r%d, r%d", a->rd, a->rr)
>>> +INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
>>> +INSN(ICALL,  "")
>>> +INSN(IJMP,   "")
>>> +INSN(IN,     "r%d, $%d", a->rd, a->imm)
>>> +INSN(INC,    "r%d", a->rd)
>>> +INSN(JMP,    "0x%x", a->imm * 2)
>>> +INSN(LAC,    "Z, r%d", a->rd)
>>> +INSN(LAS,    "Z, r%d", a->rd)
>>> +INSN(LAT,    "Z, r%d", a->rd)
>>> +INSN(LDDY,   "r%d, Y+%d", a->rd, a->imm)
>>> +INSN(LDDZ,   "r%d, Z+%d", a->rd, a->imm)
>>> +INSN(LDI,    "r%d, %d", a->rd, a->imm)
>>> +INSN(LDS,    "r%d, %d", a->rd, a->imm)
>>> +INSN(LDX1,   "r%d, X", a->rd)
>>> +INSN(LDX2,   "r%d, X+", a->rd)
>>> +INSN(LDX3,   "r%d, -X", a->rd)
>>> +INSN(LDY2,   "r%d, Y+", a->rd)
>>> +INSN(LDY3,   "r%d, -Y", a->rd)
>>> +INSN(LDZ2,   "r%d, Z+", a->rd)
>>> +INSN(LDZ3,   "r%d, -Z", a->rd)
>>> +INSN(LPM1,   "")
>>> +INSN(LPM2,   "r%d, Z", a->rd)
>>> +INSN(LPMX,   "r%d, Z+", a->rd)
>>> +INSN(LSR,    "r%d", a->rd)
>>> +INSN(MOV,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(MOVW,   "r%d:r%d, r%d,r:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
>>> +INSN(MUL,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(MULS,   "r%d, r%d", a->rd, a->rr)
>>> +INSN(MULSU,  "r%d, r%d", a->rd, a->rr)
>>> +INSN(NEG,    "r%d", a->rd)
>>> +INSN(NOP,    "")
>>> +INSN(OR,     "r%d, r%d", a->rd, a->rr)
>>> +INSN(ORI,    "r%d, %d", a->rd, a->imm)
>>> +INSN(OUT,    "$%d, r%d", a->imm, a->rd)
>>> +INSN(POP,    "r%d", a->rd)
>>> +INSN(PUSH,   "r%d", a->rd)
>>> +INSN(RCALL,  ".%+d", a->imm * 2)
>>> +INSN(RET,    "")
>>> +INSN(RETI,   "")
>>> +INSN(RJMP,   ".%+d", a->imm * 2)
>>> +INSN(ROR,    "r%d", a->rd)
>>> +INSN(SBC,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(SBCI,   "r%d, %d", a->rd, a->imm)
>>> +INSN(SBI,    "$%d, %d", a->reg, a->bit)
>>> +INSN(SBIC,   "$%d, %d", a->reg, a->bit)
>>> +INSN(SBIS,   "$%d, %d", a->reg, a->bit)
>>> +INSN(SBIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
>>> +INSN(SBRC,   "r%d, %d", a->rr, a->bit)
>>> +INSN(SBRS,   "r%d, %d", a->rr, a->bit)
>>> +INSN(SLEEP,  "")
>>> +INSN(SPM,    "")
>>> +INSN(SPMX,   "Z+")
>>> +INSN(STDY,   "r%d, Y+%d", a->rd, a->imm)
>>> +INSN(STDZ,   "r%d, Z+%d", a->rd, a->imm)
>>> +INSN(STS,    "r%d, %d", a->rd, a->imm)
>>> +INSN(STX1,   "r%d, X", a->rr)
>>> +INSN(STX2,   "r%d, X+", a->rr)
>>> +INSN(STX3,   "r%d, -X", a->rr)
>>> +INSN(STY2,   "r%d, Y+", a->rd)
>>> +INSN(STY3,   "r%d, -Y", a->rd)
>>> +INSN(STZ2,   "r%d, Z+", a->rd)
>>> +INSN(STZ3,   "r%d, -Z", a->rd)
>>> +INSN(SUB,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(SUBI,   "r%d, %d", a->rd, a->imm)
>>> +INSN(SWAP,   "r%d", a->rd)
>>> +INSN(WDR,    "")
>>> +INSN(XCH,    "Z, r%d", a->rd)
>>> +
>>> diff --git a/target/avr/translate.c b/target/avr/translate.c
>>> index 941db8e168..e562e68d88 100644
>>> --- a/target/avr/translate.c
>>> +++ b/target/avr/translate.c
>>> @@ -3032,6 +3032,17 @@ done_generating:
>>>
>>>      tb->size = (ctx.npc - pc_start) * 2;
>>>      tb->icount = num_insns;
>>> +
>>> +#ifdef DEBUG_DISAS
>>> +    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
>>> +        && qemu_log_in_addr_range(tb->pc)) {
>>> +        qemu_log_lock();
>>> +        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
>>> +        log_target_disas(cs, tb->pc, tb->size);
>>> +        qemu_log("\n");
>>> +        qemu_log_unlock();
>>> +    }
>>> +#endif
>>>  }
>>>
>>>  void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
>>> --
>>> 2.17.2 (Apple Git-113)
>>>
>>>
>
> --
> Best Regards,
> Michael Rolnik
>
Aleksandar Markovic Dec. 2, 2019, 12:01 p.m. UTC | #4
On Monday, December 2, 2019, Michael Rolnik <mrolnik@gmail.com> wrote:

> Aleksandar.
>
> If this code is going to be merge in 2019 I should modify al the
> copyrights, right. or should I put 2020 in?
>
>
Michael,

Initially I saw your message as wry sense of humor.

But, in fact, it is not a bad idea at all. Since we know that AVR support
will not be in QEMU 4.2, the last release of QEMU in 2019, it looks to me
the right thing is to update *all* copyright message to year 2020. Please
do it.

Thank you for giving me the reason to laugh this morning! You made my day!

Aleksandar



> Regards,
> Michael Rolnik
>
> On Mon, Dec 2, 2019 at 2:28 AM Aleksandar Markovic <
> aleksandar.m.mail@gmail.com> wrote:
>
>>
>>
>> On Wednesday, November 27, 2019, Michael Rolnik <mrolnik@gmail.com>
>> wrote:
>>
>>> Provide function disassembles executed instruction when `-d in_asm` is
>>> provided
>>>
>>> Example:
>>> `./avr-softmmu/qemu-system-avr -bios free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf
>>> -d in_asm` will produce something like the following
>>>
>>> ```
>>>     ...
>>>     IN:
>>>     0x0000014a:  CALL      0x3808
>>>
>>>     IN: main
>>>     0x00003808:  CALL      0x4b4
>>>
>>>     IN: vParTestInitialise
>>>     0x000004b4:  LDI       r24, 255
>>>     0x000004b6:  STS       r24, 0
>>>     0x000004b8:  MULS      r16, r20
>>>     0x000004ba:  OUT       $1, r24
>>>     0x000004bc:  LDS       r24, 0
>>>     0x000004be:  MULS      r16, r20
>>>     0x000004c0:  OUT       $2, r24
>>>     0x000004c2:  RET
>>>     ...
>>> ```
>>>
>>> Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
>>> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
>>> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>>> Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
>>> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>>> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
>>> ---
>>>  target/avr/cpu.h       |   1 +
>>>  target/avr/cpu.c       |   2 +-
>>>  target/avr/disas.c     | 228 +++++++++++++++++++++++++++++++++++++++++
>>>  target/avr/translate.c |  11 ++
>>>  4 files changed, 241 insertions(+), 1 deletion(-)
>>>  create mode 100644 target/avr/disas.c
>>>
>>> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
>>> index 9ea5260165..a3e615a1eb 100644
>>> --- a/target/avr/cpu.h
>>> +++ b/target/avr/cpu.h
>>> @@ -157,6 +157,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu, int
>>> int_req);
>>>  hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
>>>  int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
>>>  int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
>>> +int avr_print_insn(bfd_vma addr, disassemble_info *info);
>>>
>>>  static inline int avr_feature(CPUAVRState *env, int feature)
>>>  {
>>> diff --git a/target/avr/cpu.c b/target/avr/cpu.c
>>> index dae56d7845..52ec21dd16 100644
>>> --- a/target/avr/cpu.c
>>> +++ b/target/avr/cpu.c
>>> @@ -83,7 +83,7 @@ static void avr_cpu_reset(CPUState *cs)
>>>  static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info
>>> *info)
>>>  {
>>>      info->mach = bfd_arch_avr;
>>> -    info->print_insn = NULL;
>>> +    info->print_insn = avr_print_insn;
>>>  }
>>>
>>>  static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
>>> diff --git a/target/avr/disas.c b/target/avr/disas.c
>>> new file mode 100644
>>> index 0000000000..a51ade7c2a
>>> --- /dev/null
>>> +++ b/target/avr/disas.c
>>> @@ -0,0 +1,228 @@
>>> +/*
>>> + * AVR disassembler
>>> + *
>>> + * Copyright (c) 2018 Richard Henderson <rth@twiddle.net>
>>
>>
>> Just a detail: since this file is created in 2019, the copyright year
>> should be 2019 too.
>>
>> + * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com>
>>> + *
>>> + * This program is free software: you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation, either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>
>>> .
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "disas/dis-asm.h"
>>> +#include "qemu/bitops.h"
>>> +#include "cpu.h"
>>> +
>>> +typedef struct {
>>> +    disassemble_info *info;
>>> +    uint16_t next_word;
>>> +    bool next_word_used;
>>> +} DisasContext;
>>> +
>>> +static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
>>> +{
>>> +    return 16 + (indx % 16);
>>> +}
>>> +
>>> +static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
>>> +{
>>> +    return 16 + (indx % 8);
>>> +}
>>> +static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
>>> +{
>>> +    return 24 + (indx % 4) * 2;
>>> +}
>>> +static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
>>> +{
>>> +    return (indx % 16) * 2;
>>> +}
>>> +
>>> +static uint16_t next_word(DisasContext *ctx)
>>> +{
>>> +    ctx->next_word_used = true;
>>> +    return ctx->next_word;
>>> +}
>>> +
>>> +static int append_16(DisasContext *ctx, int x)
>>> +{
>>> +    return x << 16 | next_word(ctx);
>>> +}
>>> +
>>> +
>>> +/* Include the auto-generated decoder.  */
>>> +static bool decode_insn(DisasContext *ctx, uint16_t insn);
>>> +#include "decode_insn.inc.c"
>>> +
>>> +#define output(mnemonic, format, ...) \
>>> +    (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
>>> +                        mnemonic, ##__VA_ARGS__))
>>> +
>>> +int avr_print_insn(bfd_vma addr, disassemble_info *info)
>>> +{
>>> +    DisasContext ctx;
>>> +    DisasContext *pctx = &ctx;
>>> +    bfd_byte buffer[4];
>>> +    uint16_t insn;
>>> +    int status;
>>> +
>>> +    ctx.info = info;
>>> +
>>> +    status = info->read_memory_func(addr, buffer, 4, info);
>>> +    if (status != 0) {
>>> +        info->memory_error_func(status, addr, info);
>>> +        return -1;
>>> +    }
>>> +    insn = bfd_getl16(buffer);
>>> +    ctx.next_word = bfd_getl16(buffer + 2);
>>> +    ctx.next_word_used = false;
>>> +
>>> +    if (!decode_insn(&ctx, insn)) {
>>> +        output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
>>> +    }
>>> +
>>> +    return ctx.next_word_used ? 4 : 2;
>>> +}
>>> +
>>> +
>>> +#define INSN(opcode, format, ...)
>>>  \
>>> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)
>>> \
>>> +{
>>>  \
>>> +    output(#opcode, format, ##__VA_ARGS__);
>>>  \
>>> +    return true;
>>> \
>>> +}
>>> +
>>> +#define INSN_MNEMONIC(opcode, mnemonic, format, ...)
>>> \
>>> +static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)
>>> \
>>> +{
>>>  \
>>> +    output(mnemonic, format, ##__VA_ARGS__);
>>> \
>>> +    return true;
>>> \
>>> +}
>>> +
>>> +/*
>>> + *   C       Z       N       V       S       H       T       I
>>> + *   0       1       2       3       4       5       6       7
>>> + */
>>> +static const char *brbc[] = {
>>> +    "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
>>> +};
>>> +
>>> +static const char *brbs[] = {
>>> +    "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
>>> +};
>>> +
>>> +static const char *bset[] = {
>>> +    "SEC",  "SEZ",  "SEN",  "SEZ",  "SES",  "SEH",  "SET",  "SEI"
>>> +};
>>> +
>>> +static const char *bclr[] = {
>>> +    "CLC",  "CLZ",  "CLN",  "CLZ",  "CLS",  "CLH",  "CLT",  "CLI"
>>> +};
>>> +
>>> +INSN(ADC,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(ADD,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(ADIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
>>> +INSN(AND,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(ANDI,   "r%d, %d", a->rd, a->imm)
>>> +INSN(ASR,    "r%d", a->rd)
>>> +INSN_MNEMONIC(BCLR,  bclr[a->bit], "")
>>> +INSN(BLD,    "r%d, %d", a->rd, a->bit)
>>> +INSN_MNEMONIC(BRBC,  brbc[a->bit], ".%+d", a->imm * 2)
>>> +INSN_MNEMONIC(BRBS,  brbs[a->bit], ".%+d", a->imm * 2)
>>> +INSN(BREAK,  "")
>>> +INSN_MNEMONIC(BSET,  bset[a->bit], "")
>>> +INSN(BST,    "r%d, %d", a->rd, a->bit)
>>> +INSN(CALL,   "0x%x", a->imm * 2)
>>> +INSN(CBI,    "%d, %d", a->reg, a->bit)
>>> +INSN(COM,    "r%d", a->rd)
>>> +INSN(CP,     "r%d, r%d", a->rd, a->rr)
>>> +INSN(CPC,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(CPI,    "r%d, %d", a->rd, a->imm)
>>> +INSN(CPSE,   "r%d, r%d", a->rd, a->rr)
>>> +INSN(DEC,    "r%d", a->rd)
>>> +INSN(DES,    "%d", a->imm)
>>> +INSN(EICALL, "")
>>> +INSN(EIJMP,  "")
>>> +INSN(ELPM1,  "")
>>> +INSN(ELPM2,  "r%d, Z", a->rd)
>>> +INSN(ELPMX,  "r%d, Z+", a->rd)
>>> +INSN(EOR,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(FMUL,   "r%d, r%d", a->rd, a->rr)
>>> +INSN(FMULS,  "r%d, r%d", a->rd, a->rr)
>>> +INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
>>> +INSN(ICALL,  "")
>>> +INSN(IJMP,   "")
>>> +INSN(IN,     "r%d, $%d", a->rd, a->imm)
>>> +INSN(INC,    "r%d", a->rd)
>>> +INSN(JMP,    "0x%x", a->imm * 2)
>>> +INSN(LAC,    "Z, r%d", a->rd)
>>> +INSN(LAS,    "Z, r%d", a->rd)
>>> +INSN(LAT,    "Z, r%d", a->rd)
>>> +INSN(LDDY,   "r%d, Y+%d", a->rd, a->imm)
>>> +INSN(LDDZ,   "r%d, Z+%d", a->rd, a->imm)
>>> +INSN(LDI,    "r%d, %d", a->rd, a->imm)
>>> +INSN(LDS,    "r%d, %d", a->rd, a->imm)
>>> +INSN(LDX1,   "r%d, X", a->rd)
>>> +INSN(LDX2,   "r%d, X+", a->rd)
>>> +INSN(LDX3,   "r%d, -X", a->rd)
>>> +INSN(LDY2,   "r%d, Y+", a->rd)
>>> +INSN(LDY3,   "r%d, -Y", a->rd)
>>> +INSN(LDZ2,   "r%d, Z+", a->rd)
>>> +INSN(LDZ3,   "r%d, -Z", a->rd)
>>> +INSN(LPM1,   "")
>>> +INSN(LPM2,   "r%d, Z", a->rd)
>>> +INSN(LPMX,   "r%d, Z+", a->rd)
>>> +INSN(LSR,    "r%d", a->rd)
>>> +INSN(MOV,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(MOVW,   "r%d:r%d, r%d,r:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
>>> +INSN(MUL,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(MULS,   "r%d, r%d", a->rd, a->rr)
>>> +INSN(MULSU,  "r%d, r%d", a->rd, a->rr)
>>> +INSN(NEG,    "r%d", a->rd)
>>> +INSN(NOP,    "")
>>> +INSN(OR,     "r%d, r%d", a->rd, a->rr)
>>> +INSN(ORI,    "r%d, %d", a->rd, a->imm)
>>> +INSN(OUT,    "$%d, r%d", a->imm, a->rd)
>>> +INSN(POP,    "r%d", a->rd)
>>> +INSN(PUSH,   "r%d", a->rd)
>>> +INSN(RCALL,  ".%+d", a->imm * 2)
>>> +INSN(RET,    "")
>>> +INSN(RETI,   "")
>>> +INSN(RJMP,   ".%+d", a->imm * 2)
>>> +INSN(ROR,    "r%d", a->rd)
>>> +INSN(SBC,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(SBCI,   "r%d, %d", a->rd, a->imm)
>>> +INSN(SBI,    "$%d, %d", a->reg, a->bit)
>>> +INSN(SBIC,   "$%d, %d", a->reg, a->bit)
>>> +INSN(SBIS,   "$%d, %d", a->reg, a->bit)
>>> +INSN(SBIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
>>> +INSN(SBRC,   "r%d, %d", a->rr, a->bit)
>>> +INSN(SBRS,   "r%d, %d", a->rr, a->bit)
>>> +INSN(SLEEP,  "")
>>> +INSN(SPM,    "")
>>> +INSN(SPMX,   "Z+")
>>> +INSN(STDY,   "r%d, Y+%d", a->rd, a->imm)
>>> +INSN(STDZ,   "r%d, Z+%d", a->rd, a->imm)
>>> +INSN(STS,    "r%d, %d", a->rd, a->imm)
>>> +INSN(STX1,   "r%d, X", a->rr)
>>> +INSN(STX2,   "r%d, X+", a->rr)
>>> +INSN(STX3,   "r%d, -X", a->rr)
>>> +INSN(STY2,   "r%d, Y+", a->rd)
>>> +INSN(STY3,   "r%d, -Y", a->rd)
>>> +INSN(STZ2,   "r%d, Z+", a->rd)
>>> +INSN(STZ3,   "r%d, -Z", a->rd)
>>> +INSN(SUB,    "r%d, r%d", a->rd, a->rr)
>>> +INSN(SUBI,   "r%d, %d", a->rd, a->imm)
>>> +INSN(SWAP,   "r%d", a->rd)
>>> +INSN(WDR,    "")
>>> +INSN(XCH,    "Z, r%d", a->rd)
>>> +
>>> diff --git a/target/avr/translate.c b/target/avr/translate.c
>>> index 941db8e168..e562e68d88 100644
>>> --- a/target/avr/translate.c
>>> +++ b/target/avr/translate.c
>>> @@ -3032,6 +3032,17 @@ done_generating:
>>>
>>>      tb->size = (ctx.npc - pc_start) * 2;
>>>      tb->icount = num_insns;
>>> +
>>> +#ifdef DEBUG_DISAS
>>> +    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
>>> +        && qemu_log_in_addr_range(tb->pc)) {
>>> +        qemu_log_lock();
>>> +        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
>>> +        log_target_disas(cs, tb->pc, tb->size);
>>> +        qemu_log("\n");
>>> +        qemu_log_unlock();
>>> +    }
>>> +#endif
>>>  }
>>>
>>>  void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
>>> --
>>> 2.17.2 (Apple Git-113)
>>>
>>>
>
> --
> Best Regards,
> Michael Rolnik
>
Philippe Mathieu-Daudé Dec. 3, 2019, 11:18 a.m. UTC | #5
On 12/2/19 8:04 AM, Michael Rolnik wrote:
> Aleksandar.
> 
> If this code is going to be merge in 2019 I should modify al the 
> copyrights, right. or should I put 2020 in?

Usually the copyright date is when you first contributed your code to 
the world (here, the list). If a patch was on the list in 2018, even if 
you made modifications and repost it, (c) is 2018.

IOW, If your series gets merged in 2020, it will be merged as (c) 2019.

I'm not sure why Richard's (c) appears here, is target/avr/disas.c based 
on target/openrisc/disas.c? Then it looks correct to me, but IANAL.

> On Mon, Dec 2, 2019 at 2:28 AM Aleksandar Markovic 
> <aleksandar.m.mail@gmail.com <mailto:aleksandar.m.mail@gmail.com>> wrote:
> 
> 
> 
>     On Wednesday, November 27, 2019, Michael Rolnik <mrolnik@gmail.com
>     <mailto:mrolnik@gmail.com>> wrote:
> 
>         Provide function disassembles executed instruction when `-d
>         in_asm` is
>         provided
> 
>         Example:
>         `./avr-softmmu/qemu-system-avr -bios
>         free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf -d in_asm` will
>         produce something like the following
> 
>         ```
>              ...
>              IN:
>              0x0000014a:  CALL      0x3808
> 
>              IN: main
>              0x00003808:  CALL      0x4b4
> 
>              IN: vParTestInitialise
>              0x000004b4:  LDI       r24, 255
>              0x000004b6:  STS       r24, 0
>              0x000004b8:  MULS      r16, r20
>              0x000004ba:  OUT       $1, r24
>              0x000004bc:  LDS       r24, 0
>              0x000004be:  MULS      r16, r20
>              0x000004c0:  OUT       $2, r24
>              0x000004c2:  RET
>              ...
>         ```
> 
>         Signed-off-by: Michael Rolnik <mrolnik@gmail.com
>         <mailto:mrolnik@gmail.com>>
>         Suggested-by: Richard Henderson <richard.henderson@linaro.org
>         <mailto:richard.henderson@linaro.org>>
>         Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com
>         <mailto:philmd@redhat.com>>
>         Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com
>         <mailto:aleksandar.m.mail@gmail.com>>
>         Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
>         <mailto:philmd@redhat.com>>
>         Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com
>         <mailto:philmd@redhat.com>>
>         ---
>           target/avr/cpu.h       |   1 +
>           target/avr/cpu.c       |   2 +-
>           target/avr/disas.c     | 228
>         +++++++++++++++++++++++++++++++++++++++++
>           target/avr/translate.c |  11 ++
>           4 files changed, 241 insertions(+), 1 deletion(-)
>           create mode 100644 target/avr/disas.c
> 
>         diff --git a/target/avr/cpu.h b/target/avr/cpu.h
>         index 9ea5260165..a3e615a1eb 100644
>         --- a/target/avr/cpu.h
>         +++ b/target/avr/cpu.h
>         @@ -157,6 +157,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu,
>         int int_req);
>           hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
>           int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int
>         reg);
>           int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf,
>         int reg);
>         +int avr_print_insn(bfd_vma addr, disassemble_info *info);
> 
>           static inline int avr_feature(CPUAVRState *env, int feature)
>           {
>         diff --git a/target/avr/cpu.c b/target/avr/cpu.c
>         index dae56d7845..52ec21dd16 100644
>         --- a/target/avr/cpu.c
>         +++ b/target/avr/cpu.c
>         @@ -83,7 +83,7 @@ static void avr_cpu_reset(CPUState *cs)
>           static void avr_cpu_disas_set_info(CPUState *cpu,
>         disassemble_info *info)
>           {
>               info->mach = bfd_arch_avr;
>         -    info->print_insn = NULL;
>         +    info->print_insn = avr_print_insn;
>           }
> 
>           static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
>         diff --git a/target/avr/disas.c b/target/avr/disas.c
>         new file mode 100644
>         index 0000000000..a51ade7c2a
>         --- /dev/null
>         +++ b/target/avr/disas.c
>         @@ -0,0 +1,228 @@
>         +/*
>         + * AVR disassembler
>         + *
>         + * Copyright (c) 2018 Richard Henderson <rth@twiddle.net
>         <mailto:rth@twiddle.net>>
> 
> 
>     Just a detail: since this file is created in 2019, the copyright
>     year should be 2019 too.
> 
>         + * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com
>         <mailto:mrolnik@gmail.com>>
>         + *
>         + * This program is free software: you can redistribute it
>         and/or modify
>         + * it under the terms of the GNU General Public License as
>         published by
>         + * the Free Software Foundation, either version 2 of the
>         License, or
>         + * (at your option) any later version.
>         + *
>         + * This program is distributed in the hope that it will be useful,
>         + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>         + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>         + * GNU General Public License for more details.
>         + *
>         + * You should have received a copy of the GNU General Public
>         License
>         + * along with this program.  If not, see
>         <http://www.gnu.org/licenses/>.
>         + */
[...]
Michael Rolnik Dec. 3, 2019, 2:24 p.m. UTC | #6
Hi Philippe.

I copied Richard's file and modified it's content, that's why Richard is
there.

Regards,
Michael Rolnik

On Tue, Dec 3, 2019 at 1:18 PM Philippe Mathieu-Daudé <philmd@redhat.com>
wrote:

> On 12/2/19 8:04 AM, Michael Rolnik wrote:
> > Aleksandar.
> >
> > If this code is going to be merge in 2019 I should modify al the
> > copyrights, right. or should I put 2020 in?
>
> Usually the copyright date is when you first contributed your code to
> the world (here, the list). If a patch was on the list in 2018, even if
> you made modifications and repost it, (c) is 2018.
>
> IOW, If your series gets merged in 2020, it will be merged as (c) 2019.
>
> I'm not sure why Richard's (c) appears here, is target/avr/disas.c based
> on target/openrisc/disas.c? Then it looks correct to me, but IANAL.
>
> > On Mon, Dec 2, 2019 at 2:28 AM Aleksandar Markovic
> > <aleksandar.m.mail@gmail.com <mailto:aleksandar.m.mail@gmail.com>>
> wrote:
> >
> >
> >
> >     On Wednesday, November 27, 2019, Michael Rolnik <mrolnik@gmail.com
> >     <mailto:mrolnik@gmail.com>> wrote:
> >
> >         Provide function disassembles executed instruction when `-d
> >         in_asm` is
> >         provided
> >
> >         Example:
> >         `./avr-softmmu/qemu-system-avr -bios
> >         free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf -d in_asm` will
> >         produce something like the following
> >
> >         ```
> >              ...
> >              IN:
> >              0x0000014a:  CALL      0x3808
> >
> >              IN: main
> >              0x00003808:  CALL      0x4b4
> >
> >              IN: vParTestInitialise
> >              0x000004b4:  LDI       r24, 255
> >              0x000004b6:  STS       r24, 0
> >              0x000004b8:  MULS      r16, r20
> >              0x000004ba:  OUT       $1, r24
> >              0x000004bc:  LDS       r24, 0
> >              0x000004be:  MULS      r16, r20
> >              0x000004c0:  OUT       $2, r24
> >              0x000004c2:  RET
> >              ...
> >         ```
> >
> >         Signed-off-by: Michael Rolnik <mrolnik@gmail.com
> >         <mailto:mrolnik@gmail.com>>
> >         Suggested-by: Richard Henderson <richard.henderson@linaro.org
> >         <mailto:richard.henderson@linaro.org>>
> >         Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com
> >         <mailto:philmd@redhat.com>>
> >         Suggested-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com
> >         <mailto:aleksandar.m.mail@gmail.com>>
> >         Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
> >         <mailto:philmd@redhat.com>>
> >         Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com
> >         <mailto:philmd@redhat.com>>
> >         ---
> >           target/avr/cpu.h       |   1 +
> >           target/avr/cpu.c       |   2 +-
> >           target/avr/disas.c     | 228
> >         +++++++++++++++++++++++++++++++++++++++++
> >           target/avr/translate.c |  11 ++
> >           4 files changed, 241 insertions(+), 1 deletion(-)
> >           create mode 100644 target/avr/disas.c
> >
> >         diff --git a/target/avr/cpu.h b/target/avr/cpu.h
> >         index 9ea5260165..a3e615a1eb 100644
> >         --- a/target/avr/cpu.h
> >         +++ b/target/avr/cpu.h
> >         @@ -157,6 +157,7 @@ bool avr_cpu_exec_interrupt(CPUState *cpu,
> >         int int_req);
> >           hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
> >           int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int
> >         reg);
> >           int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf,
> >         int reg);
> >         +int avr_print_insn(bfd_vma addr, disassemble_info *info);
> >
> >           static inline int avr_feature(CPUAVRState *env, int feature)
> >           {
> >         diff --git a/target/avr/cpu.c b/target/avr/cpu.c
> >         index dae56d7845..52ec21dd16 100644
> >         --- a/target/avr/cpu.c
> >         +++ b/target/avr/cpu.c
> >         @@ -83,7 +83,7 @@ static void avr_cpu_reset(CPUState *cs)
> >           static void avr_cpu_disas_set_info(CPUState *cpu,
> >         disassemble_info *info)
> >           {
> >               info->mach = bfd_arch_avr;
> >         -    info->print_insn = NULL;
> >         +    info->print_insn = avr_print_insn;
> >           }
> >
> >           static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
> >         diff --git a/target/avr/disas.c b/target/avr/disas.c
> >         new file mode 100644
> >         index 0000000000..a51ade7c2a
> >         --- /dev/null
> >         +++ b/target/avr/disas.c
> >         @@ -0,0 +1,228 @@
> >         +/*
> >         + * AVR disassembler
> >         + *
> >         + * Copyright (c) 2018 Richard Henderson <rth@twiddle.net
> >         <mailto:rth@twiddle.net>>
> >
> >
> >     Just a detail: since this file is created in 2019, the copyright
> >     year should be 2019 too.
> >
> >         + * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com
> >         <mailto:mrolnik@gmail.com>>
> >         + *
> >         + * This program is free software: you can redistribute it
> >         and/or modify
> >         + * it under the terms of the GNU General Public License as
> >         published by
> >         + * the Free Software Foundation, either version 2 of the
> >         License, or
> >         + * (at your option) any later version.
> >         + *
> >         + * This program is distributed in the hope that it will be
> useful,
> >         + * but WITHOUT ANY WARRANTY; without even the implied warranty
> of
> >         + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >         + * GNU General Public License for more details.
> >         + *
> >         + * You should have received a copy of the GNU General Public
> >         License
> >         + * along with this program.  If not, see
> >         <http://www.gnu.org/licenses/>.
> >         + */
> [...]
>
>
diff mbox series

Patch

diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index 9ea5260165..a3e615a1eb 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -157,6 +157,7 @@  bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
 hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int avr_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int avr_print_insn(bfd_vma addr, disassemble_info *info);
 
 static inline int avr_feature(CPUAVRState *env, int feature)
 {
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index dae56d7845..52ec21dd16 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -83,7 +83,7 @@  static void avr_cpu_reset(CPUState *cs)
 static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
 {
     info->mach = bfd_arch_avr;
-    info->print_insn = NULL;
+    info->print_insn = avr_print_insn;
 }
 
 static void avr_cpu_realizefn(DeviceState *dev, Error **errp)
diff --git a/target/avr/disas.c b/target/avr/disas.c
new file mode 100644
index 0000000000..a51ade7c2a
--- /dev/null
+++ b/target/avr/disas.c
@@ -0,0 +1,228 @@ 
+/*
+ * AVR disassembler
+ *
+ * Copyright (c) 2018 Richard Henderson <rth@twiddle.net>
+ * Copyright (c) 2019 Michael Rolnik <mrolnik@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+#include "cpu.h"
+
+typedef struct {
+    disassemble_info *info;
+    uint16_t next_word;
+    bool next_word_used;
+} DisasContext;
+
+static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
+{
+    return 16 + (indx % 16);
+}
+
+static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
+{
+    return 16 + (indx % 8);
+}
+static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
+{
+    return 24 + (indx % 4) * 2;
+}
+static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
+{
+    return (indx % 16) * 2;
+}
+
+static uint16_t next_word(DisasContext *ctx)
+{
+    ctx->next_word_used = true;
+    return ctx->next_word;
+}
+
+static int append_16(DisasContext *ctx, int x)
+{
+    return x << 16 | next_word(ctx);
+}
+
+
+/* Include the auto-generated decoder.  */
+static bool decode_insn(DisasContext *ctx, uint16_t insn);
+#include "decode_insn.inc.c"
+
+#define output(mnemonic, format, ...) \
+    (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \
+                        mnemonic, ##__VA_ARGS__))
+
+int avr_print_insn(bfd_vma addr, disassemble_info *info)
+{
+    DisasContext ctx;
+    DisasContext *pctx = &ctx;
+    bfd_byte buffer[4];
+    uint16_t insn;
+    int status;
+
+    ctx.info = info;
+
+    status = info->read_memory_func(addr, buffer, 4, info);
+    if (status != 0) {
+        info->memory_error_func(status, addr, info);
+        return -1;
+    }
+    insn = bfd_getl16(buffer);
+    ctx.next_word = bfd_getl16(buffer + 2);
+    ctx.next_word_used = false;
+
+    if (!decode_insn(&ctx, insn)) {
+        output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
+    }
+
+    return ctx.next_word_used ? 4 : 2;
+}
+
+
+#define INSN(opcode, format, ...)                                       \
+static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)        \
+{                                                                       \
+    output(#opcode, format, ##__VA_ARGS__);                             \
+    return true;                                                        \
+}
+
+#define INSN_MNEMONIC(opcode, mnemonic, format, ...)                    \
+static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a)        \
+{                                                                       \
+    output(mnemonic, format, ##__VA_ARGS__);                            \
+    return true;                                                        \
+}
+
+/*
+ *   C       Z       N       V       S       H       T       I
+ *   0       1       2       3       4       5       6       7
+ */
+static const char *brbc[] = {
+    "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID"
+};
+
+static const char *brbs[] = {
+    "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE"
+};
+
+static const char *bset[] = {
+    "SEC",  "SEZ",  "SEN",  "SEZ",  "SES",  "SEH",  "SET",  "SEI"
+};
+
+static const char *bclr[] = {
+    "CLC",  "CLZ",  "CLN",  "CLZ",  "CLS",  "CLH",  "CLT",  "CLI"
+};
+
+INSN(ADC,    "r%d, r%d", a->rd, a->rr)
+INSN(ADD,    "r%d, r%d", a->rd, a->rr)
+INSN(ADIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
+INSN(AND,    "r%d, r%d", a->rd, a->rr)
+INSN(ANDI,   "r%d, %d", a->rd, a->imm)
+INSN(ASR,    "r%d", a->rd)
+INSN_MNEMONIC(BCLR,  bclr[a->bit], "")
+INSN(BLD,    "r%d, %d", a->rd, a->bit)
+INSN_MNEMONIC(BRBC,  brbc[a->bit], ".%+d", a->imm * 2)
+INSN_MNEMONIC(BRBS,  brbs[a->bit], ".%+d", a->imm * 2)
+INSN(BREAK,  "")
+INSN_MNEMONIC(BSET,  bset[a->bit], "")
+INSN(BST,    "r%d, %d", a->rd, a->bit)
+INSN(CALL,   "0x%x", a->imm * 2)
+INSN(CBI,    "%d, %d", a->reg, a->bit)
+INSN(COM,    "r%d", a->rd)
+INSN(CP,     "r%d, r%d", a->rd, a->rr)
+INSN(CPC,    "r%d, r%d", a->rd, a->rr)
+INSN(CPI,    "r%d, %d", a->rd, a->imm)
+INSN(CPSE,   "r%d, r%d", a->rd, a->rr)
+INSN(DEC,    "r%d", a->rd)
+INSN(DES,    "%d", a->imm)
+INSN(EICALL, "")
+INSN(EIJMP,  "")
+INSN(ELPM1,  "")
+INSN(ELPM2,  "r%d, Z", a->rd)
+INSN(ELPMX,  "r%d, Z+", a->rd)
+INSN(EOR,    "r%d, r%d", a->rd, a->rr)
+INSN(FMUL,   "r%d, r%d", a->rd, a->rr)
+INSN(FMULS,  "r%d, r%d", a->rd, a->rr)
+INSN(FMULSU, "r%d, r%d", a->rd, a->rr)
+INSN(ICALL,  "")
+INSN(IJMP,   "")
+INSN(IN,     "r%d, $%d", a->rd, a->imm)
+INSN(INC,    "r%d", a->rd)
+INSN(JMP,    "0x%x", a->imm * 2)
+INSN(LAC,    "Z, r%d", a->rd)
+INSN(LAS,    "Z, r%d", a->rd)
+INSN(LAT,    "Z, r%d", a->rd)
+INSN(LDDY,   "r%d, Y+%d", a->rd, a->imm)
+INSN(LDDZ,   "r%d, Z+%d", a->rd, a->imm)
+INSN(LDI,    "r%d, %d", a->rd, a->imm)
+INSN(LDS,    "r%d, %d", a->rd, a->imm)
+INSN(LDX1,   "r%d, X", a->rd)
+INSN(LDX2,   "r%d, X+", a->rd)
+INSN(LDX3,   "r%d, -X", a->rd)
+INSN(LDY2,   "r%d, Y+", a->rd)
+INSN(LDY3,   "r%d, -Y", a->rd)
+INSN(LDZ2,   "r%d, Z+", a->rd)
+INSN(LDZ3,   "r%d, -Z", a->rd)
+INSN(LPM1,   "")
+INSN(LPM2,   "r%d, Z", a->rd)
+INSN(LPMX,   "r%d, Z+", a->rd)
+INSN(LSR,    "r%d", a->rd)
+INSN(MOV,    "r%d, r%d", a->rd, a->rr)
+INSN(MOVW,   "r%d:r%d, r%d,r:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr)
+INSN(MUL,    "r%d, r%d", a->rd, a->rr)
+INSN(MULS,   "r%d, r%d", a->rd, a->rr)
+INSN(MULSU,  "r%d, r%d", a->rd, a->rr)
+INSN(NEG,    "r%d", a->rd)
+INSN(NOP,    "")
+INSN(OR,     "r%d, r%d", a->rd, a->rr)
+INSN(ORI,    "r%d, %d", a->rd, a->imm)
+INSN(OUT,    "$%d, r%d", a->imm, a->rd)
+INSN(POP,    "r%d", a->rd)
+INSN(PUSH,   "r%d", a->rd)
+INSN(RCALL,  ".%+d", a->imm * 2)
+INSN(RET,    "")
+INSN(RETI,   "")
+INSN(RJMP,   ".%+d", a->imm * 2)
+INSN(ROR,    "r%d", a->rd)
+INSN(SBC,    "r%d, r%d", a->rd, a->rr)
+INSN(SBCI,   "r%d, %d", a->rd, a->imm)
+INSN(SBI,    "$%d, %d", a->reg, a->bit)
+INSN(SBIC,   "$%d, %d", a->reg, a->bit)
+INSN(SBIS,   "$%d, %d", a->reg, a->bit)
+INSN(SBIW,   "r%d:r%d, %d", a->rd + 1, a->rd, a->imm)
+INSN(SBRC,   "r%d, %d", a->rr, a->bit)
+INSN(SBRS,   "r%d, %d", a->rr, a->bit)
+INSN(SLEEP,  "")
+INSN(SPM,    "")
+INSN(SPMX,   "Z+")
+INSN(STDY,   "r%d, Y+%d", a->rd, a->imm)
+INSN(STDZ,   "r%d, Z+%d", a->rd, a->imm)
+INSN(STS,    "r%d, %d", a->rd, a->imm)
+INSN(STX1,   "r%d, X", a->rr)
+INSN(STX2,   "r%d, X+", a->rr)
+INSN(STX3,   "r%d, -X", a->rr)
+INSN(STY2,   "r%d, Y+", a->rd)
+INSN(STY3,   "r%d, -Y", a->rd)
+INSN(STZ2,   "r%d, Z+", a->rd)
+INSN(STZ3,   "r%d, -Z", a->rd)
+INSN(SUB,    "r%d, r%d", a->rd, a->rr)
+INSN(SUBI,   "r%d, %d", a->rd, a->imm)
+INSN(SWAP,   "r%d", a->rd)
+INSN(WDR,    "")
+INSN(XCH,    "Z, r%d", a->rd)
+
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 941db8e168..e562e68d88 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -3032,6 +3032,17 @@  done_generating:
 
     tb->size = (ctx.npc - pc_start) * 2;
     tb->icount = num_insns;
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
+        && qemu_log_in_addr_range(tb->pc)) {
+        qemu_log_lock();
+        qemu_log("IN: %s\n", lookup_symbol(tb->pc));
+        log_target_disas(cs, tb->pc, tb->size);
+        qemu_log("\n");
+        qemu_log_unlock();
+    }
+#endif
 }
 
 void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,