qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: Laurent Vivier <laurent@vivier.eu>, qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com,
	Andreas Schwab <schwab@linux-m68k.org>,
	gerg@uclinux.org
Subject: Re: [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions
Date: Wed, 12 Aug 2015 14:05:09 -0700	[thread overview]
Message-ID: <55CBB505.8010805@twiddle.net> (raw)
In-Reply-To: <1439151229-27747-31-git-send-email-laurent@vivier.eu>

On 08/09/2015 01:13 PM, Laurent Vivier wrote:
>  uint32_t HELPER(rol32)(uint32_t val, uint32_t shift)
>  {
>      uint32_t result;
> @@ -1227,6 +1241,53 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
>      env->macc[acc + 1] = res;
>  }
>  
> +/* load from a bitfield */
> +
> +uint64_t HELPER(bitfield_load)(uint32_t addr, uint32_t offset, uint32_t width)
> +{
> +    uint8_t data[8];
> +    uint64_t bitfield;
> +    int size;
> +    int i;
> +
> +    size = (offset + width + 7) >> 3;
> +#if defined(CONFIG_USER_ONLY)
> +    cpu_memory_rw_debug(NULL, (target_ulong)addr, data, size, 0);
> +#else
> +    cpu_physical_memory_rw(addr, data, size, 0);
> +#endif

Err, this bypasses virtual memory.  Definitely not correct.

You'll need to use cpu_ld*_data instead.

> +DISAS_INSN(bitfield_reg)
> +{
> +    uint16_t ext;
> +    TCGv tmp;
> +    TCGv tmp1;
> +    TCGv reg;
> +    TCGv offset;
> +    TCGv width;
> +    int op;
> +    TCGv reg2;
> +    TCGv mask;
> +
> +    reg = DREG(insn, 0);
> +    op = (insn >> 8) & 7;
> +    ext = read_im16(env, s);
> +
> +    bitfield_param(ext, &offset, &width, &mask);
> +
> +    if (ext & 0x0800) {
> +        tcg_gen_andi_i32(offset, offset, 31);
> +    }
> +    gen_helper_ror32(mask, mask, offset);

Ah, the curious unused helpers.  Anyway, tcg_gen_rotr_i32.

Anyway, there's so much redundant computation in here let's name some
sub-expressions, and give them their own temporaries.  Let the tcg optimizer do
its job if they turn out to be unused for a specific case.

  mask_msb = mask before the rotate (at msb).
  mask_inp = mask after the rotate (in place).

> +    tmp = tcg_temp_new_i32();
> +    tcg_gen_and_i32(tmp, reg, mask);

  oldf_inp = tmp (old field in place).

> +
> +    tmp1 = tcg_temp_new_i32();
> +    gen_helper_rol32(tmp1, tmp, offset);

  oldf_msb = tmp1 (old field at msb).

> +        tcg_gen_sub_i32(tmp2, tcg_const_i32(32), width);

  comp_width = tmp2 (compliment of width).

Use tcg_gen_subfi so you won't leak the const.
Compute this once for all of the sub-cases.

> +    switch (op) {
> +    case 0: /* bftst */
> +        break;
> +    case 1: /* bfextu */
> +        tcg_gen_add_i32(tmp1, offset, width);
> +        tcg_gen_andi_i32(tmp1, tmp1, 31);
> +        gen_helper_rol32(reg2, tmp, tmp1);

  tcg_gen_shr_i32(reg2, oldf_msb, comp_width);

> +        break;
> +    case 2: /* bfchg */
> +        tcg_gen_xor_i32(reg, reg, mask);
> +        break;
> +    case 3: /* bfexts */
> +        gen_helper_rol32(reg2, tmp, offset);
> +        tcg_gen_sub_i32(width, tcg_const_i32(32), width);
> +        tcg_gen_sar_i32(reg2, reg2, width);

  tcg_gen_sar_i32(reg2, oldf_msb, comp_width);

> +    case 4: /* bfclr */
> +        tcg_gen_not_i32(mask, mask);
> +        tcg_gen_and_i32(reg, reg, mask);

  tcg_gen_andc_i32(reg, reg, mask_inp);

> +        break;
> +    case 5: /* bfffo */
> +        gen_helper_rol32(reg2, tmp, offset);
> +        gen_helper_bfffo(tmp, tmp, width);
> +        tcg_gen_add_i32(reg2, tmp, offset);

There's a typo here if you look close.  That said,

  tcg_gen_orc_i32(tmp, oldf_msb, mask_msb);
  gen_helper_clo32(tmp, tmp);
  tcg_gen_add_i32(reg2, tmp, offset);

with

uint32_t helper_clo32(uint32_t x)
{
  return clo32(x);
}

The first opcode sets all bits outside the field, so that (if the field is
smaller than 32 bits) we're guaranteed to find a one.  At which point there's
really very little that needs doing in the helper.

> +    case 6: /* bfset */
> +        tcg_gen_or_i32(reg, reg, mask);
> +        break;

  tcg_gen_or_i32(reg, reg, mask_inp);

> +    case 7: /* bfins */
> +        tcg_gen_shl_i32(tmp1, tcg_const_i32(1), width);

Undefined if width == 32.  That said...

> +        tcg_gen_subi_i32(tmp1, tmp1, 1);
> +        tcg_gen_and_i32(tmp, reg2, tmp1);
> +        tcg_gen_add_i32(tmp1, offset, width);
> +        tcg_gen_andi_i32(tmp1, tmp1, 31);
> +        gen_helper_ror32(tmp, tmp, tmp1);
> +        tcg_gen_not_i32(mask, mask);
> +        tcg_gen_and_i32(reg, reg, mask);
> +        tcg_gen_or_i32(reg, reg, tmp);
> +        break;

  /* Rotate the source so that the field is at msb.  */
  tcg_gen_rotr_i32(tmp, reg2, width);

  /* Isolate the field and set flags.  */
  tcg_gen_and_i32(tmp, tmp, mask_msb);
  gen_logic_cc(s, tmp, OS_LONG);

  /* Rotate the field into position.  */
  tcg_gen_rotr_i32(tmp, tmp, offset);

  /* Merge field into destination.  */
  tcg_gen_andc_i32(reg, reg, mask_inp);
  tcg_gen_or_i32(reg, reg, tmp);
  return;

Handle the non-bfins after the switch with

  gen_logic_cc(s, oldf_msb, OS_LONG);

> +DISAS_INSN(bitfield_mem)
> +{
> +    uint16_t ext;
> +    int op;
> +    TCGv_i64 bitfield;
> +    TCGv_i64 mask_bitfield;
> +    TCGv mask_cc;
> +    TCGv shift;
> +    TCGv val;
> +    TCGv src;
> +    TCGv offset;
> +    TCGv width;
> +    TCGv reg;
> +    TCGv tmp;
> +
> +    op = (insn >> 8) & 7;
> +    ext = read_im16(env, s);
> +    src = gen_lea(env, s, insn, OS_LONG);
> +    if (IS_NULL_QREG(src)) {
> +        gen_addr_fault(s);
> +        return;
> +    }
> +
> +    bitfield_param(ext, &offset, &width, &mask_cc);
> +
> +    /* adjust src and offset */
> +
> +    /* src += offset >> 3; */
> +
> +    tmp = tcg_temp_new_i32();
> +    tcg_gen_shri_i32(tmp, offset, 3);
> +    tcg_gen_add_i32(src, src, tmp);
> +
> +    /* offset &= 7; */
> +
> +    tcg_gen_andi_i32(offset, offset, 7);
> +
> +    /* load */
> +
> +    bitfield = tcg_temp_new_i64();
> +    gen_helper_bitfield_load(bitfield, src, offset, width);

Surely better to load the value from memory such that the field is positioned
at the MSB, share code with bitfield_reg for the actual computation of flags
and result, and then store the value back from the temporary at MSB as needed.


r~

  reply	other threads:[~2015-08-12 21:05 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-09 20:13 [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 01/30] m68k: define m680x0 CPUs and features Laurent Vivier
2015-08-11 23:13   ` Richard Henderson
2015-08-12  8:01     ` Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 02/30] m68k: manage scaled index Laurent Vivier
2015-08-12  3:42   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 03/30] m68k: introduce read_imXX() functions Laurent Vivier
2015-08-09 21:12   ` Andreas Schwab
2015-08-12  3:54   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 04/30] m68k: set disassembler mode to 680x0 or coldfire Laurent Vivier
2015-08-12  3:57   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 05/30] m68k: define operand sizes Laurent Vivier
2015-08-12  4:07   ` Richard Henderson
2015-08-12  8:44     ` Laurent Vivier
2015-08-12  8:52       ` Andreas Schwab
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 06/30] m68k: REG() macro cleanup Laurent Vivier
2015-08-12  4:11   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 07/30] m68k: allow to update flags with operation on words and bytes Laurent Vivier
2015-08-12  4:28   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 08/30] m68k: update CPU flags management Laurent Vivier
2015-08-12  5:12   ` Richard Henderson
2015-08-12 20:56     ` Laurent Vivier
2015-08-12 21:19       ` Richard Henderson
2015-08-12 21:21         ` Laurent Vivier
2015-08-13 18:09     ` Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 09/30] m68k: add X flag helpers Laurent Vivier
2015-08-12  5:18   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 10/30] m68k: tst bugfix Laurent Vivier
2015-08-12  5:18   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 11/30] m68k: improve clr/moveq Laurent Vivier
2015-08-12  5:20   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 12/30] m68k: Manage divw overflow Laurent Vivier
2015-08-12  6:03   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 13/30] m68k: set Z and N on divu/muls overflow as a real 68040 Laurent Vivier
2015-08-12  6:29   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 14/30] m68k: allow adda/suba to add/sub word Laurent Vivier
2015-08-12  7:32   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 15/30] m68k: add more modes to movem Laurent Vivier
2015-08-12  7:54   ` Richard Henderson
2015-08-12  8:07     ` Andreas Schwab
2015-08-12 15:13       ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 16/30] m68k: Add all access modes and data sizes to some 680x0 instructions Laurent Vivier
2015-08-12 16:25   ` Richard Henderson
2015-08-12 16:27   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 17/30] m68k: ori/andi/subi/addi/eori/cmpi can modify SR/CCR Laurent Vivier
2015-08-12 16:44   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 18/30] m68k: addq/subq can work with all the data sizes Laurent Vivier
2015-08-12 16:48   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 19/30] m68k: add cmpm Laurent Vivier
2015-08-12 17:00   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 20/30] m68k: add exg Laurent Vivier
2015-08-12 17:05   ` Richard Henderson
2015-08-12 22:43     ` Laurent Vivier
2015-08-12 23:09       ` Richard Henderson
2015-08-12 23:10         ` Laurent Vivier
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 21/30] m68k: add bkpt Laurent Vivier
2015-08-12 17:07   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 22/30] m68k: add cas instruction Laurent Vivier
2015-08-12 17:14   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 23/30] m68k: add linkl Laurent Vivier
2015-08-12 17:33   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 24/30] m68k: add DBcc and Scc (memory operand) Laurent Vivier
2015-08-12 17:49   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions Laurent Vivier
2015-08-12 17:57   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 26/30] m68k: add mull/divl Laurent Vivier
2015-08-12 18:36   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 27/30] m68k: add addx/subx/negx Laurent Vivier
2015-08-12 18:46   ` Richard Henderson
2015-08-13  0:11     ` Laurent Vivier
2015-08-13  2:23       ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 28/30] m68k: shift/rotate bytes and words Laurent Vivier
2015-08-12 19:11   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 29/30] m68k: add rol/rox/ror/roxr Laurent Vivier
2015-08-12 19:40   ` Richard Henderson
2015-08-09 20:13 ` [Qemu-devel] [PATCH for-2.5 30/30] m68k: add bitfield instructions Laurent Vivier
2015-08-12 21:05   ` Richard Henderson [this message]
2015-08-13  2:22 ` [Qemu-devel] [PATCH for-2.5 00/30] 680x0 instructions emulation Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55CBB505.8010805@twiddle.net \
    --to=rth@twiddle.net \
    --cc=gerg@uclinux.org \
    --cc=laurent@vivier.eu \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=schwab@linux-m68k.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).