Patchwork microblaze: Add support for the clz insn

login
register
mail settings
Submitter Edgar Iglesias
Date Jan. 10, 2012, 10:27 a.m.
Message ID <1326191247-14880-1-git-send-email-edgar.iglesias@gmail.com>
Download mbox | patch
Permalink /patch/135250/
State New
Headers show

Comments

Edgar Iglesias - Jan. 10, 2012, 10:27 a.m.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
 target-microblaze/helper.h    |    1 +
 target-microblaze/op_helper.c |   11 +++++++++++
 target-microblaze/translate.c |   11 +++++++++++
 3 files changed, 23 insertions(+), 0 deletions(-)
Edgar Iglesias - Jan. 10, 2012, 3:16 p.m.
Forgot to CC Lars on this one.

Also note that this patch has tab issues due to the ETRAX DMA model beeing
written prior to CodingStyle.

Cheers


On Tue, Jan 10, 2012 at 11:27:27AM +0100, Edgar E. Iglesias wrote:
> From: Lars Persson <larper@axis.com>
> 
> - Send EOP flags to the out channels.
> - Send data descriptor metadata to the out channels.
> 
> Signed-off-by: Lars Persson <larper@axis.com>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
> ---
>  hw/etraxfs_dma.c |   28 ++++++++++++++++++++++------
>  hw/etraxfs_dma.h |   13 ++++++++++---
>  hw/etraxfs_eth.c |    2 +-
>  3 files changed, 33 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c
> index d2bd584..332525c 100644
> --- a/hw/etraxfs_dma.c
> +++ b/hw/etraxfs_dma.c
> @@ -401,15 +401,29 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
>  	uint32_t saved_data_buf;
>  	unsigned char buf[2 * 1024];
>  
> +	struct dma_context_metadata meta;
> +	bool send_context = true;
> +
>  	if (ctrl->channels[c].eol)
>  		return 0;
>  
>  	do {
> +		bool out_eop;
>  		D(printf("ch=%d buf=%x after=%x\n",
>  			 c,
>  			 (uint32_t)ctrl->channels[c].current_d.buf,
>  			 (uint32_t)ctrl->channels[c].current_d.after));
>  
> +		if (send_context) {
> +			if (ctrl->channels[c].client->client.metadata_push) {
> +				meta.metadata = ctrl->channels[c].current_d.md;
> +				ctrl->channels[c].client->client.metadata_push(
> +					ctrl->channels[c].client->client.opaque,
> +					&meta);
> +			}
> +			send_context = false;
> +		}
> +
>  		channel_load_d(ctrl, c);
>  		saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
>  		len = (uint32_t)(unsigned long)
> @@ -420,13 +434,17 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
>  			len = sizeof buf;
>  		cpu_physical_memory_read (saved_data_buf, buf, len);
>  
> -		D(printf("channel %d pushes %x %u bytes\n", c, 
> -			 saved_data_buf, len));
> +		out_eop = ((saved_data_buf + len) ==
> +		           ctrl->channels[c].current_d.after) &&
> +			ctrl->channels[c].current_d.out_eop;
> +
> +		D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
> +		         saved_data_buf, len, out_eop));
>  
>  		if (ctrl->channels[c].client->client.push)
>  			ctrl->channels[c].client->client.push(
>  				ctrl->channels[c].client->client.opaque,
> -				buf, len);
> +				buf, len, out_eop);
>  		else
>  			printf("WARNING: DMA ch%d dataloss,"
>  			       " no attached client.\n", c);
> @@ -437,11 +455,9 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
>  				ctrl->channels[c].current_d.after) {
>  			/* Done. Step to next.  */
>  			if (ctrl->channels[c].current_d.out_eop) {
> -				/* TODO: signal eop to the client.  */
> -				D(printf("signal eop\n"));
> +				send_context = true;
>  			}
>  			if (ctrl->channels[c].current_d.intr) {
> -				/* TODO: signal eop to the client.  */
>  				/* data intr.  */
>  				D(printf("signal intr %d eol=%d\n",
>  					len, ctrl->channels[c].current_d.eol));
> diff --git a/hw/etraxfs_dma.h b/hw/etraxfs_dma.h
> index 96408ab..021c52a 100644
> --- a/hw/etraxfs_dma.h
> +++ b/hw/etraxfs_dma.h
> @@ -1,3 +1,8 @@
> +struct dma_context_metadata {
> +	/* data descriptor md */
> +	uint16_t metadata;
> +};
> +
>  struct etraxfs_dma_client
>  {
>  	/* DMA controller. */
> @@ -5,10 +10,12 @@ struct etraxfs_dma_client
>  	void *ctrl;
>  
>  	/* client.  */
> -	struct
> -	{
> -		int (*push)(void *opaque, unsigned char *buf, int len);
> +	struct {
> +		int (*push)(void *opaque, unsigned char *buf,
> +		            int len, bool eop);
>  		void (*pull)(void *opaque);
> +		void (*metadata_push)(void *opaque,
> +		                      const struct dma_context_metadata *md);
>  		void *opaque;
>  	} client;
>  };
> diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
> index b525258..5afa55f 100644
> --- a/hw/etraxfs_eth.c
> +++ b/hw/etraxfs_eth.c
> @@ -540,7 +540,7 @@ static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
>          return size;
>  }
>  
> -static int eth_tx_push(void *opaque, unsigned char *buf, int len)
> +static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop)
>  {
>  	struct fs_eth *eth = opaque;
>  
> -- 
> 1.7.3.4
> 
>
Peter Maydell - Jan. 10, 2012, 3:37 p.m.
On 10 January 2012 10:27, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> +uint32_t helper_clz(uint32_t t0)
> +{
> +    if (t0 == 0) {
> +        return 32;
> +    }
> +    if (t0 == ~0) {
> +        return 0;
> +    }
> +    return clz32(t0);
> +}

I think clz32() handles both the 0 and 0xffffffff cases correctly,
so they don't need special-casing.

-- PMM
Edgar Iglesias - Jan. 10, 2012, 3:41 p.m.
On Tue, Jan 10, 2012 at 03:37:51PM +0000, Peter Maydell wrote:
> On 10 January 2012 10:27, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> > +uint32_t helper_clz(uint32_t t0)
> > +{
> > +    if (t0 == 0) {
> > +        return 32;
> > +    }
> > +    if (t0 == ~0) {
> > +        return 0;
> > +    }
> > +    return clz32(t0);
> > +}
> 
> I think clz32() handles both the 0 and 0xffffffff cases correctly,
> so they don't need special-casing.

That seems to be the case, I'll fix that, thanks.

Cheers
Richard Henderson - Jan. 10, 2012, 11:19 p.m.
On 01/10/2012 09:27 PM, Edgar E. Iglesias wrote:
> +++ b/target-microblaze/helper.h
> @@ -5,6 +5,7 @@ DEF_HELPER_0(debug, void)
>  DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
>  DEF_HELPER_2(cmp, i32, i32, i32)
>  DEF_HELPER_2(cmpu, i32, i32, i32)
> +DEF_HELPER_1(clz, i32, i32)

Use DEF_HELPER_FLAGS_1 with PURE|CONST, since the function examines 
nothing but its arguments.


r~
Edgar Iglesias - Jan. 10, 2012, 11:20 p.m.
On Wed, Jan 11, 2012 at 10:19:19AM +1100, Richard Henderson wrote:
> On 01/10/2012 09:27 PM, Edgar E. Iglesias wrote:
> > +++ b/target-microblaze/helper.h
> > @@ -5,6 +5,7 @@ DEF_HELPER_0(debug, void)
> >  DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
> >  DEF_HELPER_2(cmp, i32, i32, i32)
> >  DEF_HELPER_2(cmpu, i32, i32, i32)
> > +DEF_HELPER_1(clz, i32, i32)
> 
> Use DEF_HELPER_FLAGS_1 with PURE|CONST, since the function examines 
> nothing but its arguments.

Yep thank, noticed that when I changed the helper today :)

Cheers

Patch

diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index b92aa34..420ff3b 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -5,6 +5,7 @@  DEF_HELPER_0(debug, void)
 DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
 DEF_HELPER_2(cmp, i32, i32, i32)
 DEF_HELPER_2(cmpu, i32, i32, i32)
+DEF_HELPER_1(clz, i32, i32)
 
 DEF_HELPER_2(divs, i32, i32, i32)
 DEF_HELPER_2(divu, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 7433cec..fe38b7b 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -165,6 +165,17 @@  uint32_t helper_cmpu(uint32_t a, uint32_t b)
     return t;
 }
 
+uint32_t helper_clz(uint32_t t0)
+{
+    if (t0 == 0) {
+        return 32;
+    }
+    if (t0 == ~0) {
+        return 0;
+    }
+    return clz32(t0);
+}
+
 uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
 {
     uint32_t ncf;
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index d7f513d..f4e6f30 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -809,6 +809,17 @@  static void dec_bit(DisasContext *dc)
                 return;
             }
             break;
+        case 0xe0:
+            if ((dc->tb_flags & MSR_EE_FLAG)
+                && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+                && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
+                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+                t_gen_raise_exception(dc, EXCP_HW_EXCP);
+            }
+            if (dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR) {
+                gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
+            }
+            break;
         default:
             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
                      dc->pc, op, dc->rd, dc->ra, dc->rb);