Patchwork (updated) Fix extlh instruction on Alpha

login
register
mail settings
Submitter Vince Weaver
Date Aug. 7, 2009, 9:35 p.m.
Message ID <20090807173221.X10097@stanley.csl.cornell.edu>
Download mbox | patch
Permalink /patch/30987/
State Superseded
Headers show

Comments

Vince Weaver - Aug. 7, 2009, 9:35 p.m.
This patch is the same as the one previously posted, but it uses
tcg_temp_local_new() at the suggestion of Filip Navara.

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 test-case 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"

Patch

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1fc5119..4219916 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();
+            tmp1 = tcg_temp_local_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 */