Patchwork Fix extlh instruction on Alpha

login
register
mail settings
Submitter Vince Weaver
Date Aug. 5, 2009, 3:26 a.m.
Message ID <20090804231934.G93384@stanley.csl.cornell.edu>
Download mbox | patch
Permalink /patch/30763/
State Superseded
Headers show

Comments

Vince Weaver - Aug. 5, 2009, 3:26 a.m.
Hello

The extlh instruction on Alpha currently doesn't work properly.
It's a combination of a cut/paste bug (16 where it should be 32) as well 
as a "shift by 64" bug.

Below is a patch that fixes the problem, and attached is a test case that 
exhibits the bug.  The program should print a 4-char wide sliding window 
across the test string; without the patch this fails.

Vince

Signed-off-by: Vince Weaver <vince@csl.cornell.edu>
# uldl.s by Vince Weaver
# This shows a bug with Qemu in handling of the extlh instruction
#  assemble with     "as -o uldl.o uldl.s"
#  link with         "ld -o uldl uldl.o"



# syscall numbers

.equ SYSCALL_EXIT,1	
.equ SYSCALL_WRITE,4
		
.equ STDIN,0
.equ STDOUT,1
.equ STDERR,2	
	
	
	.globl _start
_start:
	
	br      $27,0           # fake branch, to grab the location
	                        # of our entry point
	ldgp    $gp,0($27)      # load the GP proper for our entry point
				# this does automagic stuff...
				# gp is used for 64-bit jumps and constants
				# so if you use "la" and the like it will
				# load from gp for you. 
	

	lda     $17,title	  # load title
	br	$26,write_stdout  # print it
	
	lda	$17,test_string	  # load test string
	br	$26,write_stdout  # print it

	lda	$13,four_bytes	  # point $13 to our 32-bit wide
				  # test location
				  
	lda	$11,test_string	  # point $11 to beginning of test string
	addq	$11,20,$14	  # repeat 20 times
	
load_loop:	
	# uldl	$12,0($11)	  # load 32-bits from it
	# This expands to the following

.set noat
	lda     $28,0($11)
	ldq_u   $23,0($28)
	ldq_u   $24,3($28)
	extll   $23,$28,$23	
	extlh   $24,$28,$24	
	or      $23,$24,$12
	sextl   $12,$12
.set at

	stl	$12,0($13)	  # store to 4-byte location
	lda	$17,four_bytes	  # point to it
	br	$26,write_stdout  # print 4 chars

	addq	$11,1,$11
	
	cmpeq	$11,$14,$1
	beq	$1,load_loop

	#================================
	# Exit
	#================================
exit:		
        clr	$16			# 0 exit value
        mov	SYSCALL_EXIT,$0		# put the exit syscall number in v0
        callsys				# and exit
	
	#================================
	# WRITE_STDOUT
	#================================
	# $17 has string
	# $1 is trashed
	
write_stdout:	
	ldil	$0,SYSCALL_WRITE	# Write syscall in $0
	ldil	$16,STDOUT		# 1 in $16 (stdout)
	clr	$18			# 0 (count) in $18
	
str_loop1:
	addq	$17,$18,$1		# offset in $1
	ldbu    $1,0($1)		# load byte
	addq	$18,1,$18		# increment pointer
	bne	$1,str_loop1		# if not nul, repeat
	
	subq	$18,1,$18		# correct count
	callsys				# Make syscall
	
	ret	$26			# return
			
.data

.align 3

four_bytes: .ascii "RPLC\n\0"
.align 3
eight_bytes:	.ascii "REPLACE!\n\0"

title:	.ascii "ULDL Test\n\0"
linefeed: .ascii "\n\0"
.align 3
test_string:  .ascii "The quick brown fox jumped over the lazy dog\n\0"
Filip Navara - Aug. 5, 2009, 6:05 a.m.
On Wed, Aug 5, 2009 at 5:26 AM, Vince Weaver<vince@csl.cornell.edu> wrote:
> Hello
>
> The extlh instruction on Alpha currently doesn't work properly.
> It's a combination of a cut/paste bug (16 where it should be 32) as well
> as a "shift by 64" bug.
>
> Below is a patch that fixes the problem, and attached is a test case that
> exhibits the bug.  The program should print a 4-char wide sliding window
> across the test string; without the patch this fails.
>
> Vince
>
> Signed-off-by: Vince Weaver <vince@csl.cornell.edu>
>
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index 1fc5119..2a681b0 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -526,14 +526,24 @@ static always_inline void gen_ext_h(void (*tcg_gen_ext_i64)(TCGv t0, TCGv t1),
>             else
>                 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
>         } else {
> +            int l1;
>             TCGv tmp1, tmp2;
>             tmp1 = tcg_temp_new();

This should be tcg_temp_local_new since you added a branch instruction
and normal temporary variables are live in a basic block (eg. not
across a branch).

> +            l1 = gen_new_label();
> +
>             tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
>             tcg_gen_shli_i64(tmp1, tmp1, 3);
> +
> +            tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
> +            tcg_gen_brcondi_i64(TCG_COND_EQ, tmp1, 0, l1);
> +
>             tmp2 = tcg_const_i64(64);
>             tcg_gen_sub_i64(tmp1, tmp2, tmp1);
>             tcg_temp_free(tmp2);
>             tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
> +
> +            gen_set_label(l1);
> +
>             tcg_temp_free(tmp1);
>         }
>         if (tcg_gen_ext_i64)
> @@ -1320,7 +1330,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>             break;
>         case 0x6A:
>             /* EXTLH */
> -            gen_ext_h(&tcg_gen_ext16u_i64, ra, rb, rc, islit, lit);
> +            gen_ext_h(&tcg_gen_ext32u_i64, ra, rb, rc, islit, lit);
>             break;
>         case 0x72:
>             /* MSKQH */

Best regards,
Filip Navara

Patch

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1fc5119..2a681b0 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -526,14 +526,24 @@  static always_inline void gen_ext_h(void (*tcg_gen_ext_i64)(TCGv t0, TCGv t1),
             else
                 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
         } else {
+            int l1;
             TCGv tmp1, tmp2;
             tmp1 = tcg_temp_new();
+            l1 = gen_new_label();
+
             tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
             tcg_gen_shli_i64(tmp1, tmp1, 3);
+
+            tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
+            tcg_gen_brcondi_i64(TCG_COND_EQ, tmp1, 0, l1);
+
             tmp2 = tcg_const_i64(64);
             tcg_gen_sub_i64(tmp1, tmp2, tmp1);
             tcg_temp_free(tmp2);
             tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], tmp1);
+
+            gen_set_label(l1);
+
             tcg_temp_free(tmp1);
         }
         if (tcg_gen_ext_i64)
@@ -1320,7 +1330,7 @@  static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
             break;
         case 0x6A:
             /* EXTLH */
-            gen_ext_h(&tcg_gen_ext16u_i64, ra, rb, rc, islit, lit);
+            gen_ext_h(&tcg_gen_ext32u_i64, ra, rb, rc, islit, lit);
             break;
         case 0x72:
             /* MSKQH */