qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 1/3] target-m68k: add cmpm


From: Laurent Vivier
Subject: Re: [Qemu-devel] [PATCH v2 1/3] target-m68k: add cmpm
Date: Tue, 1 Nov 2016 20:58:53 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0


Le 01/11/2016 à 18:48, Richard Henderson a écrit :
> On 10/27/2016 03:43 PM, Laurent Vivier wrote:
>> +DISAS_INSN(cmpm)
>> +{
>> +    int opsize = insn_opsize(insn);
>> +    TCGv tmp = tcg_temp_new();
>> +    TCGv src, dst, addr;
>> +
>> +    src = gen_load(s, opsize, AREG(insn, 0), 1);
>> +    /* delay the update after the second gen_load() */
>> +    tcg_gen_addi_i32(tmp, AREG(insn, 0), opsize_bytes(opsize));
>> +
>> +    /* but if the we use the same address register to
>> +     * read the second value, we must use the updated address
>> +     */
>> +    if (REG(insn, 0) == REG(insn, 9)) {
>> +        addr = tmp;
>> +    } else {
>> +        addr = AREG(insn, 9);
>> +    }
>> +
>> +    dst = gen_load(s, opsize, addr, 1);
>> +    tcg_gen_mov_i32(AREG(insn, 0), tmp);
>> +    tcg_gen_addi_i32(AREG(insn, 9), addr, opsize_bytes(opsize));
> 
> I wonder if we should make this more generic.
> I'm thinking of transparently fixing
> 
>     case 3: /* Indirect postincrement.  */
>         reg = AREG(insn, 0);
>         result = gen_ldst(s, opsize, reg, val, what);
>         /* ??? This is not exception safe.  The instruction may still
>            fault after this point.  */
>         if (what == EA_STORE || !addrp)
>             tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
>         return result;
> 
> If we add to DisasContext
> 
>     unsigned writeback_mask;
>     TCGv writeback[8];
> 
> Then
> 
> static TCGv get_areg(DisasContext *s, unsigned regno)
> {
>     if (s->writeback_mask & (1 << regno)) {
>         return s->writeback[regno];
>     } else {
>         return cpu_aregs[regno];
>     }
> }
> 
> static void delay_set_areg(DisasContext *s, unsigned regno,
>                            TCGv val, bool give_temp)
> {
>     if (s->writeback_mask & (1 << regno)) {
>         tcg_gen_mov_i32(s->writeback[regno], val);
>         if (give_temp) {
>             tcg_temp_free(val);
>         }
>     } else {
>         s->writeback_mask |= 1 << regno;
>         if (give_temp) {
>             s->writeback[regno] = val;
>         } else {
>             TCGv tmp = tcg_temp_new();
>             tcg_gen_mov_i32(tmp, val);
>             s->writeback[regno] = tmp;
>         }
>     }
> }
> 
> static void do_writebacks(DisasContext *s)
> {
>     unsigned mask = s->writeback_mask;
>     if (mask) {
>         s->writeback_mask = 0;
>         do {
>             unsigned regno = ctz32(mask);
>             tcg_gen_mov_i32(cpu_aregs[regno], s->writeback[regno]);
>             tcg_temp_free(s->writeback[regno]);
>             mask &= mask - 1;
>         } while (mask);
>     }
> }
> 
> where get_areg is used within the AREG macro, delay_set_areg is used in
> those cases where pre- and post-increment are needed, and do_writebacks
> is invoked at the end of disas_m68k_insn.
> 
> This all pre-supposes that cmpm is not a special-case within the ISA,
> that any time one reuses a register after modification one sees the new
> value.  Given the existing code within gen_ea, this would seem to be the
> case.
> 
> Thoughts?

I think it's really a good idea to manage this in a generic way.
As you have already written 90% of the code, do you want to provide a
patch? I can test this with coldfire kernel and 68020 linux-user container.

Thanks,
Laurent



reply via email to

[Prev in Thread] Current Thread [Next in Thread]