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~
next prev parent 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).