aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tcg')
-rw-r--r--tests/tcg/Makefile145
-rw-r--r--tests/tcg/alpha/Makefile35
-rw-r--r--tests/tcg/alpha/crt.s26
-rw-r--r--tests/tcg/alpha/hello-alpha.c5
-rw-r--r--tests/tcg/alpha/test-cond.c87
-rw-r--r--tests/tcg/alpha/test-ovf.c29
-rw-r--r--tests/tcg/cris/.gdbinit11
-rw-r--r--tests/tcg/cris/Makefile155
-rw-r--r--tests/tcg/cris/README1
-rw-r--r--tests/tcg/cris/check_abs.c40
-rw-r--r--tests/tcg/cris/check_addc.c58
-rw-r--r--tests/tcg/cris/check_addcm.c85
-rw-r--r--tests/tcg/cris/check_addi.s57
-rw-r--r--tests/tcg/cris/check_addiv32.s62
-rw-r--r--tests/tcg/cris/check_addm.s96
-rw-r--r--tests/tcg/cris/check_addo.c125
-rw-r--r--tests/tcg/cris/check_addoq.c44
-rw-r--r--tests/tcg/cris/check_addq.s47
-rw-r--r--tests/tcg/cris/check_addr.s96
-rw-r--r--tests/tcg/cris/check_addxc.s91
-rw-r--r--tests/tcg/cris/check_addxm.s106
-rw-r--r--tests/tcg/cris/check_addxr.s96
-rw-r--r--tests/tcg/cris/check_andc.s80
-rw-r--r--tests/tcg/cris/check_andm.s90
-rw-r--r--tests/tcg/cris/check_andq.s46
-rw-r--r--tests/tcg/cris/check_andr.s95
-rw-r--r--tests/tcg/cris/check_asr.s230
-rw-r--r--tests/tcg/cris/check_ba.s93
-rw-r--r--tests/tcg/cris/check_bas.s102
-rw-r--r--tests/tcg/cris/check_bcc.s197
-rw-r--r--tests/tcg/cris/check_bound.c142
-rw-r--r--tests/tcg/cris/check_boundc.s101
-rw-r--r--tests/tcg/cris/check_boundr.s125
-rw-r--r--tests/tcg/cris/check_btst.s96
-rw-r--r--tests/tcg/cris/check_clearfv32.s19
-rw-r--r--tests/tcg/cris/check_clrjmp1.s36
-rw-r--r--tests/tcg/cris/check_cmp-2.s15
-rw-r--r--tests/tcg/cris/check_cmpc.s86
-rw-r--r--tests/tcg/cris/check_cmpm.s96
-rw-r--r--tests/tcg/cris/check_cmpq.s75
-rw-r--r--tests/tcg/cris/check_cmpr.s102
-rw-r--r--tests/tcg/cris/check_cmpxc.s92
-rw-r--r--tests/tcg/cris/check_cmpxm.s106
-rw-r--r--tests/tcg/cris/check_dstep.s42
-rw-r--r--tests/tcg/cris/check_ftag.c37
-rw-r--r--tests/tcg/cris/check_gcctorture_pr28634-1.c15
-rw-r--r--tests/tcg/cris/check_gcctorture_pr28634.c15
-rw-r--r--tests/tcg/cris/check_glibc_kernelversion.c116
-rw-r--r--tests/tcg/cris/check_hello.c7
-rw-r--r--tests/tcg/cris/check_int64.c47
-rw-r--r--tests/tcg/cris/check_jsr.s85
-rw-r--r--tests/tcg/cris/check_lapc.s78
-rw-r--r--tests/tcg/cris/check_lsl.s217
-rw-r--r--tests/tcg/cris/check_lsr.s218
-rw-r--r--tests/tcg/cris/check_lz.c49
-rw-r--r--tests/tcg/cris/check_mapbrk.c39
-rw-r--r--tests/tcg/cris/check_mcp.s49
-rw-r--r--tests/tcg/cris/check_mmap1.c48
-rw-r--r--tests/tcg/cris/check_mmap2.c48
-rw-r--r--tests/tcg/cris/check_mmap3.c33
-rw-r--r--tests/tcg/cris/check_movdelsr1.s33
-rw-r--r--tests/tcg/cris/check_movecr.s37
-rw-r--r--tests/tcg/cris/check_movei.s50
-rw-r--r--tests/tcg/cris/check_movemr.s78
-rw-r--r--tests/tcg/cris/check_movemrv32.s96
-rw-r--r--tests/tcg/cris/check_moveq.c51
-rw-r--r--tests/tcg/cris/check_mover.s28
-rw-r--r--tests/tcg/cris/check_moverm.s45
-rw-r--r--tests/tcg/cris/check_movmp.s131
-rw-r--r--tests/tcg/cris/check_movpmv32.s35
-rw-r--r--tests/tcg/cris/check_movpr.s28
-rw-r--r--tests/tcg/cris/check_movprv32.s21
-rw-r--r--tests/tcg/cris/check_movscr.s29
-rw-r--r--tests/tcg/cris/check_movsm.s44
-rw-r--r--tests/tcg/cris/check_movsr.s46
-rw-r--r--tests/tcg/cris/check_movucr.s33
-rw-r--r--tests/tcg/cris/check_movum.s40
-rw-r--r--tests/tcg/cris/check_movur.s45
-rw-r--r--tests/tcg/cris/check_mulv32.s51
-rw-r--r--tests/tcg/cris/check_mulx.s246
-rw-r--r--tests/tcg/cris/check_neg.s104
-rw-r--r--tests/tcg/cris/check_not.s31
-rw-r--r--tests/tcg/cris/check_openpf1.c38
-rw-r--r--tests/tcg/cris/check_openpf2.c16
-rw-r--r--tests/tcg/cris/check_openpf3.c49
-rw-r--r--tests/tcg/cris/check_openpf4.c5
-rw-r--r--tests/tcg/cris/check_openpf5.c56
-rw-r--r--tests/tcg/cris/check_orc.s71
-rw-r--r--tests/tcg/cris/check_orm.s75
-rw-r--r--tests/tcg/cris/check_orq.s41
-rw-r--r--tests/tcg/cris/check_orr.s84
-rw-r--r--tests/tcg/cris/check_ret.s25
-rw-r--r--tests/tcg/cris/check_scc.s95
-rw-r--r--tests/tcg/cris/check_settls1.c45
-rw-r--r--tests/tcg/cris/check_sigalrm.c26
-rw-r--r--tests/tcg/cris/check_stat1.c16
-rw-r--r--tests/tcg/cris/check_stat2.c20
-rw-r--r--tests/tcg/cris/check_stat3.c25
-rw-r--r--tests/tcg/cris/check_stat4.c27
-rw-r--r--tests/tcg/cris/check_subc.s87
-rw-r--r--tests/tcg/cris/check_subm.s96
-rw-r--r--tests/tcg/cris/check_subq.s52
-rw-r--r--tests/tcg/cris/check_subr.s102
-rw-r--r--tests/tcg/cris/check_swap.c76
-rw-r--r--tests/tcg/cris/check_time1.c46
-rw-r--r--tests/tcg/cris/check_time2.c18
-rw-r--r--tests/tcg/cris/check_xarith.s72
-rw-r--r--tests/tcg/cris/crisutils.h71
-rw-r--r--tests/tcg/cris/crt.s13
-rw-r--r--tests/tcg/cris/sys.c51
-rw-r--r--tests/tcg/cris/sys.h16
-rw-r--r--tests/tcg/cris/testutils.inc117
-rw-r--r--tests/tcg/hello-arm.c113
-rw-r--r--tests/tcg/hello-i386.c26
-rw-r--r--tests/tcg/hello-mips.c64
-rw-r--r--tests/tcg/linux-test.c537
-rw-r--r--tests/tcg/lm32/Makefile102
-rw-r--r--tests/tcg/lm32/crt.S84
-rw-r--r--tests/tcg/lm32/linker.ld55
-rw-r--r--tests/tcg/lm32/macros.inc79
-rw-r--r--tests/tcg/lm32/test_add.S75
-rw-r--r--tests/tcg/lm32/test_addi.S56
-rw-r--r--tests/tcg/lm32/test_and.S45
-rw-r--r--tests/tcg/lm32/test_andhi.S35
-rw-r--r--tests/tcg/lm32/test_andi.S35
-rw-r--r--tests/tcg/lm32/test_b.S13
-rw-r--r--tests/tcg/lm32/test_be.S48
-rw-r--r--tests/tcg/lm32/test_bg.S78
-rw-r--r--tests/tcg/lm32/test_bge.S78
-rw-r--r--tests/tcg/lm32/test_bgeu.S78
-rw-r--r--tests/tcg/lm32/test_bgu.S78
-rw-r--r--tests/tcg/lm32/test_bi.S23
-rw-r--r--tests/tcg/lm32/test_bne.S48
-rw-r--r--tests/tcg/lm32/test_break.S20
-rw-r--r--tests/tcg/lm32/test_bret.S38
-rw-r--r--tests/tcg/lm32/test_call.S16
-rw-r--r--tests/tcg/lm32/test_calli.S15
-rw-r--r--tests/tcg/lm32/test_cmpe.S40
-rw-r--r--tests/tcg/lm32/test_cmpei.S35
-rw-r--r--tests/tcg/lm32/test_cmpg.S64
-rw-r--r--tests/tcg/lm32/test_cmpge.S64
-rw-r--r--tests/tcg/lm32/test_cmpgei.S55
-rw-r--r--tests/tcg/lm32/test_cmpgeu.S64
-rw-r--r--tests/tcg/lm32/test_cmpgeui.S55
-rw-r--r--tests/tcg/lm32/test_cmpgi.S55
-rw-r--r--tests/tcg/lm32/test_cmpgu.S64
-rw-r--r--tests/tcg/lm32/test_cmpgui.S55
-rw-r--r--tests/tcg/lm32/test_cmpne.S40
-rw-r--r--tests/tcg/lm32/test_cmpnei.S35
-rw-r--r--tests/tcg/lm32/test_divu.S29
-rw-r--r--tests/tcg/lm32/test_eret.S38
-rw-r--r--tests/tcg/lm32/test_lb.S45
-rw-r--r--tests/tcg/lm32/test_lbu.S45
-rw-r--r--tests/tcg/lm32/test_lh.S45
-rw-r--r--tests/tcg/lm32/test_lhu.S45
-rw-r--r--tests/tcg/lm32/test_lw.S30
-rw-r--r--tests/tcg/lm32/test_modu.S35
-rw-r--r--tests/tcg/lm32/test_mul.S70
-rw-r--r--tests/tcg/lm32/test_muli.S45
-rw-r--r--tests/tcg/lm32/test_nor.S51
-rw-r--r--tests/tcg/lm32/test_nori.S35
-rw-r--r--tests/tcg/lm32/test_or.S51
-rw-r--r--tests/tcg/lm32/test_orhi.S35
-rw-r--r--tests/tcg/lm32/test_ori.S35
-rw-r--r--tests/tcg/lm32/test_ret.S14
-rw-r--r--tests/tcg/lm32/test_sb.S30
-rw-r--r--tests/tcg/lm32/test_scall.S20
-rw-r--r--tests/tcg/lm32/test_sextb.S20
-rw-r--r--tests/tcg/lm32/test_sexth.S20
-rw-r--r--tests/tcg/lm32/test_sh.S30
-rw-r--r--tests/tcg/lm32/test_sl.S45
-rw-r--r--tests/tcg/lm32/test_sli.S30
-rw-r--r--tests/tcg/lm32/test_sr.S57
-rw-r--r--tests/tcg/lm32/test_sri.S40
-rw-r--r--tests/tcg/lm32/test_sru.S57
-rw-r--r--tests/tcg/lm32/test_srui.S40
-rw-r--r--tests/tcg/lm32/test_sub.S75
-rw-r--r--tests/tcg/lm32/test_sw.S35
-rw-r--r--tests/tcg/lm32/test_xnor.S51
-rw-r--r--tests/tcg/lm32/test_xnori.S35
-rw-r--r--tests/tcg/lm32/test_xor.S51
-rw-r--r--tests/tcg/lm32/test_xori.S35
-rw-r--r--tests/tcg/pi_10.combin0 -> 54 bytes
-rw-r--r--tests/tcg/runcom.c192
-rw-r--r--tests/tcg/sha1.c240
-rw-r--r--tests/tcg/test-arm-iwmmxt.s49
-rw-r--r--tests/tcg/test-i386-code16.S79
-rw-r--r--tests/tcg/test-i386-muldiv.h76
-rw-r--r--tests/tcg/test-i386-shift.h185
-rw-r--r--tests/tcg/test-i386-ssse3.c57
-rw-r--r--tests/tcg/test-i386-vm86.S103
-rw-r--r--tests/tcg/test-i386.c2764
-rw-r--r--tests/tcg/test-i386.h152
-rw-r--r--tests/tcg/test-mmap.c476
-rw-r--r--tests/tcg/test_path.c160
-rw-r--r--tests/tcg/testthread.c51
-rw-r--r--tests/tcg/xtensa/Makefile75
-rw-r--r--tests/tcg/xtensa/crt.S24
-rw-r--r--tests/tcg/xtensa/linker.ld112
-rw-r--r--tests/tcg/xtensa/macros.inc68
-rw-r--r--tests/tcg/xtensa/test_b.S221
-rw-r--r--tests/tcg/xtensa/test_bi.S103
-rw-r--r--tests/tcg/xtensa/test_boolean.S23
-rw-r--r--tests/tcg/xtensa/test_bz.S57
-rw-r--r--tests/tcg/xtensa/test_clamps.S42
-rw-r--r--tests/tcg/xtensa/test_fail.S9
-rw-r--r--tests/tcg/xtensa/test_interrupt.S194
-rw-r--r--tests/tcg/xtensa/test_loop.S77
-rw-r--r--tests/tcg/xtensa/test_mac16.S243
-rw-r--r--tests/tcg/xtensa/test_max.S81
-rw-r--r--tests/tcg/xtensa/test_min.S81
-rw-r--r--tests/tcg/xtensa/test_mmu.S318
-rw-r--r--tests/tcg/xtensa/test_mul16.S83
-rw-r--r--tests/tcg/xtensa/test_mul32.S20
-rw-r--r--tests/tcg/xtensa/test_nsa.S59
-rw-r--r--tests/tcg/xtensa/test_pipeline.S157
-rw-r--r--tests/tcg/xtensa/test_quo.S147
-rw-r--r--tests/tcg/xtensa/test_rem.S147
-rw-r--r--tests/tcg/xtensa/test_rst0.S148
-rw-r--r--tests/tcg/xtensa/test_sar.S111
-rw-r--r--tests/tcg/xtensa/test_sext.S69
-rw-r--r--tests/tcg/xtensa/test_shift.S206
-rw-r--r--tests/tcg/xtensa/test_timer.S178
-rw-r--r--tests/tcg/xtensa/test_windowed.S302
-rw-r--r--tests/tcg/xtensa/vectors.S39
225 files changed, 19259 insertions, 0 deletions
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
new file mode 100644
index 0000000000..15e36a208c
--- /dev/null
+++ b/tests/tcg/Makefile
@@ -0,0 +1,145 @@
+-include ../config-host.mak
+-include $(SRC_PATH)/rules.mak
+
+$(call set-vpath, $(SRC_PATH)/tests)
+
+QEMU=../i386-linux-user/qemu-i386
+QEMU_X86_64=../x86_64-linux-user/qemu-x86_64
+CC_X86_64=$(CC_I386) -m64
+
+QEMU_INCLUDES += -I..
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
+#CFLAGS+=-msse2
+LDFLAGS=
+
+# TODO: automatically detect ARM and MIPS compilers, and run those too
+
+# runcom maps page 0, so it requires root privileges
+# also, pi_10.com runs indefinitely
+
+I386_TESTS=hello-i386 \
+ linux-test \
+ testthread \
+ sha1-i386 \
+ test-i386 \
+ test-mmap \
+ # runcom
+
+# native i386 compilers sometimes are not biarch. assume cross-compilers are
+ifneq ($(ARCH),i386)
+I386_TESTS+=run-test-x86_64
+endif
+
+TESTS = test_path
+ifneq ($(call find-in-path, $(CC_I386)),)
+TESTS += $(I386_TESTS)
+endif
+
+all: $(patsubst %,run-%,$(TESTS))
+
+# rules to run tests
+
+.PHONY: $(patsubst %,run-%,$(TESTS))
+
+run-%: %
+ -$(QEMU) ./$*
+
+run-hello-i386: hello-i386
+run-linux-test: linux-test
+run-testthread: testthread
+run-sha1-i386: sha1-i386
+
+run-test-i386: test-i386
+ ./test-i386 > test-i386.ref
+ -$(QEMU) test-i386 > test-i386.out
+ @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
+
+run-test-x86_64: test-x86_64
+ ./test-x86_64 > test-x86_64.ref
+ -$(QEMU_X86_64) test-x86_64 > test-x86_64.out
+ @if diff -u test-x86_64.ref test-x86_64.out ; then echo "Auto Test OK"; fi
+
+run-test-mmap: test-mmap
+ -$(QEMU) ./test-mmap
+ -$(QEMU) -p 8192 ./test-mmap 8192
+ -$(QEMU) -p 16384 ./test-mmap 16384
+ -$(QEMU) -p 32768 ./test-mmap 32768
+
+run-runcom: runcom
+ -$(QEMU) ./runcom $(SRC_PATH)/tests/pi_10.com
+
+run-test_path: test_path
+ ./test_path
+
+# rules to compile tests
+
+test_path: test_path.o
+test_path.o: test_path.c
+
+hello-i386: hello-i386.c
+ $(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
+ strip $@
+
+testthread: testthread.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread
+
+# i386/x86_64 emulation test (test various opcodes) */
+test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
+ test-i386.h test-i386-shift.h test-i386-muldiv.h
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ \
+ $(<D)/test-i386.c $(<D)/test-i386-code16.S $(<D)/test-i386-vm86.S -lm
+
+test-x86_64: test-i386.c \
+ test-i386.h test-i386-shift.h test-i386-muldiv.h
+ $(CC_X86_64) $(CFLAGS) $(LDFLAGS) -o $@ $(<D)/test-i386.c -lm
+
+# generic Linux and CPU test
+linux-test: linux-test.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm
+
+# vm86 test
+runcom: runcom.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+test-mmap: test-mmap.c
+ $(CC_I386) -m32 $(CFLAGS) -Wall -O2 $(LDFLAGS) -o $@ $<
+
+# speed test
+sha1-i386: sha1.c
+ $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+sha1: sha1.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+speed: sha1 sha1-i386
+ time ./sha1
+ time $(QEMU) ./sha1-i386
+
+# arm test
+hello-arm: hello-arm.o
+ arm-linux-ld -o $@ $<
+
+hello-arm.o: hello-arm.c
+ arm-linux-gcc -Wall -g -O2 -c -o $@ $<
+
+test-arm-iwmmxt: test-arm-iwmmxt.s
+ cpp < $< | arm-linux-gnu-gcc -Wall -static -march=iwmmxt -mabi=aapcs -x assembler - -o $@
+
+# MIPS test
+hello-mips: hello-mips.c
+ mips-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+hello-mipsel: hello-mips.c
+ mipsel-linux-gnu-gcc -nostdlib -static -mno-abicalls -fno-PIC -mabi=32 -Wall -Wextra -g -O2 -o $@ $<
+
+# testsuite for the CRIS port.
+test-cris:
+ $(MAKE) -C cris check
+
+# testsuite for the LM32 port.
+test-lm32:
+ $(MAKE) -C lm32 check
+
+clean:
+ rm -f *~ *.o test-i386.out test-i386.ref \
+ test-x86_64.log test-x86_64.ref qruncom $(TESTS)
diff --git a/tests/tcg/alpha/Makefile b/tests/tcg/alpha/Makefile
new file mode 100644
index 0000000000..2b1f03d048
--- /dev/null
+++ b/tests/tcg/alpha/Makefile
@@ -0,0 +1,35 @@
+CROSS=alpha-linux-gnu-
+CC=$(CROSS)gcc
+AS=$(CROSS)as
+
+SIM=../../alpha-linux-user/qemu-alpha
+
+CFLAGS=-O
+LINK=$(CC) -o $@ crt.o $< -nostdlib
+
+TESTS=test-cond test-cmov
+
+all: hello-alpha $(TESTS)
+
+hello-alpha: hello-alpha.o crt.o
+ $(LINK)
+
+test-cond: test-cond.o crt.o
+ $(LINK)
+
+test-cmov.o: test-cond.c
+ $(CC) -c $(CFLAGS) -DTEST_CMOV -o $@ $<
+
+test-cmov: test-cmov.o crt.o
+ $(LINK)
+
+test-ovf: test-ovf.o crt.o
+ $(LINK)
+
+check: $(TESTS)
+ for f in $(TESTS); do $(SIM) $$f || exit 1; done
+
+clean:
+ $(RM) *.o *~ hello-alpha $(TESTS)
+
+.PHONY: clean all check
diff --git a/tests/tcg/alpha/crt.s b/tests/tcg/alpha/crt.s
new file mode 100644
index 0000000000..31af8825bc
--- /dev/null
+++ b/tests/tcg/alpha/crt.s
@@ -0,0 +1,26 @@
+ .text
+
+ .globl _start
+ .ent _start,0
+_start:
+ .frame $15,0,$15
+ br $29,1f
+1: ldgp $29, 0($29)
+ .prologue 0
+ ldq $27,main($29) !literal!1
+ jsr $26,($27)
+ or $0,$0,$16
+ .end _start
+
+ .globl _exit
+_exit:
+ lda $0,1
+ callsys
+
+ call_pal 0
+
+ .globl write
+write:
+ lda $0,4
+ callsys
+ ret
diff --git a/tests/tcg/alpha/hello-alpha.c b/tests/tcg/alpha/hello-alpha.c
new file mode 100644
index 0000000000..79892e6522
--- /dev/null
+++ b/tests/tcg/alpha/hello-alpha.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+ write (1, "hello\n", 6);
+ return 0;
+}
diff --git a/tests/tcg/alpha/test-cond.c b/tests/tcg/alpha/test-cond.c
new file mode 100644
index 0000000000..74adffaa69
--- /dev/null
+++ b/tests/tcg/alpha/test-cond.c
@@ -0,0 +1,87 @@
+
+#ifdef TEST_CMOV
+
+#define TEST_COND(N) \
+int test_##N (long a) \
+{ \
+ int res = 1; \
+ \
+ asm ("cmov"#N" %1,$31,%0" \
+ : "+r" (res) : "r" (a)); \
+ return !res; \
+}
+
+#else
+
+#define TEST_COND(N) \
+int test_##N (long a) \
+{ \
+ int res = 1; \
+ \
+ asm ("b"#N" %1,1f\n\t" \
+ "addq $31,$31,%0\n\t" \
+ "1: unop\n" \
+ : "+r" (res) : "r" (a)); \
+ return res; \
+}
+
+#endif
+
+TEST_COND(eq)
+TEST_COND(ne)
+TEST_COND(ge)
+TEST_COND(gt)
+TEST_COND(lbc)
+TEST_COND(lbs)
+TEST_COND(le)
+TEST_COND(lt)
+
+static struct {
+ int (*func)(long);
+ long v;
+ int r;
+} vectors[] =
+ {
+ {test_eq, 0, 1},
+ {test_eq, 1, 0},
+
+ {test_ne, 0, 0},
+ {test_ne, 1, 1},
+
+ {test_ge, 0, 1},
+ {test_ge, 1, 1},
+ {test_ge, -1, 0},
+
+ {test_gt, 0, 0},
+ {test_gt, 1, 1},
+ {test_gt, -1, 0},
+
+ {test_lbc, 0, 1},
+ {test_lbc, 1, 0},
+ {test_lbc, -1, 0},
+
+ {test_lbs, 0, 0},
+ {test_lbs, 1, 1},
+ {test_lbs, -1, 1},
+
+ {test_le, 0, 1},
+ {test_le, 1, 0},
+ {test_le, -1, 1},
+
+ {test_lt, 0, 0},
+ {test_lt, 1, 0},
+ {test_lt, -1, 1},
+ };
+
+int main (void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
+ if ((*vectors[i].func)(vectors[i].v) != vectors[i].r) {
+ write(1, "Failed\n", 7);
+ return 1;
+ }
+ write(1, "OK\n", 3);
+ return 0;
+}
diff --git a/tests/tcg/alpha/test-ovf.c b/tests/tcg/alpha/test-ovf.c
new file mode 100644
index 0000000000..01c80e7525
--- /dev/null
+++ b/tests/tcg/alpha/test-ovf.c
@@ -0,0 +1,29 @@
+static long test_subqv (long a, long b)
+{
+ long res;
+
+ asm ("subq/v %1,%2,%0"
+ : "=r" (res) : "r" (a), "r" (b));
+ return res;
+}
+static struct {
+ long (*func)(long, long);
+ long a;
+ long b;
+ long r;
+} vectors[] =
+ {
+ {test_subqv, 0, 0x7d54000, 0xfffffffff82ac000L}
+ };
+
+int main (void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (vectors)/sizeof(vectors[0]); i++)
+ if ((*vectors[i].func)(vectors[i].a, vectors[i].b) != vectors[i].r) {
+ write(1, "Failed\n", 7);
+ }
+ write(1, "OK\n", 3);
+ return 0;
+}
diff --git a/tests/tcg/cris/.gdbinit b/tests/tcg/cris/.gdbinit
new file mode 100644
index 0000000000..5e8c1d32f3
--- /dev/null
+++ b/tests/tcg/cris/.gdbinit
@@ -0,0 +1,11 @@
+b main
+b _fail
+b exit
+display /i $pc
+display /x $srp
+display /x $r0
+display /x $r1
+display /x $r2
+display /x $r3
+display /x $r4
+display /t $ccs
diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
new file mode 100644
index 0000000000..b86bcadcc5
--- /dev/null
+++ b/tests/tcg/cris/Makefile
@@ -0,0 +1,155 @@
+-include ../../config-host.mak
+
+CROSS=crisv32-axis-linux-gnu-
+SIM=../../cris-linux-user/qemu-cris -L ./
+SIMG=cris-axis-linux-gnu-run --sysroot=./
+
+CC = $(CROSS)gcc
+#AS = $(CROSS)as
+AS = $(CC) -x assembler-with-cpp
+SIZE = $(CROSS)size
+LD = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+# we rely on GCC inline:ing the stuff we tell it to in many places here.
+CFLAGS = -Winline -Wall -g -O2 -static
+NOSTDFLAGS = -nostartfiles -nostdlib
+ASFLAGS += -g -Wa,-I,$(SRC_PATH)/tests/cris/
+LDLIBS =
+NOSTDLIBS = -lgcc
+
+CRT = crt.o
+SYS = sys.o
+TESTCASES += check_abs.tst
+TESTCASES += check_addc.tst
+TESTCASES += check_addcm.tst
+TESTCASES += check_addo.tst
+TESTCASES += check_addoq.tst
+TESTCASES += check_addi.tst
+TESTCASES += check_addiv32.tst
+TESTCASES += check_addm.tst
+TESTCASES += check_addr.tst
+TESTCASES += check_addq.tst
+TESTCASES += check_addxc.tst
+TESTCASES += check_addxm.tst
+TESTCASES += check_addxr.tst
+TESTCASES += check_andc.tst
+TESTCASES += check_andm.tst
+TESTCASES += check_andr.tst
+TESTCASES += check_andq.tst
+TESTCASES += check_asr.tst
+TESTCASES += check_ba.tst
+TESTCASES += check_bas.tst
+TESTCASES += check_bcc.tst
+TESTCASES += check_bound.tst
+TESTCASES += check_boundc.tst
+TESTCASES += check_boundr.tst
+TESTCASES += check_btst.tst
+TESTCASES += check_clearfv32.tst
+TESTCASES += check_cmpc.tst
+TESTCASES += check_cmpr.tst
+TESTCASES += check_cmpq.tst
+TESTCASES += check_cmpm.tst
+TESTCASES += check_cmpxc.tst
+TESTCASES += check_cmpxm.tst
+TESTCASES += check_cmp-2.tst
+TESTCASES += check_clrjmp1.tst
+TESTCASES += check_dstep.tst
+TESTCASES += check_ftag.tst
+TESTCASES += check_int64.tst
+# check_jsr is broken.
+#TESTCASES += check_jsr.tst
+TESTCASES += check_mcp.tst
+TESTCASES += check_movei.tst
+TESTCASES += check_mover.tst
+TESTCASES += check_moverm.tst
+TESTCASES += check_moveq.tst
+TESTCASES += check_movemr.tst
+TESTCASES += check_movemrv32.tst
+TESTCASES += check_movecr.tst
+TESTCASES += check_movmp.tst
+TESTCASES += check_movpr.tst
+TESTCASES += check_movprv32.tst
+TESTCASES += check_movdelsr1.tst
+TESTCASES += check_movpmv32.tst
+TESTCASES += check_movsr.tst
+TESTCASES += check_movsm.tst
+TESTCASES += check_movscr.tst
+TESTCASES += check_movur.tst
+TESTCASES += check_movum.tst
+TESTCASES += check_movucr.tst
+TESTCASES += check_mulx.tst
+TESTCASES += check_mulv32.tst
+TESTCASES += check_neg.tst
+TESTCASES += check_not.tst
+TESTCASES += check_lz.tst
+TESTCASES += check_lapc.tst
+TESTCASES += check_lsl.tst
+TESTCASES += check_lsr.tst
+TESTCASES += check_orc.tst
+TESTCASES += check_orm.tst
+TESTCASES += check_orr.tst
+TESTCASES += check_orq.tst
+TESTCASES += check_ret.tst
+TESTCASES += check_swap.tst
+TESTCASES += check_scc.tst
+TESTCASES += check_subc.tst
+TESTCASES += check_subq.tst
+TESTCASES += check_subr.tst
+TESTCASES += check_subm.tst
+TESTCASES += check_glibc_kernelversion.tst
+TESTCASES += check_xarith.tst
+
+TESTCASES += check_hello.ctst
+TESTCASES += check_stat1.ctst
+TESTCASES += check_stat2.ctst
+TESTCASES += check_stat3.ctst
+TESTCASES += check_stat4.ctst
+TESTCASES += check_openpf1.ctst
+TESTCASES += check_openpf2.ctst
+TESTCASES += check_openpf3.ctst
+TESTCASES += check_openpf4.ctst
+TESTCASES += check_openpf5.ctst
+TESTCASES += check_mapbrk.ctst
+TESTCASES += check_mmap1.ctst
+TESTCASES += check_mmap2.ctst
+TESTCASES += check_mmap3.ctst
+TESTCASES += check_sigalrm.ctst
+TESTCASES += check_time1.ctst
+TESTCASES += check_time2.ctst
+TESTCASES += check_settls1.ctst
+
+TESTCASES += check_gcctorture_pr28634-1.ctst
+#TESTCASES += check_gcctorture_pr28634.ctst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/cris/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/cris/%.s
+ $(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o
+ $(CC) $(CFLAGS) $(NOSTDFLAGS) $(LDLIBS) $(NOSTDLIBS) $(CRT) $< $(SYS) -o $@
+
+%.ctst: %.o
+ $(CC) $(CFLAGS) $(LDLIBS) $< -o $@
+
+build: $(CRT) $(SYS) $(TESTCASES)
+
+check: $(CRT) $(SYS) $(TESTCASES)
+ @echo -e "\nQEMU simulator."
+ for case in $(TESTCASES); do \
+ echo -n "$$case "; \
+ $(SIM) ./$$case; \
+ done
+check-g: $(CRT) $(SYS) $(TESTCASES)
+ @echo -e "\nGDB simulator."
+ @for case in $(TESTCASES); do \
+ echo -n "$$case "; \
+ $(SIMG) $$case; \
+ done
+
+clean:
+ $(RM) -fr $(TESTCASES) $(CRT) $(SYS)
diff --git a/tests/tcg/cris/README b/tests/tcg/cris/README
new file mode 100644
index 0000000000..2e65a76f10
--- /dev/null
+++ b/tests/tcg/cris/README
@@ -0,0 +1 @@
+Test-suite for the cris port. Heavily based on the test-suite for the CRIS port of sim by Hans-Peter Nilsson.
diff --git a/tests/tcg/cris/check_abs.c b/tests/tcg/cris/check_abs.c
new file mode 100644
index 0000000000..9770a8d9ef
--- /dev/null
+++ b/tests/tcg/cris/check_abs.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_abs(int n)
+{
+ int r;
+ asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
+ return r;
+}
+
+static inline void
+verify_abs(int val, int res,
+ const int n, const int z, const int v, const int c)
+{
+ int r;
+
+ cris_tst_cc_init();
+ r = cris_abs(val);
+ cris_tst_cc(n, z, v, c);
+ if (r != res)
+ err();
+}
+
+int main(void)
+{
+ verify_abs(-1, 1, 0, 0, 0, 0);
+ verify_abs(0x80000000, 0x80000000, 1, 0, 0, 0);
+ verify_abs(0x7fffffff, 0x7fffffff, 0, 0, 0, 0);
+ verify_abs(42, 42, 0, 0, 0, 0);
+ verify_abs(1, 1, 0, 0, 0, 0);
+ verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
+ verify_abs(0xffff, 0xffff, 0, 0, 0, 0);
+ verify_abs(-31, 0x1f, 0, 0, 0, 0);
+ verify_abs(0, 0, 0, 1, 0, 0);
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_addc.c b/tests/tcg/cris/check_addc.c
new file mode 100644
index 0000000000..facd1bea2d
--- /dev/null
+++ b/tests/tcg/cris/check_addc.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_addc(int a, const int b)
+{
+ asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
+ return a;
+}
+
+#define verify_addc(a, b, res, n, z, v, c) \
+{ \
+ int r; \
+ r = cris_addc((a), (b)); \
+ cris_tst_cc((n), (z), (v), (c)); \
+ if (r != (res)) \
+ err(); \
+}
+
+int main(void)
+{
+ cris_tst_cc_init();
+ asm volatile ("clearf cz");
+ verify_addc(0, 0, 0, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf z");
+ verify_addc(0, 0, 0, 0, 1, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf cz");
+ verify_addc(0, 0, 1, 0, 0, 0, 0);
+ cris_tst_cc_init();
+ asm volatile ("clearf c");
+ verify_addc(-1, 2, 1, 0, 0, 0, 1);
+
+ cris_tst_cc_init();
+ asm volatile ("clearf nzv");
+ asm volatile ("setf c");
+ verify_addc(-1, 2, 2, 0, 0, 0, 1);
+
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc(0xffff, 0xffff, 0x1ffff, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("clearf nzvc");
+ verify_addc(-1, -1, 0xfffffffe, 1, 0, 0, 1);
+
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc(0x78134452, 0x5432f789, 0xcc463bdc, 1, 0, 1, 0);
+
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_addcm.c b/tests/tcg/cris/check_addcm.c
new file mode 100644
index 0000000000..7928bc9999
--- /dev/null
+++ b/tests/tcg/cris/check_addcm.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* need to avoid acr as source here. */
+static inline int cris_addc_m(int a, const int *b)
+{
+ asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
+ return a;
+}
+
+/* 'b' is a crisv32 constrain to avoid postinc with $acr. */
+static inline int cris_addc_pi_m(int a, int **b)
+{
+ asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
+ return a;
+}
+
+#define verify_addc_m(a, b, res, n, z, v, c) \
+{ \
+ int r; \
+ r = cris_addc_m((a), (b)); \
+ cris_tst_cc((n), (z), (v), (c)); \
+ if (r != (res)) \
+ err(); \
+}
+
+#define verify_addc_pi_m(a, b, res, n, z, v, c) \
+{ \
+ int r; \
+ r = cris_addc_pi_m((a), (b)); \
+ cris_tst_cc((n), (z), (v), (c)); \
+ if (r != (res)) \
+ err(); \
+}
+
+int x[] = { 0, 0, 2, -1, 0xffff, -1, 0x5432f789};
+
+int main(void)
+{
+ int *p = (void *)&x[0];
+#if 1
+ cris_tst_cc_init();
+ asm volatile ("clearf cz");
+ verify_addc_m(0, p, 0, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf z");
+ verify_addc_m(0, p, 0, 0, 1, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc_m(0, p, 1, 0, 0, 0, 0);
+
+ cris_tst_cc_init();
+ asm volatile ("clearf c");
+ verify_addc_pi_m(0, &p, 0, 0, 1, 0, 0);
+
+ p = &x[1];
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc_pi_m(0, &p, 1, 0, 0, 0, 0);
+
+ if (p != &x[2])
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("clearf c");
+ verify_addc_pi_m(-1, &p, 1, 0, 0, 0, 1);
+
+ if (p != &x[3])
+ err();
+#endif
+ p = &x[3];
+ /* TODO: investigate why this one fails. */
+ cris_tst_cc_init();
+ asm volatile ("setf c");
+ verify_addc_m(2, p, 2, 0, 0, 0, 1);
+ p += 4;
+
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_addi.s b/tests/tcg/cris/check_addi.s
new file mode 100644
index 0000000000..a00dec02af
--- /dev/null
+++ b/tests/tcg/cris/check_addi.s
@@ -0,0 +1,57 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 0\n1\n2\n4\nbe02460f\n69d035a6\nc16c14d4\n
+
+ .include "testutils.inc"
+ start
+ moveq 0,r3
+ moveq 0,r4
+ clearf zcvn
+ addi r4.b,r3
+ test_cc 0 0 0 0
+ checkr3 0
+
+ moveq 0,r3
+ moveq 1,r4
+ setf zcvn
+ addi r4.b,r3
+ test_cc 1 1 1 1
+ checkr3 1
+
+ moveq 0,r3
+ moveq 1,r4
+ setf cv
+ clearf zn
+ addi r4.w,r3
+ test_cc 0 0 1 1
+ checkr3 2
+
+ moveq 0,r3
+ moveq 1,r4
+ clearf cv
+ setf zn
+ addi r4.d,r3
+ test_cc 1 1 0 0
+ checkr3 4
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ clearf cn
+ setf zv
+ addi r4.b,r3
+ test_cc 0 1 1 0
+ checkr3 be02460f
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ setf cn
+ clearf zv
+ addi r4.w,r3
+ test_cc 1 0 0 1
+ checkr3 69d035a6
+
+ move.d 0x12345678,r3
+ move.d 0xabcdef97,r4
+ addi r4.d,r3
+ checkr3 c16c14d4
+
+ quit
diff --git a/tests/tcg/cris/check_addiv32.s b/tests/tcg/cris/check_addiv32.s
new file mode 100644
index 0000000000..20ba25d219
--- /dev/null
+++ b/tests/tcg/cris/check_addiv32.s
@@ -0,0 +1,62 @@
+# mach: crisv32
+# output: 4455aa77\n4455aa77\nee19ccff\nff22\n4455aa77\nff224455\n55aa77ff\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 0x55aa77ff
+ .dword 0xccff2244
+ .dword 0x88ccee19
+
+ start
+ setf cv
+ moveq -1,r0
+ move.d x-32768,r5
+ move.d 32769,r6
+ addi r6.b,r5,acr
+ test_cc 0 0 1 1
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ addu.w 32771,r5
+ setf znvc
+ moveq -1,r8
+ addi r8.w,r5,acr
+ test_cc 1 1 1 1
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ moveq 5,r10
+ clearf znvc
+ addi r10.b,acr,acr
+ test_cc 0 0 0 0
+ move.d [acr],r3
+ checkr3 ee19ccff
+
+ subq 1,r5
+ move.d r5,r8
+ subq 1,r8
+ moveq 1,r9
+ addi r9.d,r8,acr
+ test_cc 0 0 0 0
+ movu.w [acr],r3
+ checkr3 ff22
+
+ moveq -2,r11
+ addi r11.w,acr,acr
+ move.d [acr],r3
+ checkr3 4455aa77
+
+ moveq 5,r9
+ addi r9.d,acr,acr
+ subq 18,acr
+ move.d [acr],r3
+ checkr3 ff224455
+
+ move.d -76789888/4,r12
+ addi r12.d,r5,acr
+ add.d 76789886,acr
+ move.d [acr],r3
+ checkr3 55aa77ff
+
+ quit
diff --git a/tests/tcg/cris/check_addm.s b/tests/tcg/cris/check_addm.s
new file mode 100644
index 0000000000..efece9f538
--- /dev/null
+++ b/tests/tcg/cris/check_addm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n781344d0\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,-1,0xffff,-1,0x5432f789
+ .word 2,-1,0xffff,0xf789
+ .byte 2,0xff,0x89
+ .byte 0x7e
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ add.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ add.d [r5],r3
+ test_cc 0 0 0 1
+ addq 4,r5
+ checkr3 1
+
+ move.d 0xffff,r3
+ add.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r3
+ add.d [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ add.d [r5+],r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r3
+ add.w [r5],r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ add.w [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ add.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ add.b [r5],r3
+ test_cc 0 0 0 1
+ addq 1,r5
+ checkr3 ffffff01
+
+ moveq 2,r3
+ add.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r3
+ add.b [r5],r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ add.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ add.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ add.b [r5],r3
+ test_cc 1 0 1 0
+ checkr3 781344d0
+
+ quit
diff --git a/tests/tcg/cris/check_addo.c b/tests/tcg/cris/check_addo.c
new file mode 100644
index 0000000000..3d8e789f5a
--- /dev/null
+++ b/tests/tcg/cris/check_addo.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* this would be better to do in asm, it's an orgy in GCC inline asm now. */
+
+#define cris_addo_b(o, v) \
+ asm volatile ("addo.b\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_w(o, v) \
+ asm volatile ("addo.w\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_d(o, v) \
+ asm volatile ("addo.d\t[%0], %1, $acr\n" : : "r" (o), "r" (v) : "acr");
+#define cris_addo_pi_b(o, v) \
+ asm volatile ("addo.b\t[%0+], %1, $acr\n" \
+ : "+b" (o): "r" (v) : "acr");
+#define cris_addo_pi_w(o, v) \
+ asm volatile ("addo.w\t[%0+], %1, $acr\n" \
+ : "+b" (o): "r" (v) : "acr");
+#define cris_addo_pi_d(o, v) \
+ asm volatile ("addo.d\t[%0+], %1, $acr\n" \
+ : "+b" (o): "r" (v) : "acr");
+
+struct {
+ uint32_t v1;
+ uint16_t v2;
+ uint32_t v3;
+ uint8_t v4;
+ uint8_t v5;
+ uint16_t v6;
+ uint32_t v7;
+} y = {
+ 32769,
+ -1,
+ 5,
+ 3, -4,
+ 2,
+ -76789887
+};
+
+static int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
+
+int main(void)
+{
+ int *r;
+ unsigned char *t, *p;
+
+ /* Note, this test-case will trig an unaligned access, partly
+ to x[0] and to [x1]. */
+ t = (unsigned char *)x;
+ t -= 32768;
+ p = (unsigned char *) &y.v1;
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_d(p, t);
+ cris_tst_cc(1, 1, 1, 1);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0x4455aa77)
+ err();
+
+
+ t += 32770;
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_w(p, t);
+ cris_tst_cc(1, 1, 1, 1);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0x4455aa77)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_d(p, r);
+ cris_tst_cc(1, 1, 1, 1);
+ p += 4;
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0xee19ccff)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_b(p, t);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*(uint16_t*)r != 0xff22)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_b(p, r);
+ cris_tst_cc(1, 1, 1, 1);
+ p += 1;
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0x4455aa77)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_w(p, r);
+ cris_tst_cc(1, 1, 1, 1);
+ p += 2;
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ if (*r != 0xff224455)
+ err();
+
+ mb(); /* dont reorder anything beyond here. */
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addo_pi_d(p, t);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (r));
+ r = (void*)(((char *)r) + 76789885);
+ if (*r != 0x55aa77ff)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_addoq.c b/tests/tcg/cris/check_addoq.c
new file mode 100644
index 0000000000..ed509e27e0
--- /dev/null
+++ b/tests/tcg/cris/check_addoq.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+/* this would be better to do in asm, it's an orgy in GCC inline asm now. */
+
+/* ACR will be clobbered. */
+#define cris_addoq(o, v) \
+ asm volatile ("addoq\t%1, %0, $acr\n" : : "r" (v), "i" (o) : "acr");
+
+
+int main(void)
+{
+ int x[3] = {0x55aa77ff, 0xccff2244, 0x88ccee19};
+ int *p, *t = x + 1;
+
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addoq(0, t);
+ cris_tst_cc(1, 1, 1, 1);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+ if (*p != 0xccff2244)
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_addoq(4, t);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+ if (*p != 0x88ccee19)
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("clearf\tzvnc\n");
+ cris_addoq(-8, t + 1);
+ cris_tst_cc(0, 0, 0, 0);
+ asm volatile ("move.d\t$acr, %0\n" : "=r" (p));
+ if (*p != 0x55aa77ff)
+ err();
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_addq.s b/tests/tcg/cris/check_addq.s
new file mode 100644
index 0000000000..e6f874f9b2
--- /dev/null
+++ b/tests/tcg/cris/check_addq.s
@@ -0,0 +1,47 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n0\n1\n100\n10000\n47\n67\na6\n80000001\n
+
+ .include "testutils.inc"
+ start
+ moveq -2,r3
+ addq 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ addq 1,r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 100
+
+ move.d 0xffff,r3
+ addq 1,r3
+ test_cc 0 0 0 0
+ checkr3 10000
+
+ move.d 0x42,r3
+ addq 5,r3
+ test_cc 0 0 0 0
+ checkr3 47
+
+ addq 32,r3
+ test_cc 0 0 0 0
+ checkr3 67
+
+ addq 63,r3
+ test_cc 0 0 0 0
+ checkr3 a6
+
+ move.d 0x7ffffffe,r3
+ addq 3,r3
+ test_cc 1 0 1 0
+ checkr3 80000001
+
+ quit
diff --git a/tests/tcg/cris/check_addr.s b/tests/tcg/cris/check_addr.s
new file mode 100644
index 0000000000..7f55cdc1b5
--- /dev/null
+++ b/tests/tcg/cris/check_addr.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq -1,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq -1,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_addxc.s b/tests/tcg/cris/check_addxc.s
new file mode 100644
index 0000000000..09c8355bf8
--- /dev/null
+++ b/tests/tcg/cris/check_addxc.s
@@ -0,0 +1,91 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq 2,r3
+ adds.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ adds.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ addu.b 0xff,r3
+ checkr3 101
+
+ moveq 2,r3
+ move.d 0xffffffff,r4
+ addu.w -1,r3
+ test_cc 0 0 0 0
+ checkr3 10001
+
+ move.d 0xffff,r3
+ addu.b -1,r3
+ test_cc 0 0 0 0
+ checkr3 100fe
+
+ move.d 0xffff,r3
+ addu.w -1,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ move.d 0xffff,r3
+ adds.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ move.d 0xffff,r3
+ adds.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ moveq -1,r3
+ adds.b 0xff,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ moveq -1,r3
+ adds.w 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 fe
+
+ moveq -1,r3
+ adds.w 0xffff,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ addu.b 0x89,r3
+ test_cc 0 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ adds.b 0x89,r3
+ test_cc 0 0 0 1
+ checkr3 781343db
+
+ move.d 0x78134452,r3
+ addu.w 0xf789,r3
+ test_cc 0 0 0 0
+ checkr3 78143bdb
+
+ move.d 0x78134452,r3
+ adds.w 0xf789,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ move.d 0x7fffffee,r3
+ addu.b 0xff,r3
+ test_cc 1 0 1 0
+ checkr3 800000ed
+
+ move.d 0x1,r3
+ adds.w 0xffff,r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_addxm.s b/tests/tcg/cris/check_addxm.s
new file mode 100644
index 0000000000..7563494b99
--- /dev/null
+++ b/tests/tcg/cris/check_addxm.s
@@ -0,0 +1,106 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n101\n10001\n100fe\n1fffe\nfffe\nfffe\nfffffffe\nfe\nfffffffe\n781344db\n781343db\n78143bdb\n78133bdb\n800000ed\n0\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .byte 0xff
+ .word 0xffff
+ .word 0xff
+ .word 0xffff
+ .byte 0x89
+ .word 0xf789
+ .byte 0xff
+ .word 0xffff
+
+ start
+ moveq 2,r3
+ move.d x,r5
+ adds.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ subq 3,r5
+ addu.b [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 101
+
+ moveq 2,r3
+ addu.w [r5+],r3
+ subq 3,r5
+ test_cc 0 0 0 0
+ checkr3 10001
+
+ move.d 0xffff,r3
+ addu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 100fe
+
+ move.d 0xffff,r3
+ addu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ move.d 0xffff,r3
+ adds.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ move.d 0xffff,r3
+ adds.w [r5],r3
+ test_cc 0 0 0 1
+ checkr3 fffe
+
+ moveq -1,r3
+ adds.b [r5],r3
+ test_cc 1 0 0 1
+ addq 3,r5
+ checkr3 fffffffe
+
+ moveq -1,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 fe
+
+ moveq -1,r3
+ adds.w [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ addu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 781344db
+
+ move.d 0x78134452,r3
+ adds.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 781343db
+
+ move.d 0x78134452,r3
+ addu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78143bdb
+
+ move.d 0x78134452,r3
+ adds.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ move.d 0x7fffffee,r3
+ addu.b [r5+],r3
+ test_cc 1 0 1 0
+ checkr3 800000ed
+
+ move.d 0x1,r3
+ adds.w [r5+],r3
+ test_cc 0 1 0 1
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_addxr.s b/tests/tcg/cris/check_addxr.s
new file mode 100644
index 0000000000..7f55cdc1b5
--- /dev/null
+++ b/tests/tcg/cris/check_addxr.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ add.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+
+ moveq -1,r4
+ move.d r4,r3
+ add.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq -1,r4
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffe
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ add.w r4,r3
+ test_cc 1 0 0 1
+ checkr3 fedafffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.w r4,r3
+ test_cc 0 0 0 1
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq 2,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq -1,r4
+ add.b r4,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ move.d 0xff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 fe
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ add.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 feda49fe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ add.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_andc.s b/tests/tcg/cris/check_andc.s
new file mode 100644
index 0000000000..a947b773c9
--- /dev/null
+++ b/tests/tcg/cris/check_andc.s
@@ -0,0 +1,80 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ and.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ and.d -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ and.d 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ and.d -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ and.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ and.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ and.w -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ and.w 0xffff,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ and.w 0xff5f,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x78134452,r3
+ and.w 0xf789,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ and.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff02
+
+ moveq 2,r3
+ and.b -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfa7,r3
+ and.b 0x5a,r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x78134453,r3
+ and.b 0x89,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ and.b 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/tests/tcg/cris/check_andm.s b/tests/tcg/cris/check_andm.s
new file mode 100644
index 0000000000..93858863fe
--- /dev/null
+++ b/tests/tcg/cris/check_andm.s
@@ -0,0 +1,90 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,-1,0xffff,-1,0x5432f789
+ .word 2,-1,0xffff,0xff5f,0xf789
+ .byte 2,-1,0x5a,0x89,0
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ and.d [r5],r3
+ test_move_cc 0 0 0 0
+ addq 4,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ and.d [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ and.d [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ and.w [r5],r3
+ test_move_cc 1 0 0 0
+ addq 2,r5
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ and.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x78134452,r3
+ and.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ and.b [r5],r3
+ test_move_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffff02
+
+ moveq 2,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfa7,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x78134453,r3
+ and.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ and.b [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/tests/tcg/cris/check_andq.s b/tests/tcg/cris/check_andq.s
new file mode 100644
index 0000000000..55aa7b0607
--- /dev/null
+++ b/tests/tcg/cris/check_andq.s
@@ -0,0 +1,46 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n1f\nffffffe0\n78134452\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ andq 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ andq -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ andq -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ andq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ andq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1f
+
+ moveq -1,r3
+ andq -32,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffe0
+
+ move.d 0x78134457,r3
+ andq -14,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq 0,r3
+ andq -14,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_andr.s b/tests/tcg/cris/check_andr.s
new file mode 100644
index 0000000000..61aa1dc32f
--- /dev/null
+++ b/tests/tcg/cris/check_andr.s
@@ -0,0 +1,95 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n50124400\nffff0002\n2\nfffff\nfedaff0f\n78134400\nffffff02\n2\nf02\n78134401\n78134400\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ and.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ and.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 50124400
+
+ moveq -1,r3
+ moveq 2,r4
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0002
+
+ moveq 2,r3
+ moveq -1,r4
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xfffff,r3
+ move.d 0xffff,r4
+ and.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffff
+
+ move.d 0xfedaffaf,r3
+ move.d 0xff5f,r4
+ and.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaff0f
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ and.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134400
+
+ moveq -1,r3
+ moveq 2,r4
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff02
+
+ moveq 2,r3
+ moveq -1,r4
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0x5a,r4
+ move.d 0xfa7,r3
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 f02
+
+ move.d 0x5432f789,r4
+ move.d 0x78134453,r3
+ and.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 78134401
+
+ moveq 0,r7
+ and.b r7,r3
+ test_move_cc 0 1 0 0
+ checkr3 78134400
+
+ quit
diff --git a/tests/tcg/cris/check_asr.s b/tests/tcg/cris/check_asr.s
new file mode 100644
index 0000000000..0a02ae6f7e
--- /dev/null
+++ b/tests/tcg/cris/check_asr.s
@@ -0,0 +1,230 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n1\nffffffff\nffffffff\n5a67f\nffffffff\nffffffff\nffffffff\nf699fc67\nffffffff\n1\nffffffff\nffffffff\n5a67f\nda67ffff\nda67ffff\nda67ffff\nda67fc67\nffffffff\nffffffff\n1\nffffffff\nffffffff\n5a670007\nda67f1ff\nda67f1ff\nda67f1ff\nda67f1e7\nffffffff\nffffffff\n1\nffffffff\nffffffff\nffffffff\n5a67f1ff\n5a67f1f9\n0\n5a670000\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ asrq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ asrq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ asrq 31,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ asrq 15,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67f19f,r3
+ asrq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 f699fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ asr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67ffff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5a67719f,r3
+ moveq 12,r4
+ asr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a670007
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1ff
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67f1e7
+
+ moveq -1,r3
+ moveq 0,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ asr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 15,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 7,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+; FIXME: was wrong.
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1ff
+
+; FIXME: was wrong.
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ asr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1f9
+
+ move.d 0x5a67f19f,r3
+ asrq 31,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x5a67419f,r3
+ moveq 16,r4
+ asr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a670000
+
+ quit
diff --git a/tests/tcg/cris/check_ba.s b/tests/tcg/cris/check_ba.s
new file mode 100644
index 0000000000..873a4086c5
--- /dev/null
+++ b/tests/tcg/cris/check_ba.s
@@ -0,0 +1,93 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: a\n
+
+
+ .set smalloffset,0
+ .set largeoffset,0
+
+
+ .macro fail
+ jump _fail
+ .endm
+
+ .global main
+main:
+ moveq 0,$r3
+
+; Short forward branch.
+ ba 0f
+ addq 1,$r3
+ fail
+
+; Max short forward branch.
+1:
+ ba 2f
+ addq 1,$r3
+ fail
+
+; Short backward branch.
+0:
+ ba 1b
+ addq 1,$r3
+ fail
+
+ .space 254-2+smalloffset+1b-.,0
+ moveq 0,$r3
+
+2:
+; Transit branch (long).
+ ba 3f
+ addq 1,$r3
+ fail
+
+ moveq 0,$r3
+4:
+; Long forward branch.
+ ba 5f
+ addq 1,$r3
+ fail
+
+ .space 256-2-smalloffset+4b-.,0
+
+ moveq 0,$r3
+
+; Max short backward branch.
+3:
+ ba 4b
+ addq 1,$r3
+ fail
+
+5:
+; Max long forward branch.
+ ba 6f
+ addq 1,$r3
+ fail
+
+ .space 32766+largeoffset-2+5b-.,0
+
+ moveq 0,$r3
+6:
+; Transit branch.
+ ba 7f
+ addq 1,$r3
+ fail
+
+ moveq 0,$r3
+9:
+ jsr pass
+ nop
+
+; Transit branch.
+ moveq 0,$r3
+7:
+ ba 8f
+ addq 1,$r3
+ fail
+
+ .space 32768-largeoffset+9b-.,0
+
+8:
+; Max long backward branch.
+ ba 9b
+ addq 1,$r3
+ fail
diff --git a/tests/tcg/cris/check_bas.s b/tests/tcg/cris/check_bas.s
new file mode 100644
index 0000000000..11929d4202
--- /dev/null
+++ b/tests/tcg/cris/check_bas.s
@@ -0,0 +1,102 @@
+# mach: crisv32
+# output: 0\n0\n0\nfb349abc\n0\n12124243\n0\n0\neab5baad\n0\nefb37832\n
+
+ .include "testutils.inc"
+ start
+x:
+ setf zncv
+ bsr 0f
+ nop
+0:
+ test_cc 1 1 1 1
+ move srp,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ bas 1f,mof
+ moveq 0,r0
+6:
+ nop
+ quit
+
+2:
+ move srp,r3
+ sub.d 3f,r3
+ checkr3 0
+ move srp,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 fb349abc
+
+ basc 4f,mof
+ nop
+ .dword 0x12124243
+7:
+ nop
+ quit
+
+8:
+ move mof,r3
+ sub.d 7f,r3
+ checkr3 0
+
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 eab5baad
+
+ jasc 9f,mof
+ nop
+ .dword 0xefb37832
+0:
+ quit
+
+ quit
+9:
+ move mof,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 efb37832
+
+ quit
+
+4:
+ move mof,r3
+ sub.d 7b,r3
+ checkr3 0
+ move mof,r4
+ subq 4,r4
+ move.d [r4],r3
+ checkr3 12124243
+ basc 5f,bz
+ moveq 0,r3
+ .dword 0x7634aeba
+ quit
+
+ .space 32770,0
+1:
+ move mof,r3
+ sub.d 6b,r3
+ checkr3 0
+
+ bsrc 2b
+ nop
+ .dword 0xfb349abc
+3:
+
+ quit
+
+5:
+ move mof,r3
+ sub.d 7b,r3
+ checkr3 0
+ move.d 8b,r6
+ jasc r6,mof
+ nop
+ .dword 0xeab5baad
+7:
+ quit
diff --git a/tests/tcg/cris/check_bcc.s b/tests/tcg/cris/check_bcc.s
new file mode 100644
index 0000000000..c57ffa6fa3
--- /dev/null
+++ b/tests/tcg/cris/check_bcc.s
@@ -0,0 +1,197 @@
+ .global main
+ .type main, @function
+main:
+ clearf nzvc
+ setf nzv
+ bcc 0f
+ addq 1, $r3
+ jump dofail
+
+0:
+ clearf nzvc
+ setf nzv
+ bcs dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf ncv
+ bne 1f
+ addq 1, $r3
+
+fail:
+dofail:
+ jump _fail
+
+1:
+ clearf nzvc
+ setf ncv
+ beq dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf ncz
+ bvc 2f
+ addq 1,$r3
+ jump dofail
+
+2:
+ clearf nzvc
+ setf ncz
+ bvs dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf vcz
+ bpl 3f
+ addq 1,$r3
+ jump fail
+3:
+ clearf nzvc
+ setf vcz
+ bmi dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf nv
+ bls dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf nv
+ bhi 4f
+ addq 1,$r3
+ jump dofail
+
+4:
+ clearf nzvc
+ setf zc
+ bge 5f
+ addq 1,$r3
+ jump dofail
+
+5:
+ clearf nzvc
+ setf zc
+ blt dofail
+ addq 1,$r3
+
+ clearf nzvc
+ setf c
+ bgt 6f
+ addq 1,$r3
+ jump fail
+
+6:
+ clearf nzvc
+ setf c
+ ble dofail
+ addq 1,$r3
+
+;;;;;;;;;;
+
+ setf nzvc
+ clearf nzv
+ bcc dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf nzv
+ bcs 0f
+ addq 1,$r3
+ jump fail
+
+0:
+ setf nzvc
+ clearf ncv
+ bne dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf ncv
+ beq 1f
+ addq 1,$r3
+ jump fail
+
+1:
+ setf nzvc
+ clearf ncz
+ bvc dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf ncz
+ bvs 2f
+ addq 1,$r3
+ jump fail
+
+2:
+ setf nzvc
+ clearf vcz
+ bpl dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf vcz
+ bmi 3f
+ addq 1,$r3
+ jump fail
+
+3:
+ setf nzvc
+ clearf nv
+ bls 4f
+ addq 1,$r3
+ jump fail
+
+4:
+ setf nzvc
+ clearf nv
+ bhi dofail
+ addq 1,$r3
+
+ setf zvc
+ clearf nzc
+ bge dofail
+ addq 1,$r3
+
+ setf nzc
+ clearf vzc
+ blt 5f
+ addq 1,$r3
+ jump fail
+
+5:
+ setf nzvc
+ clearf c
+ bgt dofail
+ addq 1,$r3
+
+ setf nzvc
+ clearf c
+ ble 6f
+ addq 1,$r3
+ jump fail
+
+6:
+ ; do a forward branch.
+ ba 2f
+ nop
+ .fill 100
+1:
+ ba 3f
+ nop
+ .fill 800
+2:
+ ba 1b
+ nop
+ .fill 1024
+3:
+
+ moveq 31, $r0
+1: bne 1b
+ subq 1, $r0
+
+ jsr pass
+ moveq 0, $r10
+ ret
+ nop
diff --git a/tests/tcg/cris/check_bound.c b/tests/tcg/cris/check_bound.c
new file mode 100644
index 0000000000..e8831754ec
--- /dev/null
+++ b/tests/tcg/cris/check_bound.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline int cris_bound_b(int v, int b)
+{
+ int r = v;
+ asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
+ return r;
+}
+
+static inline int cris_bound_w(int v, int b)
+{
+ int r = v;
+ asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
+ return r;
+}
+
+static inline int cris_bound_d(int v, int b)
+{
+ int r = v;
+ asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
+ return r;
+}
+
+int main(void)
+{
+ int r;
+
+ cris_tst_cc_init();
+ r = cris_bound_d(-1, 2);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(2, 0xffffffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(0xffff, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(-1, 0xffffffff);
+ cris_tst_cc(1, 0, 0, 0);
+ if (r != 0xffffffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_d(0x78134452, 0x5432f789);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0x5432f789)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(-1, 2);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(-1, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(2, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(0xfedaffff, 0xffff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xffff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(0x78134452, 0xf789);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xf789)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(-1, 2);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(2, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 2)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(-1, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0xff, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0xfeda49ff, 0xff);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0x78134452, 0x89);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0x89)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_w(0x78134452, 0);
+ cris_tst_cc(0, 1, 0, 0);
+ if (r != 0)
+ err();
+
+ cris_tst_cc_init();
+ r = cris_bound_b(0xffff, -1);
+ cris_tst_cc(0, 0, 0, 0);
+ if (r != 0xff)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_boundc.s b/tests/tcg/cris/check_boundc.s
new file mode 100644
index 0000000000..fb9e5bc905
--- /dev/null
+++ b/tests/tcg/cris/check_boundc.s
@@ -0,0 +1,101 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n5432f789\n2\nffff\n2\nffff\nffff\nf789\n2\n2\nff\nff\nff\n89\n0\nff\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ bound.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ bound.d 0xffffffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ bound.d 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ bound.d 0xffffffff,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ bound.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 5432f789
+
+ moveq -1,r3
+ bound.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq 2,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ bound.w 0xffff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x78134452,r3
+ bound.w 0xf789,r3
+ test_move_cc 0 0 0 0
+ checkr3 f789
+
+ moveq -1,r3
+ bound.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xff,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ bound.b 0xff,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x78134452,r3
+ bound.b 0x89,r3
+ test_move_cc 0 0 0 0
+ checkr3 89
+
+ bound.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xffff,r3
+ bound.b -1,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ quit
diff --git a/tests/tcg/cris/check_boundr.s b/tests/tcg/cris/check_boundr.s
new file mode 100644
index 0000000000..5c50cc5f6a
--- /dev/null
+++ b/tests/tcg/cris/check_boundr.s
@@ -0,0 +1,125 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\nffff\nffffffff\n5432f789\n2\n2\nffff\nffff\nffff\nf789\n2\n2\nff\nff\n89\nfeda4953\nfeda4962\n0\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5432f789
+
+ moveq -1,r3
+ moveq 2,r4
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq -1,r3
+ bound.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r4
+ move.d r4,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 f789
+
+ moveq -1,r3
+ moveq 2,r4
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ moveq 2,r3
+ moveq -1,r4
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r4
+ move.d r4,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ bound.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 89
+
+ move.d 0xfeda4956,r3
+ move.d 0xfeda4953,r4
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feda4953
+
+ move.d 0xfeda4962,r3
+ move.d 0xfeda4963,r4
+ bound.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feda4962
+
+ move.d 0xfeda4956,r3
+ move.d 0,r4
+ bound.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xfeda4956,r4
+ move.d 0,r3
+ bound.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_btst.s b/tests/tcg/cris/check_btst.s
new file mode 100644
index 0000000000..e39fc8f4d6
--- /dev/null
+++ b/tests/tcg/cris/check_btst.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1111\n
+
+ .include "testutils.inc"
+ start
+ clearf nzvc
+ moveq -1,r3
+ .if 1 ;..asm.arch.cris.v32
+ .else
+ setf vc
+ .endif
+ btstq 0,r3
+ test_cc 1 0 0 0
+
+ moveq 2,r3
+ btstq 1,r3
+ test_cc 1 0 0 0
+
+ moveq 4,r3
+ btstq 1,r3
+ test_cc 0 1 0 0
+
+ moveq -1,r3
+ btstq 31,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a67f19f,r3
+ btstq 12,r3
+ test_cc 1 0 0 0
+
+ move.d 0xda67f19f,r3
+ move.d 29,r4
+ btst r4,r3
+ test_cc 0 0 0 0
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0xda67f191,r3
+ move.d 33,r4
+ btst r4,r3
+ test_cc 0 0 0 0
+
+ moveq -1,r3
+ moveq 0,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq 2,r3
+ moveq 1,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq -1,r3
+ moveq 31,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ moveq 4,r3
+ btstq 1,r3
+ test_cc 0 1 0 0
+
+ moveq -1,r3
+ moveq 15,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ btst r4,r3
+ test_cc 1 0 0 0
+
+ move.d 0x5a678000,r3
+ moveq 11,r4
+ btst r4,r3
+ test_cc 0 1 0 0
+
+ move.d 0x5a67f19f,r3
+ btst r3,r3
+ test_cc 0 0 0 0
+
+ move.d 0x1111,r3
+ checkr3 1111
+
+ ; check that X gets cleared and that only the NZ flags are touched.
+ move.d 0xff, $r0
+ move $r0, $ccs
+ btst r3,r3
+ move $ccs, $r0
+ and.d 0xff, $r0
+ cmp.d 0xe3, $r0
+ test_cc 0 1 0 0
+
+ quit
diff --git a/tests/tcg/cris/check_clearfv32.s b/tests/tcg/cris/check_clearfv32.s
new file mode 100644
index 0000000000..4e91360273
--- /dev/null
+++ b/tests/tcg/cris/check_clearfv32.s
@@ -0,0 +1,19 @@
+# mach: crisv32
+# output: ef\nef\n
+
+; Check that "clearf x" doesn't trivially fail.
+
+ .include "testutils.inc"
+ start
+ setf puixnzvc
+ clearf x ; Actually, x would be cleared by almost-all other insns.
+ move ccs,r3
+ and.d 0xff, $r3
+ checkr3 ef
+
+ setf puixnzvc
+ moveq 0, $r3 ; moveq should only clear the xflag.
+ move ccs,r3
+ and.d 0xff, $r3
+ checkr3 ef
+ quit
diff --git a/tests/tcg/cris/check_clrjmp1.s b/tests/tcg/cris/check_clrjmp1.s
new file mode 100644
index 0000000000..45a7005e24
--- /dev/null
+++ b/tests/tcg/cris/check_clrjmp1.s
@@ -0,0 +1,36 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\n
+
+; A bug resulting in a non-effectual clear.b discovered running the GCC
+; testsuite; jump actually wrote to p0.
+
+ .include "testutils.inc"
+
+ start
+ jump 1f
+ nop
+ .p2align 8
+1:
+ move.d y,r4
+
+ .if 0 ;0 == ..asm.arch.cris.v32
+; There was a bug causing this insn to set special register p0
+; (byte-clear) to 8 (low 8 bits of location after insn).
+ jump [r4+]
+ .endif
+
+1:
+ move.d 0f,r4
+
+; The corresponding bug would cause this insn too, to set p0.
+ jump r4
+ nop
+ quit
+0:
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+ quit
+
+y:
+ .dword 1b
diff --git a/tests/tcg/cris/check_cmp-2.s b/tests/tcg/cris/check_cmp-2.s
new file mode 100644
index 0000000000..414d370517
--- /dev/null
+++ b/tests/tcg/cris/check_cmp-2.s
@@ -0,0 +1,15 @@
+
+
+.include "testutils.inc"
+
+ start
+
+ move.d 4294967283, $r0
+ move.d $r0, $r10
+ cmp.d $r0, $r10
+ beq 1f
+ move.d $r10, $r3
+ fail
+1:
+ pass
+ quit
diff --git a/tests/tcg/cris/check_cmpc.s b/tests/tcg/cris/check_cmpc.s
new file mode 100644
index 0000000000..267c9ba8c0
--- /dev/null
+++ b/tests/tcg/cris/check_cmpc.s
@@ -0,0 +1,86 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649282\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ cmp.d -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.d 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.d -0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmp.d 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmp.d -0x5432f789,r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.w -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.w 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ cmp.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ cmp.w 0x877,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.b -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.b 1,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r3
+ cmp.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ cmp.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d 0x78134452,r3
+ cmp.b 0x77,r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649282,r3
+ cmp.b 0x82,r3
+ test_cc 0 1 0 0
+ checkr3 85649282
+
+ quit
diff --git a/tests/tcg/cris/check_cmpm.s b/tests/tcg/cris/check_cmpm.s
new file mode 100644
index 0000000000..e4dde15b32
--- /dev/null
+++ b/tests/tcg/cris/check_cmpm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword -2,1,-0xffff,1,-0x5432f789
+ .word -2,1,1,0x877
+ .byte -2,1,0x77
+ .byte 0x22
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ cmp.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.d [r5],r3
+ test_cc 0 0 0 0
+ addq 4,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmp.d [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmp.d [r5+],r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmp.w [r5],r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ cmp.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ cmp.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ cmp.b [r5],r3
+ test_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffffff
+
+ moveq 2,r3
+ cmp.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xff,r3
+ cmp.b [r5],r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d 0xfeda49ff,r3
+ cmp.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d 0x78134452,r3
+ cmp.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649222,r3
+ cmp.b [r5],r3
+ test_cc 0 1 0 0
+ checkr3 85649222
+
+ quit
diff --git a/tests/tcg/cris/check_cmpq.s b/tests/tcg/cris/check_cmpq.s
new file mode 100644
index 0000000000..5469141c91
--- /dev/null
+++ b/tests/tcg/cris/check_cmpq.s
@@ -0,0 +1,75 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1\n1f\n1f\nffffffe1\nffffffe1\nffffffe0\n0\n0\nffffffff\nffffffff\n10000\n100\n5678900\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ cmpq 1,r3
+ test_cc 0 1 0 0
+ checkr3 1
+
+ cmpq -1,r3
+ test_cc 0 0 0 1
+ checkr3 1
+
+ cmpq 31,r3
+ test_cc 1 0 0 1
+ checkr3 1
+
+ moveq 31,r3
+ cmpq 31,r3
+ test_cc 0 1 0 0
+ checkr3 1f
+
+ cmpq -31,r3
+ test_cc 0 0 0 1
+ checkr3 1f
+
+ movs.b -31,r3
+ cmpq -31,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffe1
+
+ cmpq -32,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffe1
+
+ movs.b -32,r3
+ cmpq -32,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffe0
+
+ moveq 0,r3
+ cmpq 1,r3
+ test_cc 1 0 0 1
+ checkr3 0
+
+ cmpq -32,r3
+ test_cc 0 0 0 1
+ checkr3 0
+
+ moveq -1,r3
+ cmpq 1,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ cmpq -1,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x10000,r3
+ cmpq 1,r3
+ test_cc 0 0 0 0
+ checkr3 10000
+
+ move.d 0x100,r3
+ cmpq 1,r3
+ test_cc 0 0 0 0
+ checkr3 100
+
+ move.d 0x5678900,r3
+ cmpq 7,r3
+ test_cc 0 0 0 0
+ checkr3 5678900
+
+ quit
diff --git a/tests/tcg/cris/check_cmpr.s b/tests/tcg/cris/check_cmpr.s
new file mode 100644
index 0000000000..b30af7a538
--- /dev/null
+++ b/tests/tcg/cris/check_cmpr.s
@@ -0,0 +1,102 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n2\nffff\nffffffff\n78134452\nffffffff\n2\nffff\nfedaffff\n78134452\nffffffff\n2\nff\nfeda49ff\n78134452\n85649222\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq -2,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ cmp.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq 1,r4
+ moveq -1,r3
+ cmp.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.d r4,r3
+ test_cc 1 0 1 1
+ checkr3 78134452
+
+ moveq -1,r3
+ moveq -2,r4
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ cmp.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffff
+
+ move.d 0xfedaffff,r3
+ move.d -0xfedaffff,r4
+ cmp.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ moveq -1,r3
+ moveq -2,r4
+ cmp.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ cmp.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 2
+
+ move.d -0xff,r4
+ move.d 0xff,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 ff
+
+ move.d -0xfeda49ff,r4
+ move.d 0xfeda49ff,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 feda49ff
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ cmp.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 78134452
+
+ move.d 0x85649222,r3
+ move.d 0x77445622,r4
+ cmp.b r4,r3
+ test_cc 0 1 0 0
+ checkr3 85649222
+
+ quit
diff --git a/tests/tcg/cris/check_cmpxc.s b/tests/tcg/cris/check_cmpxc.s
new file mode 100644
index 0000000000..b237a93175
--- /dev/null
+++ b/tests/tcg/cris/check_cmpxc.s
@@ -0,0 +1,92 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
+
+ .include "testutils.inc"
+ start
+ moveq 2,r3
+ cmps.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmps.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmpu.b 0xff,r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ move.d 0xffffffff,r4
+ cmpu.w -1,r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmpu.b -1,r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmpu.w -1,r3
+ test_cc 0 1 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.b 0xff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.w 0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmps.b 0xff,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w 0xff,r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w 0xffff,r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmpu.b 0x89,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.b 0x89,r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmpu.w 0xf789,r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.w 0xf789,r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x4452,r3
+ cmps.w 0x8002,r3
+ test_cc 0 0 0 1
+ checkr3 4452
+
+ move.d 0x80000032,r3
+ cmpu.w 0x764,r3
+ test_cc 0 0 1 0
+ checkr3 80000032
+
+ quit
diff --git a/tests/tcg/cris/check_cmpxm.s b/tests/tcg/cris/check_cmpxm.s
new file mode 100644
index 0000000000..87ea5bf8e3
--- /dev/null
+++ b/tests/tcg/cris/check_cmpxm.s
@@ -0,0 +1,106 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 2\n2\n2\n2\nffff\nffff\nffff\nffff\nffffffff\nffffffff\nffffffff\n78134452\n78134452\n78134452\n78134452\n4452\n80000032\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .byte 0xff
+ .word 0xffff
+ .word 0xff
+ .word 0xffff
+ .byte 0x89
+ .word 0xf789
+ .word 0x8002
+ .word 0x764
+
+ start
+ moveq 2,r3
+ move.d x,r5
+ cmps.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ subq 3,r5
+ cmpu.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 2
+
+ moveq 2,r3
+ cmpu.w [r5+],r3
+ test_cc 1 0 0 1
+ subq 3,r5
+ checkr3 2
+
+ move.d 0xffff,r3
+ cmpu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmpu.w [r5],r3
+ test_cc 0 1 0 0
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.b [r5],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ move.d 0xffff,r3
+ cmps.w [r5],r3
+ test_cc 0 0 0 1
+ checkr3 ffff
+
+ moveq -1,r3
+ cmps.b [r5],r3
+ test_cc 0 1 0 0
+ addq 3,r5
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ cmps.w [r5+],r3
+ test_cc 0 1 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ cmpu.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.b [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmpu.w [r5],r3
+ test_cc 0 0 0 0
+ checkr3 78134452
+
+ move.d 0x78134452,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 78134452
+
+ move.d 0x4452,r3
+ cmps.w [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 4452
+
+ move.d 0x80000032,r3
+ cmpu.w [r5+],r3
+ test_cc 0 0 1 0
+ checkr3 80000032
+
+ quit
diff --git a/tests/tcg/cris/check_dstep.s b/tests/tcg/cris/check_dstep.s
new file mode 100644
index 0000000000..bd43b838ea
--- /dev/null
+++ b/tests/tcg/cris/check_dstep.s
@@ -0,0 +1,42 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: fffffffc\n4\nffff\nfffffffe\n9bf3911b\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffc
+
+ moveq 2,r3
+ moveq -1,r4
+ dstep r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ dstep r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ dstep r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 9bf3911b
+
+ move.d 0xffff,r3
+ move.d 0x1fffe,r4
+ dstep r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_ftag.c b/tests/tcg/cris/check_ftag.c
new file mode 100644
index 0000000000..908773a38a
--- /dev/null
+++ b/tests/tcg/cris/check_ftag.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+static inline void cris_ftag_i(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("ftagi\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_ftag_d(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("ftagd\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_fidx_i(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("fidxi\t[%0]\n" : : "r" (v) );
+}
+static inline void cris_fidx_d(unsigned int x)
+{
+ register unsigned int v asm("$r10") = x;
+ asm ("fidxd\t[%0]\n" : : "r" (v) );
+}
+
+
+int main(void)
+{
+ cris_ftag_i(0);
+ cris_ftag_d(0);
+ cris_fidx_i(0);
+ cris_fidx_d(0);
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_gcctorture_pr28634-1.c b/tests/tcg/cris/check_gcctorture_pr28634-1.c
new file mode 100644
index 0000000000..45ecd159b3
--- /dev/null
+++ b/tests/tcg/cris/check_gcctorture_pr28634-1.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634. On targets with delayed branches,
+ dbr_schedule could do the next iteration's addition in the
+ branch delay slot, then subtract the value again if the branch
+ wasn't taken. This can lead to rounding errors. */
+int x = -1;
+int y = 1;
+int
+main (void)
+{
+ while (y > 0)
+ y += x;
+ if (y != x + 1)
+ abort ();
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_gcctorture_pr28634.c b/tests/tcg/cris/check_gcctorture_pr28634.c
new file mode 100644
index 0000000000..a0c525497d
--- /dev/null
+++ b/tests/tcg/cris/check_gcctorture_pr28634.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/28634. On targets with delayed branches,
+ dbr_schedule could do the next iteration's addition in the
+ branch delay slot, then subtract the value again if the branch
+ wasn't taken. This can lead to rounding errors. */
+double x = -0x1.0p53;
+double y = 1;
+int
+main (void)
+{
+ while (y > 0)
+ y += x;
+ if (y != x + 1)
+ abort ();
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_glibc_kernelversion.c b/tests/tcg/cris/check_glibc_kernelversion.c
new file mode 100644
index 0000000000..07448722c0
--- /dev/null
+++ b/tests/tcg/cris/check_glibc_kernelversion.c
@@ -0,0 +1,116 @@
+/*
+ * Check the lz insn.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+
+#define __LINUX_KERNEL_VERSION 131584
+
+#define DL_SYSDEP_OSCHECK(FATAL) \
+ do { \
+ /* Test whether the kernel is new enough. This test is only \
+ performed if the library is not compiled to run on all \
+ kernels. */ \
+ if (__LINUX_KERNEL_VERSION > 0) \
+ { \
+ char bufmem[64]; \
+ char *buf = bufmem; \
+ unsigned int version; \
+ int parts; \
+ char *cp; \
+ struct utsname uts; \
+ \
+ /* Try the uname syscall */ \
+ if (__uname (&uts)) \
+ { \
+ /* This was not successful. Now try reading the /proc \
+ filesystem. */ \
+ ssize_t reslen; \
+ int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY); \
+ if (fd == -1 \
+ || (reslen = __read (fd, bufmem, sizeof (bufmem))) <= 0) \
+ /* This also didn't work. We give up since we cannot \
+ make sure the library can actually work. */ \
+ FATAL ("FATAL: cannot determine library version\n"); \
+ __close (fd); \
+ buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0'; \
+ } \
+ else \
+ buf = uts.release; \
+ \
+ /* Now convert it into a number. The string consists of at most \
+ three parts. */ \
+ version = 0; \
+ parts = 0; \
+ cp = buf; \
+ while ((*cp >= '0') && (*cp <= '9')) \
+ { \
+ unsigned int here = *cp++ - '0'; \
+ \
+ while ((*cp >= '0') && (*cp <= '9')) \
+ { \
+ here *= 10; \
+ here += *cp++ - '0'; \
+ } \
+ \
+ ++parts; \
+ version <<= 8; \
+ version |= here; \
+ \
+ if (*cp++ != '.') \
+ /* Another part following? */ \
+ break; \
+ } \
+ \
+ if (parts < 3) \
+ version <<= 8 * (3 - parts); \
+ \
+ /* Now we can test with the required version. */ \
+ if (version < __LINUX_KERNEL_VERSION) \
+ /* Not sufficient. */ \
+ FATAL ("FATAL: kernel too old\n"); \
+ \
+ _dl_osversion = version; \
+ } \
+ } while (0)
+
+int main(void)
+{
+ char bufmem[64] = "2.6.22";
+ char *buf = bufmem;
+ unsigned int version;
+ int parts;
+ char *cp;
+
+ version = 0;
+ parts = 0;
+ cp = buf;
+ while ((*cp >= '0') && (*cp <= '9'))
+ {
+ unsigned int here = *cp++ - '0';
+
+ while ((*cp >= '0') && (*cp <= '9'))
+ {
+ here *= 10;
+ here += *cp++ - '0';
+ }
+
+ ++parts;
+ version <<= 8;
+ version |= here;
+
+ if (*cp++ != '.')
+ /* Another part following? */
+ break;
+ }
+
+ if (parts < 3)
+ version <<= 8 * (3 - parts);
+ if (version < __LINUX_KERNEL_VERSION)
+ err();
+ pass();
+ exit(0);
+}
diff --git a/tests/tcg/cris/check_hello.c b/tests/tcg/cris/check_hello.c
new file mode 100644
index 0000000000..fb403ba996
--- /dev/null
+++ b/tests/tcg/cris/check_hello.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdlib.h>
+int main ()
+{
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_int64.c b/tests/tcg/cris/check_int64.c
new file mode 100644
index 0000000000..fc600176e2
--- /dev/null
+++ b/tests/tcg/cris/check_int64.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+
+static inline int64_t add64(const int64_t a, const int64_t b)
+{
+ return a + b;
+}
+
+static inline int64_t sub64(const int64_t a, const int64_t b)
+{
+ return a - b;
+}
+
+int main(void)
+{
+ int64_t a = 1;
+ int64_t b = 2;
+
+ /* FIXME: add some tests. */
+ a = add64(a, b);
+ if (a != 3)
+ err();
+
+ a = sub64(a, b);
+ if (a != 1)
+ err();
+
+ a = add64(a, -4);
+ if (a != -3)
+ err();
+
+ a = add64(a, 3);
+ if (a != 0)
+ err();
+
+ a = 0;
+ a = sub64(a, 1);
+ if (a != -1)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_jsr.s b/tests/tcg/cris/check_jsr.s
new file mode 100644
index 0000000000..1060237873
--- /dev/null
+++ b/tests/tcg/cris/check_jsr.s
@@ -0,0 +1,85 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 0\n0\n0\n0\n0\n0\n
+
+# Test that jsr Rn and jsr [PC+] work.
+
+ .include "testutils.inc"
+ start
+x:
+ move.d 0f,r6
+ setf nzvc
+ jsr r6
+ .if 1; ..asm.arch.cris.v32
+ nop
+ .endif
+0:
+ test_move_cc 1 1 1 1
+ move srp,r3
+ sub.d 0b,r3
+ checkr3 0
+
+ move.d 1f,r0
+ setf nzvc
+ jsr r0
+ .if 1 ; ..asm.arch.cris.v32
+ moveq 0,r0
+ .endif
+6:
+ nop
+ quit
+
+2:
+ test_move_cc 0 0 0 0
+ move srp,r3
+ sub.d 3f,r3
+ checkr3 0
+ jsr 4f
+ .if 1 ; ..asm.arch.cris.v32
+ nop
+ .endif
+7:
+ nop
+ quit
+
+8:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ quit
+
+4:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ move.d 5f,r3
+ jump r3
+ .if 1; ..asm.arch.cris.v32
+ moveq 0,r3
+ .endif
+ quit
+
+ .space 32770,0
+1:
+ test_move_cc 1 1 1 1
+ move srp,r3
+ sub.d 6b,r3
+ checkr3 0
+
+ clearf cznv
+ jsr 2b
+ .if 1; ..asm.arch.cris.v32
+ nop
+ .endif
+3:
+
+ quit
+
+5:
+ move srp,r3
+ sub.d 7b,r3
+ checkr3 0
+ jump 8b
+ .if 1 ; ..asm.arch.cris.v32
+ nop
+ .endif
+ quit
diff --git a/tests/tcg/cris/check_lapc.s b/tests/tcg/cris/check_lapc.s
new file mode 100644
index 0000000000..9a6150b749
--- /dev/null
+++ b/tests/tcg/cris/check_lapc.s
@@ -0,0 +1,78 @@
+# mach: crisv32
+# output: 0\n0\nfffffffa\nfffffffe\nffffffda\n1e\n1e\n0\n
+
+.include "testutils.inc"
+
+; To accommodate dumpr3 with more than one instruction, keep it
+; out of lapc operand ranges and difference calculations.
+
+ start
+ lapc.d 0f,r3
+0:
+ sub.d .,r3
+ checkr3 0
+
+ lapcq 0f,r3
+0:
+ sub.d .,r3
+ checkr3 0
+
+ lapc.d .,r3
+ sub.d .,r3
+ checkr3 fffffffa
+
+ lapcq .,r3
+ sub.d .,r3
+ checkr3 fffffffe
+
+0:
+ .rept 16
+ nop
+ .endr
+ lapc.d 0b,r3
+ sub.d .,r3
+ checkr3 ffffffda
+
+ setf zcvn
+ lapc.d 0f,r3
+ test_cc 1 1 1 1
+ sub.d .,r3
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+0:
+ checkr3 1e
+0:
+ lapcq 0f,r3
+ sub.d 0b,r3
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+0:
+ checkr3 1e
+ clearf cn
+ setf zv
+1:
+ lapcq .,r3
+ test_cc 0 1 1 0
+ sub.d 1b,r3
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_lsl.s b/tests/tcg/cris/check_lsl.s
new file mode 100644
index 0000000000..9e2ddd7cd0
--- /dev/null
+++ b/tests/tcg/cris/check_lsl.s
@@ -0,0 +1,217 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n4\n80000000\nffff8000\n7f19f000\n80000000\n0\n0\n699fc67c\nffffffff\n4\n80000000\nffff8000\n7f19f000\nda670000\nda670000\nda670000\nda67c67c\nffffffff\nfffafffe\n4\nffff0000\nffff8000\n5a67f000\nda67f100\nda67f100\nda67f100\nda67f17c\nfff3faff\nfff3fafe\n4\nffffff00\nffffff00\nffffff80\n5a67f100\n5a67f1f0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ lslq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ lslq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ lslq 31,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ lslq 15,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ lslq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 7f19f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 699fc67c
+
+ moveq -1,r3
+ moveq 0,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 7f19f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 da67c67c
+
+ moveq -1,r3
+ moveq 0,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0xfffaffff,r3
+ moveq 1,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffafffe
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8000
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f000
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsl.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da67f17c
+
+ move.d 0xfff3faff,r3
+ moveq 0,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fff3faff
+
+ move.d 0xfff3faff,r3
+ moveq 1,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fff3fafe
+
+ moveq 2,r3
+ moveq 1,r4
+ lsl.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 4
+
+ moveq -1,r3
+ moveq 31,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 15,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 7,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffff80
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsl.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a67f100
+
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ lsl.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 5a67f1f0
+
+ quit
diff --git a/tests/tcg/cris/check_lsr.s b/tests/tcg/cris/check_lsr.s
new file mode 100644
index 0000000000..18fdbef9b2
--- /dev/null
+++ b/tests/tcg/cris/check_lsr.s
@@ -0,0 +1,218 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\n1\n1\n1ffff\n5a67f\n1\n0\n0\n3699fc67\nffffffff\n1\n1\n1ffff\n5a67f\nda670000\nda670000\nda670000\nda673c67\nffffffff\nffff7fff\n1\nffff0000\nffff0001\n5a67000f\nda67f100\nda67f100\nda67f100\nda67f127\nffffffff\nffffff7f\n1\nffffff00\nffffff00\nffffff01\n5a67f100\n5a67f109\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ lsrq 0,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ lsrq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ lsrq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ lsrq 15,r3
+ test_move_cc 0 0 0 0
+ checkr3 1ffff
+
+ move.d 0x5a67f19f,r3
+ lsrq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.d r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3699fc67
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1ffff
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da670000
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da673c67
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff7fff
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+;; FIXME: this was wrong. Z should be set.
+ moveq -1,r3
+ moveq 31,r4
+ lsr.w r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0001
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67000f
+
+ move.d 0xda67f19f,r3
+ move.d 31,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 32,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 33,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 da67f100
+
+ move.d 0xda67f19f,r3
+ move.d 66,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 da67f127
+
+ moveq -1,r3
+ moveq 0,r4
+ lsr.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 1,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff7f
+
+ moveq 2,r3
+ moveq 1,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ moveq -1,r3
+ moveq 31,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 15,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ moveq -1,r3
+ moveq 7,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff01
+
+ move.d 0x5a67f19f,r3
+ moveq 12,r4
+ lsr.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 5a67f100
+
+ move.d 0x5a67f19f,r3
+ moveq 4,r4
+ lsr.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5a67f109
+
+ quit
diff --git a/tests/tcg/cris/check_lz.c b/tests/tcg/cris/check_lz.c
new file mode 100644
index 0000000000..69c2e6d4ec
--- /dev/null
+++ b/tests/tcg/cris/check_lz.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+
+static inline int cris_lz(int x)
+{
+ int r;
+ asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
+ return r;
+}
+
+void check_lz(void)
+{
+ int i;
+
+ if (cris_lz(0) != 32)
+ err();
+ if (cris_lz(1) != 31)
+ err();
+ if (cris_lz(2) != 30)
+ err();
+ if (cris_lz(4) != 29)
+ err();
+ if (cris_lz(8) != 28)
+ err();
+
+ /* try all positions with a single bit. */
+ for (i = 1; i < 32; i++) {
+ if (cris_lz(1 << (i-1)) != (32 - i))
+ err();
+ }
+
+ /* try all positions with all bits. */
+ for (i = 1; i < 32; i++) {
+ /* split up this computation to clarify it. */
+ uint32_t val;
+ val = (unsigned int)-1 >> (32 - i);
+ if (cris_lz(val) != (32 - i))
+ err();
+ }
+}
+
+int main(void)
+{
+ check_lz();
+ pass();
+ exit(0);
+}
diff --git a/tests/tcg/cris/check_mapbrk.c b/tests/tcg/cris/check_mapbrk.c
new file mode 100644
index 0000000000..1aff7622bc
--- /dev/null
+++ b/tests/tcg/cris/check_mapbrk.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Basic sanity check that syscalls to implement malloc (brk, mmap2,
+ munmap) are trivially functional. */
+
+int main ()
+{
+ void *p1, *p2, *p3, *p4, *p5, *p6;
+
+ if ((p1 = malloc (8100)) == NULL
+ || (p2 = malloc (16300)) == NULL
+ || (p3 = malloc (4000)) == NULL
+ || (p4 = malloc (500)) == NULL
+ || (p5 = malloc (1023*1024)) == NULL
+ || (p6 = malloc (8191*1024)) == NULL)
+ {
+ printf ("fail\n");
+ exit (1);
+ }
+
+ free (p1);
+ free (p2);
+ free (p3);
+ free (p4);
+ free (p5);
+ free (p6);
+
+ p1 = malloc (64000);
+ if (p1 == NULL)
+ {
+ printf ("fail\n");
+ exit (1);
+ }
+ free (p1);
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_mcp.s b/tests/tcg/cris/check_mcp.s
new file mode 100644
index 0000000000..e65ccddfd4
--- /dev/null
+++ b/tests/tcg/cris/check_mcp.s
@@ -0,0 +1,49 @@
+# mach: crisv32
+# output: fffffffe\n1\n1ffff\nfffffffe\ncc463bdc\n4c463bdc\n0\n
+
+ .include "testutils.inc"
+ start
+
+; Set R, clear C.
+ move 0x100,ccs
+ moveq -5,r3
+ move 2,mof
+ mcp mof,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ moveq 2,r3
+ move -1,srp
+ mcp srp,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move 0xffff,srp
+ move srp,r3
+ mcp srp,r3
+ test_cc 0 0 0 0
+ checkr3 1ffff
+
+ move -1,mof
+ move mof,r3
+ mcp mof,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move 0x5432f789,mof
+ move.d 0x78134452,r3
+ mcp mof,r3
+ test_cc 1 0 1 0
+ checkr3 cc463bdc
+
+ move 0x80000000,srp
+ mcp srp,r3
+ test_cc 0 0 1 0
+ checkr3 4c463bdc
+
+ move 0xb3b9c423,srp
+ mcp srp,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_mmap1.c b/tests/tcg/cris/check_mmap1.c
new file mode 100644
index 0000000000..b803f0c431
--- /dev/null
+++ b/tests/tcg/cris/check_mmap1.c
@@ -0,0 +1,48 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+ int fd = open (argv[0], O_RDONLY);
+ struct stat sb;
+ int size;
+ void *a;
+ const char *str = "a string you'll only find in the program";
+
+ if (fd == -1)
+ {
+ perror ("open");
+ abort ();
+ }
+
+ if (fstat (fd, &sb) < 0)
+ {
+ perror ("fstat");
+ abort ();
+ }
+
+ size = sb.st_size;
+
+ /* We want to test mmapping a size that isn't exactly a page. */
+ if ((size & 8191) == 0)
+ size--;
+
+ a = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ if (memmem (a, size, str, strlen (str) + 1) == NULL)
+ abort ();
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_mmap2.c b/tests/tcg/cris/check_mmap2.c
new file mode 100644
index 0000000000..35139a0ed9
--- /dev/null
+++ b/tests/tcg/cris/check_mmap2.c
@@ -0,0 +1,48 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+ int fd = open (argv[0], O_RDONLY);
+ struct stat sb;
+ int size;
+ void *a;
+ const char *str = "a string you'll only find in the program";
+
+ if (fd == -1)
+ {
+ perror ("open");
+ abort ();
+ }
+
+ if (fstat (fd, &sb) < 0)
+ {
+ perror ("fstat");
+ abort ();
+ }
+
+ size = sb.st_size;
+
+ /* We want to test mmapping a size that isn't exactly a page. */
+ if ((size & 8191) == 0)
+ size--;
+
+ a = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+
+ if (memmem (a, size, str, strlen (str) + 1) == NULL)
+ abort ();
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_mmap3.c b/tests/tcg/cris/check_mmap3.c
new file mode 100644
index 0000000000..34401fa0c9
--- /dev/null
+++ b/tests/tcg/cris/check_mmap3.c
@@ -0,0 +1,33 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main (int argc, char *argv[])
+{
+ volatile unsigned char *a;
+
+ /* Check that we can map a non-multiple of a page and still get a full page. */
+ a = mmap (NULL, 0x4c, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (a == NULL || a == (unsigned char *) -1)
+ abort ();
+
+ a[0] = 0xbe;
+ a[8191] = 0xef;
+ memset ((char *) a + 1, 0, 8190);
+
+ if (a[0] != 0xbe || a[8191] != 0xef)
+ abort ();
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_movdelsr1.s b/tests/tcg/cris/check_movdelsr1.s
new file mode 100644
index 0000000000..300cc87742
--- /dev/null
+++ b/tests/tcg/cris/check_movdelsr1.s
@@ -0,0 +1,33 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: aa117acd\n
+# output: eeaabb42\n
+
+; Bug with move to special register in delay slot, due to
+; special flush-insn-cache simulator use. Ordinary move worked;
+; special register caused branch to fail.
+
+ .include "testutils.inc"
+ start
+ move -1,srp
+
+ move.d 0xaa117acd,r1
+ moveq 3,r9
+ cmpq 1,r9
+ bhi 0f
+ move.d r1,r3
+
+ fail
+0:
+ checkr3 aa117acd
+
+ move.d 0xeeaabb42,r1
+ moveq 3,r9
+ cmpq 1,r9
+ bhi 0f
+ move r1,srp
+
+ fail
+0:
+ move srp,r3
+ checkr3 eeaabb42
+ quit
diff --git a/tests/tcg/cris/check_movecr.s b/tests/tcg/cris/check_movecr.s
new file mode 100644
index 0000000000..da8ec26284
--- /dev/null
+++ b/tests/tcg/cris/check_movecr.s
@@ -0,0 +1,37 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff42\n94\nffff4321\n9234\n76543210\n76540000\n
+
+; Move constant byte, word, dword to register. Check that no extension is
+; performed, that only part of the register is set.
+
+ .include "testutils.inc"
+ startnostack
+ moveq -1,r3
+ move.b 0x42,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff42
+
+ moveq 0,r3
+ move.b 0x94,r3
+ test_move_cc 1 0 0 0
+ checkr3 94
+
+ moveq -1,r3
+ move.w 0x4321,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff4321
+
+ moveq 0,r3
+ move.w 0x9234,r3
+ test_move_cc 1 0 0 0
+ checkr3 9234
+
+ move.d 0x76543210,r3
+ test_move_cc 0 0 0 0
+ checkr3 76543210
+
+ move.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 76540000
+
+ quit
diff --git a/tests/tcg/cris/check_movei.s b/tests/tcg/cris/check_movei.s
new file mode 100644
index 0000000000..bbfa633373
--- /dev/null
+++ b/tests/tcg/cris/check_movei.s
@@ -0,0 +1,50 @@
+# mach: crisv32
+# output: fffffffe\n
+# output: fffffffe\n
+
+; Check basic integral-write semantics regarding flags.
+
+ .include "testutils.inc"
+ start
+
+ move.d 0, $r3
+; A write that works. Check that flags are set correspondingly.
+ move.d d,r4
+ ;; store to bring it into the tlb with the right prot bits
+ move.d r3,[r4]
+ moveq -2,r5
+ setf c
+ clearf p
+ move.d [r4],r3
+ ax
+ move.d r5,[r4]
+ move.d [r4],r3
+
+ bcc 0f
+ nop
+ fail
+
+0:
+ checkr3 fffffffe
+
+; A write that fails; check flags too.
+ move.d d,r4
+ moveq 23,r5
+ setf p
+ clearf c
+ move.d [r4],r3
+ ax
+ move.d r5,[r4]
+ move.d [r4],r3
+
+ bcs 0f
+ nop
+ fail
+
+0:
+ checkr3 fffffffe
+ quit
+
+ .data
+d:
+ .dword 42424242
diff --git a/tests/tcg/cris/check_movemr.s b/tests/tcg/cris/check_movemr.s
new file mode 100644
index 0000000000..88489dee31
--- /dev/null
+++ b/tests/tcg/cris/check_movemr.s
@@ -0,0 +1,78 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 12345678\n10234567\n12345678\n12344567\n12344523\n76543210\nffffffaa\naa\n9911\nffff9911\n78\n56\n3456\n6712\n
+
+ .include "testutils.inc"
+ start
+
+ .data
+mem1:
+ .dword 0x12345678
+mem2:
+ .word 0x4567
+mem3:
+ .byte 0x23
+ .dword 0x76543210
+ .byte 0xaa,0x11,0x99
+
+ .text
+ move.d mem1,r2
+ move.d [r2],r3
+ test_move_cc 0 0 0 0
+ checkr3 12345678
+
+ move.d mem2,r3
+ move.d [r3],r3
+ test_move_cc 0 0 0 0
+ checkr3 10234567
+
+ move.d mem1,r2
+ move.d [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12345678
+
+ move.w [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12344567
+
+ move.b [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 12344523
+
+ move.d [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 76543210
+
+ movs.b [r2],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffaa
+
+ movu.b [r2+],r3
+ test_move_cc 0 0 0 0
+ checkr3 aa
+
+ movu.w [r2],r3
+ test_move_cc 0 0 0 0
+ checkr3 9911
+
+ movs.w [r2+],r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff9911
+
+ move.d mem1,r13
+ movs.b [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 78
+
+ movu.b [r13],r3
+ test_move_cc 0 0 0 0
+ checkr3 56
+
+ movs.w [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 3456
+
+ movu.w [r13+],r3
+ test_move_cc 0 0 0 0
+ checkr3 6712
+
+ quit
diff --git a/tests/tcg/cris/check_movemrv32.s b/tests/tcg/cris/check_movemrv32.s
new file mode 100644
index 0000000000..53950abd5b
--- /dev/null
+++ b/tests/tcg/cris/check_movemrv32.s
@@ -0,0 +1,96 @@
+# mach: crisv32
+# output: 15\n7\n2\nffff1234\nb\n16\nf\n2\nffffffef\nf\nffff1234\nf\nfffffff4\nd\nfffffff2\n10\nfffffff2\nd\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 8,9,10,11
+y:
+ .dword -12,13,-14,15,16
+
+ start
+ moveq 7,r0
+ moveq 2,r1
+ move.d 0xffff1234,r2
+ moveq 21,r3
+ move.d x,r4
+ setf zcvn
+ movem r2,[r4+]
+ test_cc 1 1 1 1
+ subq 12,r4
+
+ checkr3 15
+
+ move.d [r4+],r3
+ checkr3 7
+
+ move.d [r4+],r3
+ checkr3 2
+
+ move.d [r4+],r3
+ checkr3 ffff1234
+
+ move.d [r4+],r3
+ checkr3 b
+
+ subq 16,r4
+ moveq 22,r0
+ moveq 15,r1
+ clearf zcvn
+ movem r0,[r4]
+ test_cc 0 0 0 0
+ move.d [r4+],r3
+ checkr3 16
+
+ move.d r1,r3
+ checkr3 f
+
+ move.d [r4+],r3
+ checkr3 2
+
+ subq 8,r4
+ moveq 10,r2
+ moveq -17,r0
+ clearf zc
+ setf vn
+ movem r1,[r4]
+ test_cc 1 0 1 0
+ move.d [r4+],r3
+ checkr3 ffffffef
+
+ move.d [r4+],r3
+ checkr3 f
+
+ move.d [r4+],r3
+ checkr3 ffff1234
+
+ move.d y,r4
+ setf zc
+ clearf vn
+ movem [r4+],r3
+ test_cc 0 1 0 1
+ checkr3 f
+
+ move.d r0,r3
+ checkr3 fffffff4
+
+ move.d r1,r3
+ checkr3 d
+
+ move.d r2,r3
+ checkr3 fffffff2
+
+ move.d [r4],r3
+ checkr3 10
+
+ subq 8,r4
+ setf zcvn
+ movem [r4+],r0
+ test_cc 1 1 1 1
+ move.d r0,r3
+ checkr3 fffffff2
+
+ move.d r1,r3
+ checkr3 d
+
+ quit
diff --git a/tests/tcg/cris/check_moveq.c b/tests/tcg/cris/check_moveq.c
new file mode 100644
index 0000000000..80f2dff6ab
--- /dev/null
+++ b/tests/tcg/cris/check_moveq.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+#define cris_moveq(dst, src) \
+ asm volatile ("moveq %1, %0\n" : "=r" (dst) : "i" (src));
+
+
+
+int main(void)
+{
+ int t;
+
+ cris_tst_cc_init();
+ asm volatile ("setf\tzvnc\n");
+ cris_moveq(t, 10);
+ cris_tst_cc(1, 1, 1, 1);
+ if (t != 10)
+ err();
+
+ /* make sure moveq doesn't clobber the zflag. */
+ cris_tst_cc_init();
+ asm volatile ("setf vnc\n");
+ asm volatile ("clearf z\n");
+ cris_moveq(t, 0);
+ cris_tst_cc(1, 0, 1, 1);
+ if (t != 0)
+ err();
+
+ /* make sure moveq doesn't clobber the nflag.
+ Also check large immediates */
+ cris_tst_cc_init();
+ asm volatile ("setf zvc\n");
+ asm volatile ("clearf n\n");
+ cris_moveq(t, -31);
+ cris_tst_cc(0, 1, 1, 1);
+ if (t != -31)
+ err();
+
+ cris_tst_cc_init();
+ asm volatile ("setf nzvc\n");
+ cris_moveq(t, 31);
+ cris_tst_cc(1, 1, 1, 1);
+ if (t != 31)
+ err();
+
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_mover.s b/tests/tcg/cris/check_mover.s
new file mode 100644
index 0000000000..b4db595d64
--- /dev/null
+++ b/tests/tcg/cris/check_mover.s
@@ -0,0 +1,28 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff05\nffff0005\n5\nffffff00\n
+
+; Move between registers. Check that just the subreg is copied.
+
+ .include "testutils.inc"
+ startnostack
+ moveq -30,r3
+ moveq 5,r4
+ move.b r4,r3
+ test_move_cc 0 0 0 0 ; FIXME
+ checkr3 ffffff05
+
+ move.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0005
+
+ move.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq -1,r3
+ moveq 0,r4
+ move.b r4,r3
+ test_move_cc 0 1 0 0
+ checkr3 ffffff00
+
+ quit
diff --git a/tests/tcg/cris/check_moverm.s b/tests/tcg/cris/check_moverm.s
new file mode 100644
index 0000000000..eabc9588d4
--- /dev/null
+++ b/tests/tcg/cris/check_moverm.s
@@ -0,0 +1,45 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 7823fec2\n10231879\n102318fe\n
+
+ .include "testutils.inc"
+ start
+
+ .data
+mem1:
+ .dword 0x12345678
+mem2:
+ .word 0x4567
+mem3:
+ .byte 0x23
+ .dword 0x76543210
+ .byte 0xaa,0x11,0x99
+
+ .text
+ move.d mem1,r2
+ move.d 0x7823fec2,r4
+ setf nzvc
+ move.d r4,[r2+]
+ test_cc 1 1 1 1
+ subq 4,r2
+ move.d [r2],r3
+ checkr3 7823fec2
+
+ move.d mem2,r3
+ move.d 0x45231879,r4
+ clearf nzvc
+ move.w r4,[r3]
+ test_cc 0 0 0 0
+ move.d [r3],r3
+ checkr3 10231879
+
+ move.d mem2,r2
+ moveq -2,r4
+ clearf nc
+ setf zv
+ move.b r4,[r2+]
+ test_cc 0 1 1 0
+ subq 1,r2
+ move.d [r2],r3
+ checkr3 102318fe
+
+ quit
diff --git a/tests/tcg/cris/check_movmp.s b/tests/tcg/cris/check_movmp.s
new file mode 100644
index 0000000000..7fc11f064d
--- /dev/null
+++ b/tests/tcg/cris/check_movmp.s
@@ -0,0 +1,131 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+# Test generic "move Ps,[]" and "move [],Pd" insns; the ones with
+# functionality common to all models.
+
+ .include "testutils.inc"
+ start
+
+ .data
+filler:
+ .byte 0xaa
+ .word 0x4433
+ .dword 0x55778866
+ .byte 0xcc
+
+ .text
+; Test that writing to zero-registers is a nop
+ .if 0
+ ; We used to just ignore the writes, but now an error is emitted. We
+ ; keep the test-code but disabled, in case we need to change this again.
+ move 0xaa,p0
+ move 0x4433,p4
+ move 0x55774433,p8
+ .endif
+
+ moveq -1,r3
+ setf zcvn
+ clear.b r3
+ test_cc 1 1 1 1
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clearf zcvn
+ clear.w r3
+ test_cc 0 0 0 0
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; "Write" using ordinary memory references too.
+ .if 0 ; See ".if 0" above.
+ move.d filler,r6
+ move [r6],p0
+ move [r6],p4
+ move [r6],p8
+ .endif
+
+# ffffff00\nffff0000\n0\nffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; And postincremented.
+ .if 0 ; See ".if 0" above.
+ move [r6+],p0
+ move [r6+],p4
+ move [r6+],p8
+ .endif
+
+# ffffff00\nffff0000\n0\nbb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+; Now see that we can write to the registers too.
+# bb113344\n664433aa\ncc557788\nabcde012\nabcde000\n77880000\n0\n
+; [PC+]
+ move.d filler,r9
+ move 0xbb113344,srp
+ move srp,r3
+ checkr3 bb113344
+
+; [R+]
+ move [r9+],srp
+ move srp,r3
+ checkr3 664433aa
+
+; [R]
+ move [r9],srp
+ move srp,r3
+ checkr3 cc557788
+
+; And check writing to memory, clear and srp.
+
+ move.d filler,r9
+ move 0xabcde012,srp
+ setf zcvn
+ move srp,[r9+]
+ test_cc 1 1 1 1
+ subq 4,r9
+ move.d [r9],r3
+ checkr3 abcde012
+
+ clearf zcvn
+ clear.b [r9]
+ test_cc 0 0 0 0
+ move.d [r9],r3
+ checkr3 abcde000
+
+ addq 2,r9
+ clear.w [r9+]
+ subq 2,r9
+ move.d [r9],r3
+ checkr3 77880000
+
+ clear.d [r9]
+ move.d [r9],r3
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movpmv32.s b/tests/tcg/cris/check_movpmv32.s
new file mode 100644
index 0000000000..daf0970e4a
--- /dev/null
+++ b/tests/tcg/cris/check_movpmv32.s
@@ -0,0 +1,35 @@
+# mach: crisv32
+# output: 11223320\nbb113344\naa557711\n
+
+# Test v32-specific special registers. FIXME: more registers.
+
+ .include "testutils.inc"
+ start
+ .data
+store:
+ .dword 0x11223344
+ .dword 0x77665544
+
+ .text
+ moveq -1,r3
+ move.d store,r4
+ move vr,[r4]
+ move [r4+],mof
+ move mof,r3
+ checkr3 11223320
+
+ moveq -1,r3
+ clearf zcvn
+ move 0xbb113344,mof
+ test_cc 0 0 0 0
+ move mof,r3
+ checkr3 bb113344
+
+ setf zcvn
+ move 0xaa557711,mof
+ test_cc 1 1 1 1
+ move mof,[r4]
+ move.d [r4],r3
+ checkr3 aa557711
+
+ quit
diff --git a/tests/tcg/cris/check_movpr.s b/tests/tcg/cris/check_movpr.s
new file mode 100644
index 0000000000..eef9bdb4fb
--- /dev/null
+++ b/tests/tcg/cris/check_movpr.s
@@ -0,0 +1,28 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: ffffff00\nffff0000\n0\nbb113344\n
+
+# Test generic "move Ps,Rd" and "move Rs,Pd" insns; the ones with
+# functionality common to all models.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ clear.b r3
+ checkr3 ffffff00
+
+ moveq -1,r3
+ clear.w r3
+ checkr3 ffff0000
+
+ moveq -1,r3
+ clear.d r3
+ checkr3 0
+
+ moveq -1,r3
+ move.d 0xbb113344,r4
+ setf zcvn
+ move r4,srp
+ move srp,r3
+ test_cc 1 1 1 1
+ checkr3 bb113344
+ quit
diff --git a/tests/tcg/cris/check_movprv32.s b/tests/tcg/cris/check_movprv32.s
new file mode 100644
index 0000000000..d0d90e1246
--- /dev/null
+++ b/tests/tcg/cris/check_movprv32.s
@@ -0,0 +1,21 @@
+# mach: crisv32
+# output: ffffff20\nbb113344\n
+
+# Test v32-specific special registers. FIXME: more registers.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ setf zcvn
+ move vr,r3
+ test_cc 1 1 1 1
+ checkr3 ffffff20
+
+ moveq -1,r3
+ move.d 0xbb113344,r4
+ clearf cvnz
+ move r4,mof
+ test_cc 0 0 0 0
+ move mof,r3
+ checkr3 bb113344
+ quit
diff --git a/tests/tcg/cris/check_movscr.s b/tests/tcg/cris/check_movscr.s
new file mode 100644
index 0000000000..53c8ce6b50
--- /dev/null
+++ b/tests/tcg/cris/check_movscr.s
@@ -0,0 +1,29 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 42\nffffff85\n7685\nffff8765\n0\n
+
+; Move constant byte, word, dword to register. Check that sign-extension
+; is performed.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ movs.b 0x42,r3
+ checkr3 42
+
+ movs.b 0x85,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffff85
+
+ movs.w 0x7685,r3
+ test_move_cc 0 0 0 0
+ checkr3 7685
+
+ movs.w 0x8765,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff8765
+
+ movs.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movsm.s b/tests/tcg/cris/check_movsm.s
new file mode 100644
index 0000000000..7074336e78
--- /dev/null
+++ b/tests/tcg/cris/check_movsm.s
@@ -0,0 +1,44 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nfffffff5\n5\nfffffff5\n0\n
+
+; Movs between registers. Check that sign-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+
+ .data
+x:
+ .byte 5,-11
+ .word 5,-11
+ .word 0
+
+ start
+ move.d x,r5
+
+ moveq -1,r3
+ movs.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r3
+ movs.b [r5],r3
+ test_move_cc 1 0 0 0
+ addq 1,r5
+ checkr3 fffffff5
+
+ moveq -1,r3
+ movs.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r3
+ movs.w [r5],r3
+ test_move_cc 1 0 0 0
+ addq 2,r5
+ checkr3 fffffff5
+
+ movs.w [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movsr.s b/tests/tcg/cris/check_movsr.s
new file mode 100644
index 0000000000..d1889a7a1b
--- /dev/null
+++ b/tests/tcg/cris/check_movsr.s
@@ -0,0 +1,46 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nfffffff5\n5\nfffffff5\n0\n
+
+; Movs between registers. Check that sign-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r5
+ moveq 5,r4
+ move.b r4,r5
+ moveq -1,r3
+ movs.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.b r4,r5
+ moveq 0,r3
+ movs.b r5,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffff5
+
+ moveq -1,r5
+ moveq 5,r4
+ move.w r4,r5
+ moveq -1,r3
+ movs.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.w r4,r5
+ moveq 0,r3
+ movs.w r5,r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffff5
+
+ moveq 0,r5
+ movs.b r5,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movucr.s b/tests/tcg/cris/check_movucr.s
new file mode 100644
index 0000000000..7c8487d1a2
--- /dev/null
+++ b/tests/tcg/cris/check_movucr.s
@@ -0,0 +1,33 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 42\n85\n7685\n8765\n0\n
+
+; Move constant byte, word, dword to register. Check that zero-extension
+; is performed.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ movu.b 0x42,r3
+ test_move_cc 0 0 0 0
+ checkr3 42
+
+ moveq -1,r3
+ movu.b 0x85,r3
+ test_move_cc 0 0 0 0
+ checkr3 85
+
+ moveq -1,r3
+ movu.w 0x7685,r3
+ test_move_cc 0 0 0 0
+ checkr3 7685
+
+ moveq -1,r3
+ movu.w 0x8765,r3
+ test_move_cc 0 0 0 0
+ checkr3 8765
+
+ movu.b 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movum.s b/tests/tcg/cris/check_movum.s
new file mode 100644
index 0000000000..038e539463
--- /dev/null
+++ b/tests/tcg/cris/check_movum.s
@@ -0,0 +1,40 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nf5\n5\nfff5\n0\n
+
+; Movu between registers. Check that zero-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+
+ .data
+x:
+ .byte 5,-11
+ .word 5,-11
+ .word 0
+
+ start
+ move.d x,r5
+
+ movu.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ movu.b [r5],r3
+ test_move_cc 0 0 0 0
+ addq 1,r5
+ checkr3 f5
+
+ movu.w [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ movu.w [r5],r3
+ test_move_cc 0 0 0 0
+ addq 2,r5
+ checkr3 fff5
+
+ movu.w [r5],r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_movur.s b/tests/tcg/cris/check_movur.s
new file mode 100644
index 0000000000..3ecf475f75
--- /dev/null
+++ b/tests/tcg/cris/check_movur.s
@@ -0,0 +1,45 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 5\nf5\n5\nfff5\n0\n
+
+; Movu between registers. Check that zero-extension is performed and the
+; full register is set.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r5
+ moveq 5,r4
+ move.b r4,r5
+ moveq -1,r3
+ movu.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.b r4,r5
+ moveq -1,r3
+ movu.b r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 f5
+
+ moveq -1,r5
+ moveq 5,r4
+ move.w r4,r5
+ moveq -1,r3
+ movu.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 5
+
+ moveq 0,r5
+ moveq -11,r4
+ move.w r4,r5
+ moveq -1,r3
+ movu.w r5,r3
+ test_move_cc 0 0 0 0
+ checkr3 fff5
+
+ movu.w 0,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_mulv32.s b/tests/tcg/cris/check_mulv32.s
new file mode 100644
index 0000000000..f379358765
--- /dev/null
+++ b/tests/tcg/cris/check_mulv32.s
@@ -0,0 +1,51 @@
+# mach: crisv32
+# output: fffffffe\n
+# output: ffffffff\n
+# output: fffffffe\n
+# output: 1\n
+# output: fffffffe\n
+# output: ffffffff\n
+# output: fffffffe\n
+# output: 1\n
+
+; Check that carry is not modified on v32.
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ setf c
+ muls.d r4,r3
+ test_cc 1 0 0 1
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ setf c
+ mulu.d r4,r3
+ test_cc 0 0 1 1
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ moveq -1,r3
+ moveq 2,r4
+ clearf c
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ clearf c
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ quit
diff --git a/tests/tcg/cris/check_mulx.s b/tests/tcg/cris/check_mulx.s
new file mode 100644
index 0000000000..d43241a6f5
--- /dev/null
+++ b/tests/tcg/cris/check_mulx.s
@@ -0,0 +1,246 @@
+# mach: crisv10 crisv32
+# output: fffffffe\nffffffff\nfffffffe\n1\nfffffffe\nffffffff\nfffffffe\n1\nfffe0001\n0\nfffe0001\n0\n1\n0\n1\nfffffffe\n193eade2\n277e3a49\n193eade2\n277e3a49\nfffffffe\nffffffff\n1fffe\n0\nfffffffe\nffffffff\n1fffe\n0\n1\n0\nfffe0001\n0\nfdbdade2\nffffffff\n420fade2\n0\nfffffffe\nffffffff\n1fe\n0\nfffffffe\nffffffff\n1fe\n0\n1\n0\nfe01\n0\n1\n0\nfe01\n0\nffffd9e2\nffffffff\n2be2\n0\n0\n0\n0\n0\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq 2,r4
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ moveq 2,r3
+ moveq -1,r4
+ muls.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 1
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ muls.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ mulu.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ muls.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.d r4,r3
+ test_cc 1 0 1 0
+ checkr3 1
+ move mof,r3
+ checkr3 fffffffe
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 193eade2
+ move mof,r3
+ checkr3 277e3a49
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.d r4,r3
+ test_cc 0 0 1 0
+ checkr3 193eade2
+ move mof,r3
+ checkr3 277e3a49
+
+ move.d 0xffff,r3
+ moveq 2,r4
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+ move mof,r3
+ checkr3 0
+
+ moveq 2,r3
+ move.d 0xffff,r4
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fffe
+ move mof,r3
+ checkr3 0
+
+ move.d 0xffff,r4
+ move.d r4,r3
+ muls.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 fffe0001
+ move mof,r3
+ checkr3 0
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fdbdade2
+ move mof,r3
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 420fade2
+ move mof,r3
+ checkr3 0
+
+ move.d 0xff,r3
+ moveq 2,r4
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq -1,r3
+ moveq 2,r4
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fe
+ move mof,r3
+ checkr3 0
+
+ moveq 2,r3
+ moveq -1,r4
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+ move mof,r3
+ checkr3 ffffffff
+
+ moveq 2,r3
+ moveq -1,r4
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1fe
+ move mof,r3
+ checkr3 0
+
+ move.d 0xff,r4
+ move.d r4,r3
+ muls.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ moveq -1,r4
+ move.d r4,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 fe01
+ move mof,r3
+ checkr3 0
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ muls.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+ move mof,r3
+ checkr3 0
+
+ move.d 0xfeda49ff,r4
+ move.d r4,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 fe01
+ move mof,r3
+ checkr3 0
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ muls.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 ffffd9e2
+ move mof,r3
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ mulu.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 2be2
+ move mof,r3
+ checkr3 0
+
+ moveq 0,r3
+ move.d 0xf87f4aeb,r4
+ muls.d r4,r3
+ test_cc 0 1 0 0
+ checkr3 0
+ move mof,r3
+ checkr3 0
+
+ move.d 0xf87f4aeb,r3
+ moveq 0,r4
+ mulu.d r4,r3
+ test_cc 0 1 0 0
+ checkr3 0
+ move mof,r3
+ checkr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_neg.s b/tests/tcg/cris/check_neg.s
new file mode 100644
index 0000000000..963c4b6f5e
--- /dev/null
+++ b/tests/tcg/cris/check_neg.s
@@ -0,0 +1,104 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: ffffffff\nffffffff\n0\n80000000\n1\nba987655\nffff\nffff\n0\n89ab8000\nffff0001\n45677655\nff\nff\n0\n89abae80\nffffff01\n45678955\n
+
+ .include "testutils.inc"
+ start
+ moveq 0,r3
+ moveq 1,r4
+ neg.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+;; FIXME: this was wrong.
+ moveq 0,r3
+ neg.d r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x80000000,r3
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 80000000
+
+ moveq -1,r3
+ neg.d r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0x456789ab,r3
+ neg.d r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ba987655
+
+ moveq 0,r3
+ moveq 1,r4
+ neg.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.w r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff
+
+ moveq 0,r3
+ neg.w r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x89ab8000,r3
+ neg.w r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 89ab8000
+
+ moveq -1,r3
+ neg.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0001
+
+ move.d 0x456789ab,r3
+ neg.w r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 45677655
+
+ moveq 0,r3
+ moveq 1,r4
+ neg.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ff
+
+ moveq 1,r3
+ moveq 0,r4
+ neg.b r3,r3
+ test_move_cc 1 0 0 0
+ checkr3 ff
+
+ moveq 0,r3
+ neg.b r3,r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+;; FIXME: was wrong.
+ move.d 0x89abae80,r3
+ neg.b r3,r3
+ test_move_cc 1 0 0 1
+ checkr3 89abae80
+
+ moveq -1,r3
+ neg.b r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffffff01
+
+ move.d 0x456789ab,r3
+ neg.b r3,r3
+ test_move_cc 0 0 0 0
+ checkr3 45678955
+
+ quit
diff --git a/tests/tcg/cris/check_not.s b/tests/tcg/cris/check_not.s
new file mode 100644
index 0000000000..33bcf155e5
--- /dev/null
+++ b/tests/tcg/cris/check_not.s
@@ -0,0 +1,31 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: fffffffe\nfffffffd\nffff0f00\n0\n87ecbbad\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffe
+
+ moveq 2,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 fffffffd
+
+ move.d 0xf0ff,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 ffff0f00
+
+ moveq -1,r3
+ not r3
+ test_move_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x78134452,r3
+ not r3
+ test_move_cc 1 0 0 0
+ checkr3 87ecbbad
+
+ quit
diff --git a/tests/tcg/cris/check_openpf1.c b/tests/tcg/cris/check_openpf1.c
new file mode 100644
index 0000000000..fdcf4c5c3f
--- /dev/null
+++ b/tests/tcg/cris/check_openpf1.c
@@ -0,0 +1,38 @@
+/* Check that --sysroot is applied to open(2).
+#sim: --sysroot=@exedir@
+
+ We assume, with EXE being the name of the executable:
+ - The simulator executes with cwd the same directory where the executable
+ is located (so argv[0] contains a plain filename without directory
+ components).
+ - There's no /EXE on the host file system. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+int main (int argc, char *argv[])
+{
+ char *fnam = argv[0];
+ FILE *f;
+ if (argv[0][0] != '/')
+ {
+ fnam = malloc (strlen (argv[0]) + 2);
+ if (fnam == NULL)
+ abort ();
+ strcpy (fnam, "/");
+ strcat (fnam, argv[0]);
+ }
+
+ f = fopen (fnam, "rb");
+ if (f == NULL)
+ abort ();
+ fclose(f);
+
+ /* Cover another execution path. */
+ if (fopen ("/nonexistent", "rb") != NULL
+ || errno != ENOENT)
+ abort ();
+ printf ("pass\n");
+ return 0;
+}
diff --git a/tests/tcg/cris/check_openpf2.c b/tests/tcg/cris/check_openpf2.c
new file mode 100644
index 0000000000..5d56189f8e
--- /dev/null
+++ b/tests/tcg/cris/check_openpf2.c
@@ -0,0 +1,16 @@
+/* Check that the simulator has chdir:ed to the --sysroot argument
+#sim: --sysroot=@srcdir@
+ (or that --sysroot is applied to relative file paths). */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+int main (int argc, char *argv[])
+{
+ FILE *f = fopen ("check_openpf2.c", "rb");
+ if (f == NULL)
+ abort ();
+ fclose(f);
+ printf ("pass\n");
+ return 0;
+}
diff --git a/tests/tcg/cris/check_openpf3.c b/tests/tcg/cris/check_openpf3.c
new file mode 100644
index 0000000000..557adee92d
--- /dev/null
+++ b/tests/tcg/cris/check_openpf3.c
@@ -0,0 +1,49 @@
+/* Basic file operations (rename, unlink); once without sysroot. We
+ also test that the simulator has chdir:ed to PREFIX, when defined. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef PREFIX
+#define PREFIX
+#endif
+
+void err (const char *s)
+{
+ perror (s);
+ abort ();
+}
+
+int main (int argc, char *argv[])
+{
+ FILE *f;
+ struct stat buf;
+
+ unlink (PREFIX "testfoo2.tmp");
+
+ f = fopen ("testfoo1.tmp", "w");
+ if (f == NULL)
+ err ("open");
+ fclose (f);
+
+ if (rename (PREFIX "testfoo1.tmp", PREFIX "testfoo2.tmp") != 0)
+ err ("rename");
+
+ if (stat (PREFIX "testfoo2.tmp", &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ err ("stat 1");
+
+ if (stat ("testfoo2.tmp", &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ err ("stat 2");
+
+ if (unlink (PREFIX "testfoo2.tmp") != 0)
+ err ("unlink");
+
+ printf ("pass\n");
+ return 0;
+}
diff --git a/tests/tcg/cris/check_openpf4.c b/tests/tcg/cris/check_openpf4.c
new file mode 100644
index 0000000000..8bbee41a64
--- /dev/null
+++ b/tests/tcg/cris/check_openpf4.c
@@ -0,0 +1,5 @@
+/* Basic file operations, now *with* sysroot.
+#sim: --sysroot=@exedir@
+*/
+#define PREFIX "/"
+#include "check_openpf3.c"
diff --git a/tests/tcg/cris/check_openpf5.c b/tests/tcg/cris/check_openpf5.c
new file mode 100644
index 0000000000..1f86ea283d
--- /dev/null
+++ b/tests/tcg/cris/check_openpf5.c
@@ -0,0 +1,56 @@
+/* Check that TRT happens when error on too many opened files.
+#notarget: cris*-*-elf
+#sim: --sysroot=@exedir@
+*/
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+int main (int argc, char *argv[])
+{
+ int i;
+ int filemax;
+
+#ifdef OPEN_MAX
+ filemax = OPEN_MAX;
+#else
+ filemax = sysconf (_SC_OPEN_MAX);
+#endif
+
+ char *fn = malloc (strlen (argv[0]) + 2);
+ if (fn == NULL)
+ abort ();
+ strcpy (fn, "/");
+ strcat (fn, argv[0]);
+
+ for (i = 0; i < filemax + 1; i++)
+ {
+ if (open (fn, O_RDONLY) < 0)
+ {
+ /* Shouldn't happen too early. */
+ if (i < filemax - 3 - 1)
+ {
+ fprintf (stderr, "i: %d\n", i);
+ abort ();
+ }
+ if (errno != EMFILE)
+ {
+ perror ("open");
+ abort ();
+ }
+ goto ok;
+ }
+ }
+ abort ();
+
+ok:
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_orc.s b/tests/tcg/cris/check_orc.s
new file mode 100644
index 0000000000..c733f036a2
--- /dev/null
+++ b/tests/tcg/cris/check_orc.s
@@ -0,0 +1,71 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ or.d 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.d 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ or.d 0xff0f,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r3
+ or.d -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ or.d 0x5432f789,r3
+ test_move_cc 0 0 0 0
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ or.w 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0003
+
+ moveq 2,r3
+ or.w 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ or.w 0xff5f,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ or.w 0xf789,r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ or.b 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.b 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfa3,r3
+ or.b 0x4a,r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x78134453,r3
+ or.b 0x89,r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_orm.s b/tests/tcg/cris/check_orm.s
new file mode 100644
index 0000000000..ee723a6aa0
--- /dev/null
+++ b/tests/tcg/cris/check_orm.s
@@ -0,0 +1,75 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword 2,1,0xff0f,-1,0x5432f789
+ .word 2,1,0xff5f,0xf789
+ .byte 2,1,0x4a,0x89
+
+ start
+ moveq 1,r3
+ move.d x,r5
+ or.d [r5+],r3
+ checkr3 3
+
+ moveq 2,r3
+ or.d [r5],r3
+ addq 4,r5
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ or.d [r5+],r3
+ checkr3 ffff
+
+ moveq -1,r3
+ or.d [r5+],r3
+ checkr3 ffffffff
+
+ move.d 0x78134452,r3
+ or.d [r5+],r3
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ or.w [r5+],r3
+ checkr3 ffff0003
+
+ moveq 2,r3
+ or.w [r5],r3
+ addq 2,r5
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ or.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x78134452,r3
+ or.w [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ or.b [r5+],r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ or.b [r5],r3
+ addq 1,r5
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfa3,r3
+ or.b [r5+],r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x78134453,r3
+ or.b [r5],r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_orq.s b/tests/tcg/cris/check_orq.s
new file mode 100644
index 0000000000..5060edc72d
--- /dev/null
+++ b/tests/tcg/cris/check_orq.s
@@ -0,0 +1,41 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffffffff\nffffffff\n1f\nffffffe0\n7813445e\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ orq 2,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ orq 1,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xf0ff,r3
+ orq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 0,r3
+ orq -1,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ moveq 0,r3
+ orq 31,r3
+ test_move_cc 0 0 0 0
+ checkr3 1f
+
+ moveq 0,r3
+ orq -32,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffe0
+
+ move.d 0x78134452,r3
+ orq 12,r3
+ test_move_cc 0 0 0 0
+ checkr3 7813445e
+
+ quit
diff --git a/tests/tcg/cris/check_orr.s b/tests/tcg/cris/check_orr.s
new file mode 100644
index 0000000000..a514c11bc9
--- /dev/null
+++ b/tests/tcg/cris/check_orr.s
@@ -0,0 +1,84 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 3\n3\nffff\nffffffff\n7c33f7db\nffff0003\n3\nfedaffff\n7813f7db\n3\n3\nfeb\n781344db\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ moveq 2,r4
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ moveq 1,r4
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xff0f,r4
+ move.d 0xf0ff,r3
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff
+
+ moveq -1,r4
+ move.d r4,r3
+ or.d r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 ffffffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ or.d r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 7c33f7db
+
+ move.d 0xffff0001,r3
+ moveq 2,r4
+ or.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 ffff0003
+
+ moveq 2,r3
+ move.d 0xffff0001,r4
+ or.w r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0xfedaffaf,r3
+ move.d 0xffffff5f,r4
+ or.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 fedaffff
+
+ move.d 0x5432f789,r4
+ move.d 0x78134452,r3
+ or.w r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 7813f7db
+
+ moveq 1,r3
+ move.d 0xffffff02,r4
+ or.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ moveq 2,r3
+ moveq 1,r4
+ or.b r4,r3
+ test_move_cc 0 0 0 0
+ checkr3 3
+
+ move.d 0x4a,r4
+ move.d 0xfa3,r3
+ or.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 feb
+
+ move.d 0x5432f789,r4
+ move.d 0x78134453,r3
+ or.b r4,r3
+ test_move_cc 1 0 0 0
+ checkr3 781344db
+
+ quit
diff --git a/tests/tcg/cris/check_ret.s b/tests/tcg/cris/check_ret.s
new file mode 100644
index 0000000000..b44fb25933
--- /dev/null
+++ b/tests/tcg/cris/check_ret.s
@@ -0,0 +1,25 @@
+# mach: crisv3 crisv8 crisv10
+# output: 3\n
+
+# Test that ret works.
+
+ .include "testutils.inc"
+ start
+x:
+ moveq 0,r3
+ jsr z
+w:
+ quit
+y:
+ addq 1,r3
+ checkr3 3
+ quit
+
+z:
+ addq 1,r3
+ move srp,r2
+ add.d y-w,r2
+ move r2,srp
+ ret
+ addq 1,r3
+ quit
diff --git a/tests/tcg/cris/check_scc.s b/tests/tcg/cris/check_scc.s
new file mode 100644
index 0000000000..4a8674cc1a
--- /dev/null
+++ b/tests/tcg/cris/check_scc.s
@@ -0,0 +1,95 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n1\n0\n1\n0\n1\n0\n1\n0\n0\n1\n0\n1\n1\n0\n1\n0\n0\n1\n1\n0\n1\n1\n0\n
+
+ .include "testutils.inc"
+
+ .macro lcheckr3 v
+ move $ccs, $r9
+ checkr3 \v
+ move $r9, $ccs
+ .endm
+
+ start
+ clearf nzvc
+ scc r3
+ lcheckr3 1
+ scs r3
+ lcheckr3 0
+ sne r3
+ lcheckr3 1
+ seq r3
+ lcheckr3 0
+ svc r3
+ lcheckr3 1
+ svs r3
+ lcheckr3 0
+ spl r3
+ lcheckr3 1
+ smi r3
+ lcheckr3 0
+ sls r3
+ lcheckr3 0
+ shi r3
+ lcheckr3 1
+ sge r3
+ lcheckr3 1
+ slt r3
+ lcheckr3 0
+ sgt r3
+ lcheckr3 1
+ sle r3
+ lcheckr3 0
+ sa r3
+ lcheckr3 1
+ setf nzvc
+ scc r3
+ lcheckr3 0
+ scs r3
+ lcheckr3 1
+ sne r3
+ lcheckr3 0
+ svc r3
+ lcheckr3 0
+ svs r3
+ lcheckr3 1
+ spl r3
+ lcheckr3 0
+ smi r3
+ lcheckr3 1
+ sls r3
+ lcheckr3 1
+ shi r3
+ lcheckr3 0
+ sge r3
+ lcheckr3 1
+ slt r3
+ lcheckr3 0
+ sgt r3
+ lcheckr3 0
+ sle r3
+ lcheckr3 1
+ sa r3
+ lcheckr3 1
+ clearf n
+ sge r3
+ lcheckr3 0
+ slt r3
+ lcheckr3 1
+
+ .if 1 ;..asm.arch.cris.v32
+ setf p
+ ssb r3
+ .else
+ moveq 1,r3
+ .endif
+ lcheckr3 1
+
+ .if 1 ;..asm.arch.cris.v32
+ clearf p
+ ssb r3
+ .else
+ moveq 0,r3
+ .endif
+ lcheckr3 0
+
+ quit
diff --git a/tests/tcg/cris/check_settls1.c b/tests/tcg/cris/check_settls1.c
new file mode 100644
index 0000000000..69d202652a
--- /dev/null
+++ b/tests/tcg/cris/check_settls1.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+
+#ifndef SYS_set_thread_area
+#define SYS_set_thread_area 243
+#endif
+
+int main (void)
+{
+ unsigned long tp, old_tp;
+ int ret;
+
+ asm volatile ("move $pid,%0" : "=r" (old_tp));
+ old_tp &= ~0xff;
+
+ ret = syscall (SYS_set_thread_area, 0xf0);
+ if (ret != -1 || errno != EINVAL) {
+ syscall (SYS_set_thread_area, old_tp);
+ perror ("Invalid thread area accepted:");
+ abort();
+ }
+
+ ret = syscall (SYS_set_thread_area, 0xeddeed00);
+ if (ret != 0) {
+ perror ("Valid thread area not accepted: ");
+ abort ();
+ }
+
+ asm volatile ("move $pid,%0" : "=r" (tp));
+ tp &= ~0xff;
+ syscall (SYS_set_thread_area, old_tp);
+
+ if (tp != 0xeddeed00) {
+ * (volatile int *) 0 = 0;
+ perror ("tls2");
+ abort ();
+ }
+
+ printf ("pass\n");
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/cris/check_sigalrm.c b/tests/tcg/cris/check_sigalrm.c
new file mode 100644
index 0000000000..39fa8d9bac
--- /dev/null
+++ b/tests/tcg/cris/check_sigalrm.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#define MAGIC (0xdeadbeef)
+
+int s = 0;
+void sighandler(int sig)
+{
+ s = MAGIC;
+}
+
+int main(int argc, char **argv)
+{
+ int p;
+
+ p = getpid();
+ signal(SIGALRM, sighandler);
+ kill(p, SIGALRM);
+ if (s != MAGIC)
+ return EXIT_FAILURE;
+
+ printf ("passed\n");
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/cris/check_stat1.c b/tests/tcg/cris/check_stat1.c
new file mode 100644
index 0000000000..2e2cae51df
--- /dev/null
+++ b/tests/tcg/cris/check_stat1.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (void)
+{
+ struct stat buf;
+
+ if (stat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_stat2.c b/tests/tcg/cris/check_stat2.c
new file mode 100644
index 0000000000..e36172ed25
--- /dev/null
+++ b/tests/tcg/cris/check_stat2.c
@@ -0,0 +1,20 @@
+/*
+#notarget: cris*-*-elf
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (void)
+{
+ struct stat buf;
+
+ if (lstat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_stat3.c b/tests/tcg/cris/check_stat3.c
new file mode 100644
index 0000000000..36a9d5d274
--- /dev/null
+++ b/tests/tcg/cris/check_stat3.c
@@ -0,0 +1,25 @@
+/* Simulator options:
+#sim: --sysroot=@exedir@
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+ char path[1024] = "/";
+ struct stat buf;
+
+ strncat(path, argv[0], sizeof(path) - 2);
+ if (stat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ if (stat (path, &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_stat4.c b/tests/tcg/cris/check_stat4.c
new file mode 100644
index 0000000000..04f21fe7c4
--- /dev/null
+++ b/tests/tcg/cris/check_stat4.c
@@ -0,0 +1,27 @@
+/* Simulator options:
+#notarget: cris*-*-elf
+#sim: --sysroot=@exedir@
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main (int argc, char *argv[])
+{
+ char path[1024] = "/";
+ struct stat buf;
+
+ strncat(path, argv[0], sizeof(path) - 2);
+ if (lstat (".", &buf) != 0
+ || !S_ISDIR (buf.st_mode))
+ abort ();
+ if (lstat (path, &buf) != 0
+ || !S_ISREG (buf.st_mode))
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_subc.s b/tests/tcg/cris/check_subc.s
new file mode 100644
index 0000000000..e34b5448e2
--- /dev/null
+++ b/tests/tcg/cris/check_subc.s
@@ -0,0 +1,87 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ start
+
+ moveq -1,r3
+ sub.d -2,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ sub.d 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.d -0xffff,r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq -1,r3
+ sub.d 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ sub.d -0x5432f789,r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ sub.w -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ sub.w 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ sub.w 1,r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ sub.w 0x877,r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ sub.b -2,r3
+ test_cc 0 0 0 0
+ checkr3 ffffff01
+
+ moveq 2,r3
+ sub.b 1,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ sub.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ sub.b 1,r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ sub.b 0x77,r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649282,r3
+ sub.b 0x82,r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/tests/tcg/cris/check_subm.s b/tests/tcg/cris/check_subm.s
new file mode 100644
index 0000000000..e07ea02dd4
--- /dev/null
+++ b/tests/tcg/cris/check_subm.s
@@ -0,0 +1,96 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ .data
+x:
+ .dword -2,1,-0xffff,1,-0x5432f789
+ .word -2,1,1,0x877
+ .byte -2,1,0x77
+ .byte 0x22
+
+ start
+ moveq -1,r3
+ move.d x,r5
+ sub.d [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ sub.d [r5],r3
+ test_cc 0 0 0 0
+ addq 4,r5
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.d [r5+],r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq -1,r3
+ sub.d [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x78134452,r3
+ sub.d [r5+],r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ sub.w [r5],r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ sub.w [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d 0x78134452,r3
+ sub.w [r5+],r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ sub.b [r5],r3
+ test_cc 0 0 0 0
+ addq 1,r5
+ checkr3 ffffff01
+
+ moveq 2,r3
+ sub.b [r5],r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xff,r3
+ sub.b [r5],r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d 0xfeda49ff,r3
+ sub.b [r5+],r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d 0x78134452,r3
+ sub.b [r5+],r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649222,r3
+ sub.b [r5],r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/tests/tcg/cris/check_subq.s b/tests/tcg/cris/check_subq.s
new file mode 100644
index 0000000000..9e34fa31ab
--- /dev/null
+++ b/tests/tcg/cris/check_subq.s
@@ -0,0 +1,52 @@
+# mach: crisv3 crisv8 crisv10 crisv32
+# output: 0\nffffffff\nfffffffe\nffff\nff\n56788f9\n56788d9\n567889a\n0\n7ffffffc\n
+
+ .include "testutils.inc"
+ start
+ moveq 1,r3
+ subq 1,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ subq 1,r3
+ test_cc 1 0 0 1
+ checkr3 ffffffff
+
+ subq 1,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d 0x10000,r3
+ subq 1,r3
+ test_cc 0 0 0 0
+ checkr3 ffff
+
+ move.d 0x100,r3
+ subq 1,r3
+ test_cc 0 0 0 0
+ checkr3 ff
+
+ move.d 0x5678900,r3
+ subq 7,r3
+ test_cc 0 0 0 0
+ checkr3 56788f9
+
+ subq 32,r3
+ test_cc 0 0 0 0
+ checkr3 56788d9
+
+ subq 63,r3
+ test_cc 0 0 0 0
+ checkr3 567889a
+
+ move.d 34,r3
+ subq 34,r3
+ test_cc 0 1 0 0
+ checkr3 0
+
+ move.d 0x80000024,r3
+ subq 40,r3
+ test_cc 0 0 1 0
+ checkr3 7ffffffc
+
+ quit
diff --git a/tests/tcg/cris/check_subr.s b/tests/tcg/cris/check_subr.s
new file mode 100644
index 0000000000..742fbc8915
--- /dev/null
+++ b/tests/tcg/cris/check_subr.s
@@ -0,0 +1,102 @@
+# mach: crisv0 crisv3 crisv8 crisv10 crisv32
+# output: 1\n1\n1fffe\nfffffffe\ncc463bdb\nffff0001\n1\nfffe\nfedafffe\n78133bdb\nffffff01\n1\nfe\nfeda49fe\n781344db\n85649200\n
+
+ .include "testutils.inc"
+ start
+ moveq -1,r3
+ moveq -2,r4
+ sub.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.d r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ sub.d r4,r3
+ test_cc 0 0 0 1
+ checkr3 1fffe
+
+ moveq 1,r4
+ moveq -1,r3
+ sub.d r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffffffe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.d r4,r3
+ test_cc 1 0 1 1
+ checkr3 cc463bdb
+
+ moveq -1,r3
+ moveq -2,r4
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffff0001
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d 0xffff,r3
+ move.d -0xffff,r4
+ sub.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fffe
+
+ move.d 0xfedaffff,r3
+ move.d -0xfedaffff,r4
+ sub.w r4,r3
+ test_cc 1 0 0 0
+ checkr3 fedafffe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.w r4,r3
+ test_cc 0 0 0 0
+ checkr3 78133bdb
+
+ moveq -1,r3
+ moveq -2,r4
+ sub.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 ffffff01
+
+ moveq 2,r3
+ moveq 1,r4
+ sub.b r4,r3
+ test_cc 0 0 0 0
+ checkr3 1
+
+ move.d -0xff,r4
+ move.d 0xff,r3
+ sub.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 fe
+
+ move.d -0xfeda49ff,r4
+ move.d 0xfeda49ff,r3
+ sub.b r4,r3
+ test_cc 1 0 0 0
+ checkr3 feda49fe
+
+ move.d -0x5432f789,r4
+ move.d 0x78134452,r3
+ sub.b r4,r3
+ test_cc 1 0 0 1
+ checkr3 781344db
+
+ move.d 0x85649222,r3
+ move.d 0x77445622,r4
+ sub.b r4,r3
+ test_cc 0 1 0 0
+ checkr3 85649200
+
+ quit
diff --git a/tests/tcg/cris/check_swap.c b/tests/tcg/cris/check_swap.c
new file mode 100644
index 0000000000..f851cbcef1
--- /dev/null
+++ b/tests/tcg/cris/check_swap.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "sys.h"
+#include "crisutils.h"
+
+#define N 8
+#define W 4
+#define B 2
+#define R 1
+
+static inline int cris_swap(const int mode, int x)
+{
+ switch (mode)
+ {
+ case N: asm ("swapn\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W: asm ("swapw\t%0\n" : "+r" (x) : "0" (x)); break;
+ case B: asm ("swapb\t%0\n" : "+r" (x) : "0" (x)); break;
+ case R: asm ("swapr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case B|R: asm ("swapbr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W|R: asm ("swapwr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W|B: asm ("swapwb\t%0\n" : "+r" (x) : "0" (x)); break;
+ case W|B|R: asm ("swapwbr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|R: asm ("swapnr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|B: asm ("swapnb\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|B|R: asm ("swapnbr\t%0\n" : "+r" (x) : "0" (x)); break;
+ case N|W: asm ("swapnw\t%0\n" : "+r" (x) : "0" (x)); break;
+ default:
+ err();
+ break;
+ }
+ return x;
+}
+
+/* Made this a macro to be able to pick up the location of the errors. */
+#define verify_swap(mode, val, expected, n, z) \
+do { \
+ int r; \
+ cris_tst_cc_init(); \
+ r = cris_swap(mode, val); \
+ cris_tst_mov_cc(n, z); \
+ if (r != expected) \
+ err(); \
+} while(0)
+
+void check_swap(void)
+{
+ /* Some of these numbers are borrowed from GDB's cris sim
+ testsuite. */
+ if (cris_swap(N, 0) != 0xffffffff)
+ err();
+ if (cris_swap(W, 0x12345678) != 0x56781234)
+ err();
+ if (cris_swap(B, 0x12345678) != 0x34127856)
+ err();
+
+ verify_swap(R, 0x78134452, 0x1ec8224a, 0, 0);
+ verify_swap(B, 0x78134452, 0x13785244, 0, 0);
+ verify_swap(B|R, 0x78134452, 0xc81e4a22, 1, 0);
+ verify_swap(W, 0x78134452, 0x44527813, 0, 0);
+ verify_swap(W|R, 0x78134452, 0x224a1ec8, 0, 0);
+ verify_swap(W|B|R, 0x78134452, 0x4a22c81e, 0, 0);
+ verify_swap(N, 0x78134452, 0x87ecbbad, 1, 0);
+ verify_swap(N|R, 0x78134452, 0xe137ddb5, 1, 0);
+ verify_swap(N|B, 0x78134452, 0xec87adbb, 1, 0);
+ verify_swap(N|B|R, 0x78134452, 0x37e1b5dd, 0, 0);
+ verify_swap(N|W, 0x78134452, 0xbbad87ec, 1, 0);
+ verify_swap(N|B|R, 0xffffffff, 0, 0, 1);
+}
+
+int main(void)
+{
+ check_swap();
+ pass();
+ return 0;
+}
diff --git a/tests/tcg/cris/check_time1.c b/tests/tcg/cris/check_time1.c
new file mode 100644
index 0000000000..3fcf0e1535
--- /dev/null
+++ b/tests/tcg/cris/check_time1.c
@@ -0,0 +1,46 @@
+/* Basic time functionality test: check that milliseconds are
+ incremented for each syscall (does not work on host). */
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdlib.h>
+
+void err (const char *s)
+{
+ perror (s);
+ abort ();
+}
+
+int
+main (void)
+{
+ struct timeval t_m = {0, 0};
+ struct timezone t_z = {0, 0};
+ struct timeval t_m1 = {0, 0};
+ int i;
+
+ if (gettimeofday (&t_m, &t_z) != 0)
+ err ("gettimeofday");
+
+ for (i = 1; i < 10000; i++)
+ if (gettimeofday (&t_m1, NULL) != 0)
+ err ("gettimeofday 1");
+ else
+ if (t_m1.tv_sec * 1000000 + t_m1.tv_usec
+ != (t_m.tv_sec * 1000000 + t_m.tv_usec + i * 1000))
+ {
+ fprintf (stderr, "t0 (%ld, %ld), i %d, t1 (%ld, %ld)\n",
+ t_m.tv_sec, t_m.tv_usec, i, t_m1.tv_sec, t_m1.tv_usec);
+ abort ();
+ }
+
+ if (time (NULL) != t_m1.tv_sec)
+ {
+ fprintf (stderr, "time != gettod\n");
+ abort ();
+ }
+
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_time2.c b/tests/tcg/cris/check_time2.c
new file mode 100644
index 0000000000..20b69b4f60
--- /dev/null
+++ b/tests/tcg/cris/check_time2.c
@@ -0,0 +1,18 @@
+/* CB_SYS_time doesn't implement the Linux time syscall; the return
+ value isn't written to the argument. */
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ time_t x = (time_t) -1;
+ time_t t = time (&x);
+
+ if (t == (time_t) -1 || t != x)
+ abort ();
+ printf ("pass\n");
+ exit (0);
+}
diff --git a/tests/tcg/cris/check_xarith.s b/tests/tcg/cris/check_xarith.s
new file mode 100644
index 0000000000..80038b2ab9
--- /dev/null
+++ b/tests/tcg/cris/check_xarith.s
@@ -0,0 +1,72 @@
+
+.include "testutils.inc"
+
+ start
+
+ moveq -1, $r0
+ moveq 0, $r1
+ addq 1, $r0
+ ax
+ addq 0, $r1
+
+ move.d $r0, $r3
+ checkr3 0
+ move.d $r1, $r3
+ checkr3 1
+
+ move.d 0, $r0
+ moveq -1, $r1
+ subq 1, $r0
+ ax
+ subq 0, $r1
+
+ move.d $r0, $r3
+ checkr3 ffffffff
+ move.d $r1, $r3
+ checkr3 fffffffe
+
+
+ moveq -1, $r0
+ moveq -1, $r1
+ cmpq -1, $r0
+ ax
+ cmpq -1, $r1
+ beq 1f
+ nop
+ fail
+1:
+ cmpq 0, $r0
+ ax
+ cmpq -1, $r1
+ bne 1f
+ nop
+ fail
+1:
+
+ ;; test for broken X sequence, run it several times.
+ moveq 8, $r0
+1:
+ moveq 0, $r3
+ move.d $r0, $r1
+ andq 1, $r1
+ lslq 4, $r1
+ moveq 1, $r2
+ or.d $r1, $r2
+ ba 2f
+ move $r2, $ccs
+2:
+ addq 0, $r3
+ move.d $r0, $r4
+ move.d $r1, $r5
+ move.d $r2, $r6
+ move.d $r3, $r7
+ lsrq 4, $r1
+ move.d $r1, $r8
+ xor $r1, $r3
+ checkr3 0
+ subq 1, $r0
+ bne 1b
+ nop
+
+ pass
+ quit
diff --git a/tests/tcg/cris/crisutils.h b/tests/tcg/cris/crisutils.h
new file mode 100644
index 0000000000..29b71cd7b9
--- /dev/null
+++ b/tests/tcg/cris/crisutils.h
@@ -0,0 +1,71 @@
+static char *tst_cc_loc = NULL;
+
+#define cris_tst_cc_init() \
+do { tst_cc_loc = "test_cc failed at " CURRENT_LOCATION; } while(0)
+
+/* We need a real symbol to signal error. */
+void _err(void) {
+ if (!tst_cc_loc)
+ tst_cc_loc = "tst_cc_failed\n";
+ _fail(tst_cc_loc);
+}
+
+static inline void cris_tst_cc_n1(void)
+{
+ asm volatile ("bpl _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_n0(void)
+{
+ asm volatile ("bmi _err\n"
+ "nop\n");
+}
+
+static inline void cris_tst_cc_z1(void)
+{
+ asm volatile ("bne _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_z0(void)
+{
+ asm volatile ("beq _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_v1(void)
+{
+ asm volatile ("bvc _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_v0(void)
+{
+ asm volatile ("bvs _err\n"
+ "nop\n");
+}
+
+static inline void cris_tst_cc_c1(void)
+{
+ asm volatile ("bcc _err\n"
+ "nop\n");
+}
+static inline void cris_tst_cc_c0(void)
+{
+ asm volatile ("bcs _err\n"
+ "nop\n");
+}
+
+static inline void cris_tst_mov_cc(int n, int z)
+{
+ if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
+ if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
+ asm volatile ("" : : "g" (_err));
+}
+
+static inline void cris_tst_cc(const int n, const int z,
+ const int v, const int c)
+{
+ if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
+ if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
+ if (v) cris_tst_cc_v1(); else cris_tst_cc_v0();
+ if (c) cris_tst_cc_c1(); else cris_tst_cc_c0();
+ asm volatile ("" : : "g" (_err));
+}
diff --git a/tests/tcg/cris/crt.s b/tests/tcg/cris/crt.s
new file mode 100644
index 0000000000..af027d7475
--- /dev/null
+++ b/tests/tcg/cris/crt.s
@@ -0,0 +1,13 @@
+ .data
+_stack_start:
+ .space 8192, 0
+_stack_end:
+ .text
+ .global _start
+_start:
+ move.d _stack_end, $sp
+ jsr main
+ nop
+ moveq 0, $r10
+ jump exit
+ nop
diff --git a/tests/tcg/cris/sys.c b/tests/tcg/cris/sys.c
new file mode 100644
index 0000000000..551c5dd7cb
--- /dev/null
+++ b/tests/tcg/cris/sys.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline int mystrlen(char *s) {
+ int i = 0;
+ while (s[i])
+ i++;
+ return i;
+}
+
+void pass(void) {
+ char s[] = "passed.\n";
+ write (1, s, sizeof (s) - 1);
+ exit (0);
+}
+
+void _fail(char *reason) {
+ char s[] = "\nfailed: ";
+ int len = mystrlen(reason);
+ write (1, s, sizeof (s) - 1);
+ write (1, reason, len);
+ write (1, "\n", 1);
+// exit (1);
+}
+
+void *memset (void *s, int c, size_t n) {
+ char *p = s;
+ int i;
+ for (i = 0; i < n; i++)
+ p[i] = c;
+ return p;
+}
+
+void exit (int status) {
+ asm volatile ("moveq 1, $r9\n" /* NR_exit. */
+ "break 13\n");
+ while(1)
+ ;
+}
+
+ssize_t write (int fd, const void *buf, size_t count) {
+ int r;
+ asm ("move.d %0, $r10\n"
+ "move.d %1, $r11\n"
+ "move.d %2, $r12\n"
+ "moveq 4, $r9\n" /* NR_write. */
+ "break 13\n" : : "r" (fd), "r" (buf), "r" (count) : "memory");
+ asm ("move.d $r10, %0\n" : "=r" (r));
+ return r;
+}
diff --git a/tests/tcg/cris/sys.h b/tests/tcg/cris/sys.h
new file mode 100644
index 0000000000..c5f88e1a29
--- /dev/null
+++ b/tests/tcg/cris/sys.h
@@ -0,0 +1,16 @@
+#include <unistd.h>
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+
+#define CURRENT_LOCATION __FILE__ ":" TOSTRING(__LINE__)
+
+#define err() \
+{ \
+ _fail("at " CURRENT_LOCATION " "); \
+}
+
+#define mb() asm volatile ("" : : : "memory")
+
+void pass(void);
+void _fail(char *reason);
diff --git a/tests/tcg/cris/testutils.inc b/tests/tcg/cris/testutils.inc
new file mode 100644
index 0000000000..aa1641b2e6
--- /dev/null
+++ b/tests/tcg/cris/testutils.inc
@@ -0,0 +1,117 @@
+ .syntax no_register_prefix
+
+ .macro start
+ .text
+ .global main
+main:
+ .endm
+
+ .macro quit
+ jump pass
+ nop
+ .endm
+
+ .macro pass
+ jump pass
+ nop
+ .endm
+
+ .macro startnostack
+ start
+ .endm
+
+ .macro fail
+ .data
+99:
+ .asciz " checkr3 failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+ .endm
+
+ .macro checkr3 val
+ cmp.d 0x\val, $r3
+ beq 100f
+ nop
+ .data
+99:
+ .asciz "checkr3 failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+100:
+ .endm
+
+; Test the condition codes
+ .macro test_cc N Z V C
+ .if \N
+ bpl 9f
+ nop
+ .else
+ bmi 9f
+ nop
+ .endif
+ .if \Z
+ bne 9f
+ nop
+ .else
+ beq 9f
+ nop
+ .endif
+ .if \V
+ bvc 9f
+ nop
+ .else
+ bvs 9f
+ nop
+ .endif
+ .if \C
+ bcc 9f
+ nop
+ .else
+ bcs 9f
+ nop
+ .endif
+ ba 8f
+ nop
+9:
+ .data
+99:
+ .asciz "test_move_cc failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+8:
+ .endm
+
+
+ .macro test_move_cc N Z V C
+ .if \N
+ bpl 9f
+ nop
+ .else
+ bmi 9f
+ nop
+ .endif
+ .if \Z
+ bne 9f
+ nop
+ .else
+ beq 9f
+ nop
+ .endif
+ ba 8f
+ nop
+9:
+ .data
+99:
+ .asciz "test_move_cc failed\n"
+ .text
+ move.d 99b, $r10
+ jsr _fail
+ nop
+8:
+ .endm
diff --git a/tests/tcg/hello-arm.c b/tests/tcg/hello-arm.c
new file mode 100644
index 0000000000..e0daa7ad98
--- /dev/null
+++ b/tests/tcg/hello-arm.c
@@ -0,0 +1,113 @@
+#define __NR_SYSCALL_BASE 0x900000
+#define __NR_exit1 (__NR_SYSCALL_BASE+ 1)
+#define __NR_write (__NR_SYSCALL_BASE+ 4)
+
+#define __sys2(x) #x
+#define __sys1(x) __sys2(x)
+
+#ifndef __syscall
+#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t"
+#endif
+
+#define __syscall_return(type, res) \
+do { \
+ return (type) (res); \
+} while (0)
+
+#define _syscall0(type,name) \
+type name(void) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ "mov %0,r0" \
+ :"=r" (__res) : : "r0","lr"); \
+ __syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ __syscall(name) \
+ "mov %0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)) \
+ : "r0","lr"); \
+ __syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)) \
+ : "r0","r1","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)) \
+ : "r0","r1","r2","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ "mov\tr3,%4\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)) \
+ : "r0","r1","r2","r3","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ "mov\tr3,%4\n\t" \
+ "mov\tr4,%5\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)), \
+ "r" ((long)(arg5)) \
+ : "r0","r1","r2","r3","r4","lr"); \
+ __syscall_return(type,__res); \
+}
+
+_syscall1(int,exit1,int,status);
+_syscall3(int,write,int,fd,const char *,buf, int, len);
+
+void _start(void)
+{
+ write(1, "Hello World\n", 12);
+ exit1(0);
+}
diff --git a/tests/tcg/hello-i386.c b/tests/tcg/hello-i386.c
new file mode 100644
index 0000000000..86afc34fb1
--- /dev/null
+++ b/tests/tcg/hello-i386.c
@@ -0,0 +1,26 @@
+#include <asm/unistd.h>
+
+static inline volatile void exit(int status)
+{
+ int __res;
+ __asm__ volatile ("movl %%ecx,%%ebx\n"\
+ "int $0x80" \
+ : "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
+}
+
+static inline int write(int fd, const char * buf, int len)
+{
+ int status;
+ __asm__ volatile ("pushl %%ebx\n"\
+ "movl %%esi,%%ebx\n"\
+ "int $0x80\n" \
+ "popl %%ebx\n"\
+ : "=a" (status) \
+ : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len)));
+}
+
+void _start(void)
+{
+ write(1, "Hello World\n", 12);
+ exit(0);
+}
diff --git a/tests/tcg/hello-mips.c b/tests/tcg/hello-mips.c
new file mode 100644
index 0000000000..f8256730dd
--- /dev/null
+++ b/tests/tcg/hello-mips.c
@@ -0,0 +1,64 @@
+/*
+* MIPS o32 Linux syscall example
+*
+* http://www.linux-mips.org/wiki/RISC/os
+* http://www.linux-mips.org/wiki/MIPSABIHistory
+* http://www.linux.com/howtos/Assembly-HOWTO/mips.shtml
+*
+* mipsel-linux-gcc -nostdlib -mno-abicalls -fno-PIC -mabi=32 \
+* -O2 -static -o hello-mips hello-mips.c
+*
+*/
+#define __NR_SYSCALL_BASE 4000
+#define __NR_exit (__NR_SYSCALL_BASE+ 1)
+#define __NR_write (__NR_SYSCALL_BASE+ 4)
+
+static inline void exit1(int status)
+{
+ register unsigned long __a0 asm("$4") = (unsigned long) status;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set noreorder \n"
+ " li $2, %0 \n"
+ " syscall \n"
+ " .set pop "
+ :
+ : "i" (__NR_exit), "r" (__a0)
+ : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+ "memory");
+}
+
+static inline int write(int fd, const char *buf, int len)
+{
+ register unsigned long __a0 asm("$4") = (unsigned long) fd;
+ register unsigned long __a1 asm("$5") = (unsigned long) buf;
+ register unsigned long __a2 asm("$6") = (unsigned long) len;
+ register unsigned long __a3 asm("$7");
+ unsigned long __v0;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set noreorder \n"
+ " li $2, %2 \n"
+ " syscall \n"
+ " move %0, $2 \n"
+ " .set pop "
+ : "=r" (__v0), "=r" (__a3)
+ : "i" (__NR_write), "r" (__a0), "r" (__a1), "r" (__a2)
+ : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
+ "memory");
+
+/* if (__a3 == 0) */
+ return (int) __v0;
+/*
+ errno = __v0;
+ return -1;
+ */
+}
+
+void __start(void)
+{
+ write (1, "Hello, World!\n", 14);
+ exit1 (42);
+}
diff --git a/tests/tcg/linux-test.c b/tests/tcg/linux-test.c
new file mode 100644
index 0000000000..2e4a746ac3
--- /dev/null
+++ b/tests/tcg/linux-test.c
@@ -0,0 +1,537 @@
+/*
+ * linux and CPU test
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <utime.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <sys/shm.h>
+
+#define TESTPATH "/tmp/linux-test.tmp"
+#define TESTPORT 7654
+#define STACK_SIZE 16384
+
+void error1(const char *filename, int line, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d: ", filename, line);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ exit(1);
+}
+
+int __chk_error(const char *filename, int line, int ret)
+{
+ if (ret < 0) {
+ error1(filename, line, "%m (ret=%d, errno=%d)",
+ ret, errno);
+ }
+ return ret;
+}
+
+#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
+
+#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
+
+/*******************************************************/
+
+#define FILE_BUF_SIZE 300
+
+void test_file(void)
+{
+ int fd, i, len, ret;
+ uint8_t buf[FILE_BUF_SIZE];
+ uint8_t buf2[FILE_BUF_SIZE];
+ uint8_t buf3[FILE_BUF_SIZE];
+ char cur_dir[1024];
+ struct stat st;
+ struct utimbuf tbuf;
+ struct iovec vecs[2];
+ DIR *dir;
+ struct dirent *de;
+
+ /* clean up, just in case */
+ unlink(TESTPATH "/file1");
+ unlink(TESTPATH "/file2");
+ unlink(TESTPATH "/file3");
+ rmdir(TESTPATH);
+
+ if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
+ error("getcwd");
+
+ chk_error(mkdir(TESTPATH, 0755));
+
+ chk_error(chdir(TESTPATH));
+
+ /* open/read/write/close/readv/writev/lseek */
+
+ fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644));
+ for(i=0;i < FILE_BUF_SIZE; i++)
+ buf[i] = i;
+ len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2));
+ if (len != (FILE_BUF_SIZE / 2))
+ error("write");
+ vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2);
+ vecs[0].iov_len = 16;
+ vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16;
+ vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16;
+ len = chk_error(writev(fd, vecs, 2));
+ if (len != (FILE_BUF_SIZE / 2))
+ error("writev");
+ chk_error(close(fd));
+
+ chk_error(rename("file1", "file2"));
+
+ fd = chk_error(open("file2", O_RDONLY));
+
+ len = chk_error(read(fd, buf2, FILE_BUF_SIZE));
+ if (len != FILE_BUF_SIZE)
+ error("read");
+ if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0)
+ error("memcmp");
+
+#define FOFFSET 16
+ ret = chk_error(lseek(fd, FOFFSET, SEEK_SET));
+ if (ret != 16)
+ error("lseek");
+ vecs[0].iov_base = buf3;
+ vecs[0].iov_len = 32;
+ vecs[1].iov_base = buf3 + 32;
+ vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32;
+ len = chk_error(readv(fd, vecs, 2));
+ if (len != FILE_BUF_SIZE - FOFFSET)
+ error("readv");
+ if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0)
+ error("memcmp");
+
+ chk_error(close(fd));
+
+ /* access */
+ chk_error(access("file2", R_OK));
+
+ /* stat/chmod/utime/truncate */
+
+ chk_error(chmod("file2", 0600));
+ tbuf.actime = 1001;
+ tbuf.modtime = 1000;
+ chk_error(truncate("file2", 100));
+ chk_error(utime("file2", &tbuf));
+ chk_error(stat("file2", &st));
+ if (st.st_size != 100)
+ error("stat size");
+ if (!S_ISREG(st.st_mode))
+ error("stat mode");
+ if ((st.st_mode & 0777) != 0600)
+ error("stat mode2");
+ if (st.st_atime != 1001 ||
+ st.st_mtime != 1000)
+ error("stat time");
+
+ chk_error(stat(TESTPATH, &st));
+ if (!S_ISDIR(st.st_mode))
+ error("stat mode");
+
+ /* fstat */
+ fd = chk_error(open("file2", O_RDWR));
+ chk_error(ftruncate(fd, 50));
+ chk_error(fstat(fd, &st));
+ chk_error(close(fd));
+
+ if (st.st_size != 50)
+ error("stat size");
+ if (!S_ISREG(st.st_mode))
+ error("stat mode");
+
+ /* symlink/lstat */
+ chk_error(symlink("file2", "file3"));
+ chk_error(lstat("file3", &st));
+ if (!S_ISLNK(st.st_mode))
+ error("stat mode");
+
+ /* getdents */
+ dir = opendir(TESTPATH);
+ if (!dir)
+ error("opendir");
+ len = 0;
+ for(;;) {
+ de = readdir(dir);
+ if (!de)
+ break;
+ if (strcmp(de->d_name, ".") != 0 &&
+ strcmp(de->d_name, "..") != 0 &&
+ strcmp(de->d_name, "file2") != 0 &&
+ strcmp(de->d_name, "file3") != 0)
+ error("readdir");
+ len++;
+ }
+ closedir(dir);
+ if (len != 4)
+ error("readdir");
+
+ chk_error(unlink("file3"));
+ chk_error(unlink("file2"));
+ chk_error(chdir(cur_dir));
+ chk_error(rmdir(TESTPATH));
+}
+
+void test_fork(void)
+{
+ int pid, status;
+
+ pid = chk_error(fork());
+ if (pid == 0) {
+ /* child */
+ exit(2);
+ }
+ chk_error(waitpid(pid, &status, 0));
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 2)
+ error("waitpid status=0x%x", status);
+}
+
+void test_time(void)
+{
+ struct timeval tv, tv2;
+ struct timespec ts, rem;
+ struct rusage rusg1, rusg2;
+ int ti, i;
+
+ chk_error(gettimeofday(&tv, NULL));
+ rem.tv_sec = 1;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 20 * 1000000;
+ chk_error(nanosleep(&ts, &rem));
+ if (rem.tv_sec != 1)
+ error("nanosleep");
+ chk_error(gettimeofday(&tv2, NULL));
+ ti = tv2.tv_sec - tv.tv_sec;
+ if (ti >= 2)
+ error("gettimeofday");
+
+ chk_error(getrusage(RUSAGE_SELF, &rusg1));
+ for(i = 0;i < 10000; i++);
+ chk_error(getrusage(RUSAGE_SELF, &rusg2));
+ if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 ||
+ (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0)
+ error("getrusage");
+}
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+ int len;
+ len = strlen(buf);
+ if (len < buf_size)
+ pstrcpy(buf + len, buf_size - len, s);
+ return buf;
+}
+
+int server_socket(void)
+{
+ int val, fd;
+ struct sockaddr_in sockaddr;
+
+ /* server socket */
+ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+
+ val = 1;
+ chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)));
+
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(TESTPORT);
+ sockaddr.sin_addr.s_addr = 0;
+ chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+ chk_error(listen(fd, 0));
+ return fd;
+
+}
+
+int client_socket(void)
+{
+ int fd;
+ struct sockaddr_in sockaddr;
+
+ /* server socket */
+ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(TESTPORT);
+ inet_aton("127.0.0.1", &sockaddr.sin_addr);
+ chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+ return fd;
+}
+
+const char socket_msg[] = "hello socket\n";
+
+void test_socket(void)
+{
+ int server_fd, client_fd, fd, pid, ret, val;
+ struct sockaddr_in sockaddr;
+ socklen_t len;
+ char buf[512];
+
+ server_fd = server_socket();
+
+ /* test a few socket options */
+ len = sizeof(val);
+ chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len));
+ if (val != SOCK_STREAM)
+ error("getsockopt");
+
+ pid = chk_error(fork());
+ if (pid == 0) {
+ client_fd = client_socket();
+ send(client_fd, socket_msg, sizeof(socket_msg), 0);
+ close(client_fd);
+ exit(0);
+ }
+ len = sizeof(sockaddr);
+ fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len));
+
+ ret = chk_error(recv(fd, buf, sizeof(buf), 0));
+ if (ret != sizeof(socket_msg))
+ error("recv");
+ if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0)
+ error("socket_msg");
+ chk_error(close(fd));
+ chk_error(close(server_fd));
+}
+
+#define WCOUNT_MAX 512
+
+void test_pipe(void)
+{
+ fd_set rfds, wfds;
+ int fds[2], fd_max, ret;
+ uint8_t ch;
+ int wcount, rcount;
+
+ chk_error(pipe(fds));
+ chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK));
+ chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK));
+ wcount = 0;
+ rcount = 0;
+ for(;;) {
+ FD_ZERO(&rfds);
+ fd_max = fds[0];
+ FD_SET(fds[0], &rfds);
+
+ FD_ZERO(&wfds);
+ FD_SET(fds[1], &wfds);
+ if (fds[1] > fd_max)
+ fd_max = fds[1];
+
+ ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL));
+ if (ret > 0) {
+ if (FD_ISSET(fds[0], &rfds)) {
+ chk_error(read(fds[0], &ch, 1));
+ rcount++;
+ if (rcount >= WCOUNT_MAX)
+ break;
+ }
+ if (FD_ISSET(fds[1], &wfds)) {
+ ch = 'a';
+ chk_error(write(fds[0], &ch, 1));
+ wcount++;
+ }
+ }
+ }
+ chk_error(close(fds[0]));
+ chk_error(close(fds[1]));
+}
+
+int thread1_res;
+int thread2_res;
+
+int thread1_func(void *arg)
+{
+ int i;
+ for(i=0;i<5;i++) {
+ thread1_res++;
+ usleep(10 * 1000);
+ }
+ return 0;
+}
+
+int thread2_func(void *arg)
+{
+ int i;
+ for(i=0;i<6;i++) {
+ thread2_res++;
+ usleep(10 * 1000);
+ }
+ return 0;
+}
+
+void test_clone(void)
+{
+ uint8_t *stack1, *stack2;
+ int pid1, pid2, status1, status2;
+
+ stack1 = malloc(STACK_SIZE);
+ pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1"));
+
+ stack2 = malloc(STACK_SIZE);
+ pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
+
+ while (waitpid(pid1, &status1, 0) != pid1);
+ free(stack1);
+ while (waitpid(pid2, &status2, 0) != pid2);
+ free(stack2);
+ if (thread1_res != 5 ||
+ thread2_res != 6)
+ error("clone");
+}
+
+/***********************************/
+
+volatile int alarm_count;
+jmp_buf jmp_env;
+
+void sig_alarm(int sig)
+{
+ if (sig != SIGALRM)
+ error("signal");
+ alarm_count++;
+}
+
+void sig_segv(int sig, siginfo_t *info, void *puc)
+{
+ if (sig != SIGSEGV)
+ error("signal");
+ longjmp(jmp_env, 1);
+}
+
+void test_signal(void)
+{
+ struct sigaction act;
+ struct itimerval it, oit;
+
+ /* timer test */
+
+ alarm_count = 0;
+
+ act.sa_handler = sig_alarm;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ chk_error(sigaction(SIGALRM, &act, NULL));
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 10 * 1000;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 10 * 1000;
+ chk_error(setitimer(ITIMER_REAL, &it, NULL));
+ chk_error(getitimer(ITIMER_REAL, &oit));
+ if (oit.it_value.tv_sec != it.it_value.tv_sec ||
+ oit.it_value.tv_usec != it.it_value.tv_usec)
+ error("itimer");
+
+ while (alarm_count < 5) {
+ usleep(10 * 1000);
+ }
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 0;
+ memset(&oit, 0xff, sizeof(oit));
+ chk_error(setitimer(ITIMER_REAL, &it, &oit));
+ if (oit.it_value.tv_sec != 0 ||
+ oit.it_value.tv_usec != 10 * 1000)
+ error("setitimer");
+
+ /* SIGSEGV test */
+ act.sa_sigaction = sig_segv;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ chk_error(sigaction(SIGSEGV, &act, NULL));
+ if (setjmp(jmp_env) == 0) {
+ *(uint8_t *)0 = 0;
+ }
+
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ chk_error(sigaction(SIGSEGV, &act, NULL));
+}
+
+#define SHM_SIZE 32768
+
+void test_shm(void)
+{
+ void *ptr;
+ int shmid;
+
+ shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777));
+ ptr = shmat(shmid, NULL, 0);
+ if (!ptr)
+ error("shmat");
+
+ memset(ptr, 0, SHM_SIZE);
+
+ chk_error(shmctl(shmid, IPC_RMID, 0));
+ chk_error(shmdt(ptr));
+}
+
+int main(int argc, char **argv)
+{
+ test_file();
+ test_fork();
+ test_time();
+ test_socket();
+ // test_clone();
+ test_signal();
+ test_shm();
+ return 0;
+}
diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile
new file mode 100644
index 0000000000..03a1abbcfb
--- /dev/null
+++ b/tests/tcg/lm32/Makefile
@@ -0,0 +1,102 @@
+-include ../../config-host.mak
+
+CROSS=lm32-elf-
+
+SIM = qemu-system-lm32
+SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel
+
+CC = $(CROSS)gcc
+AS = $(CROSS)as
+AS = $(CC) -x assembler
+SIZE = $(CROSS)size
+LD = $(CC)
+OBJCOPY = $(CROSS)objcopy
+
+LDFLAGS = -Tlinker.ld
+
+CRT = crt.o
+TESTCASES += test_add.tst
+TESTCASES += test_addi.tst
+TESTCASES += test_and.tst
+TESTCASES += test_andhi.tst
+TESTCASES += test_andi.tst
+TESTCASES += test_b.tst
+TESTCASES += test_be.tst
+TESTCASES += test_bg.tst
+TESTCASES += test_bge.tst
+TESTCASES += test_bgeu.tst
+TESTCASES += test_bgu.tst
+TESTCASES += test_bi.tst
+TESTCASES += test_bne.tst
+TESTCASES += test_break.tst
+TESTCASES += test_bret.tst
+TESTCASES += test_call.tst
+TESTCASES += test_calli.tst
+TESTCASES += test_cmpe.tst
+TESTCASES += test_cmpei.tst
+TESTCASES += test_cmpg.tst
+TESTCASES += test_cmpgi.tst
+TESTCASES += test_cmpge.tst
+TESTCASES += test_cmpgei.tst
+TESTCASES += test_cmpgeu.tst
+TESTCASES += test_cmpgeui.tst
+TESTCASES += test_cmpgu.tst
+TESTCASES += test_cmpgui.tst
+TESTCASES += test_cmpne.tst
+TESTCASES += test_cmpnei.tst
+TESTCASES += test_divu.tst
+TESTCASES += test_eret.tst
+TESTCASES += test_lb.tst
+TESTCASES += test_lbu.tst
+TESTCASES += test_lh.tst
+TESTCASES += test_lhu.tst
+TESTCASES += test_lw.tst
+TESTCASES += test_modu.tst
+TESTCASES += test_mul.tst
+TESTCASES += test_muli.tst
+TESTCASES += test_nor.tst
+TESTCASES += test_nori.tst
+TESTCASES += test_or.tst
+TESTCASES += test_ori.tst
+TESTCASES += test_orhi.tst
+#TESTCASES += test_rcsr.tst
+TESTCASES += test_ret.tst
+TESTCASES += test_sb.tst
+TESTCASES += test_scall.tst
+TESTCASES += test_sextb.tst
+TESTCASES += test_sexth.tst
+TESTCASES += test_sh.tst
+TESTCASES += test_sl.tst
+TESTCASES += test_sli.tst
+TESTCASES += test_sr.tst
+TESTCASES += test_sri.tst
+TESTCASES += test_sru.tst
+TESTCASES += test_srui.tst
+TESTCASES += test_sub.tst
+TESTCASES += test_sw.tst
+#TESTCASES += test_wcsr.tst
+TESTCASES += test_xnor.tst
+TESTCASES += test_xnori.tst
+TESTCASES += test_xor.tst
+TESTCASES += test_xori.tst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/lm32/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/lm32/%.S
+ $(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o macros.inc $(CRT)
+ $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(CRT) $(TESTCASES)
+
+check: $(CRT) $(SYS) $(TESTCASES)
+ @for case in $(TESTCASES); do \
+ $(SIM) $(SIMFLAGS) ./$$case; \
+ done
+
+clean:
+ $(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/tcg/lm32/crt.S b/tests/tcg/lm32/crt.S
new file mode 100644
index 0000000000..5f9cfd95d3
--- /dev/null
+++ b/tests/tcg/lm32/crt.S
@@ -0,0 +1,84 @@
+.text
+.global _start
+
+_start:
+_reset_handler:
+ xor r0, r0, r0
+ mvhi r1, hi(_start)
+ ori r1, r1, lo(_start)
+ wcsr eba, r1
+ wcsr deba, r1
+ bi _main
+ nop
+ nop
+
+_breakpoint_handler:
+ ori r25, r25, 1
+ addi ra, ba, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_instruction_bus_error_handler:
+ ori r25, r25, 2
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_watchpoint_handler:
+ ori r25, r25, 4
+ addi ra, ba, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_data_bus_error_handler:
+ ori r25, r25, 8
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_divide_by_zero_handler:
+ ori r25, r25, 16
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_interrupt_handler:
+ ori r25, r25, 32
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
+_system_call_handler:
+ ori r25, r25, 64
+ addi ra, ea, 4
+ ret
+ nop
+ nop
+ nop
+ nop
+ nop
+
diff --git a/tests/tcg/lm32/linker.ld b/tests/tcg/lm32/linker.ld
new file mode 100644
index 0000000000..52d43a4c74
--- /dev/null
+++ b/tests/tcg/lm32/linker.ld
@@ -0,0 +1,55 @@
+OUTPUT_FORMAT("elf32-lm32")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+ ram : ORIGIN = 0x08000000, LENGTH = 0x04000000 /* 64M */
+}
+
+SECTIONS
+{
+ .text :
+ {
+ _ftext = .;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ _etext = .;
+ } > ram
+
+ .rodata :
+ {
+ . = ALIGN(4);
+ _frodata = .;
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ _erodata = .;
+ } > ram
+
+ .data :
+ {
+ . = ALIGN(4);
+ _fdata = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.data1)
+ _gp = ALIGN(16);
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ _edata = .;
+ } > ram
+
+ .bss :
+ {
+ . = ALIGN(4);
+ _fbss = .;
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ _ebss = .;
+ _end = .;
+ } > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
+
diff --git a/tests/tcg/lm32/macros.inc b/tests/tcg/lm32/macros.inc
new file mode 100644
index 0000000000..367c7c50d8
--- /dev/null
+++ b/tests/tcg/lm32/macros.inc
@@ -0,0 +1,79 @@
+
+.macro test_name name
+ .data
+tn_\name:
+ .asciz "\name"
+ .text
+ mvhi r13, hi(tn_\name)
+ ori r13, r13, lo(tn_\name)
+ sw (r12+8), r13
+.endm
+
+.macro load reg val
+ mvhi \reg, hi(\val)
+ ori \reg, \reg, lo(\val)
+.endm
+
+.macro tc_pass
+ mvi r13, 0
+ sw (r12+4), r13
+.endm
+
+.macro tc_fail
+ mvi r13, 1
+ sw (r12+4), r13
+.endm
+
+.macro check_r3 val
+ mvhi r13, hi(\val)
+ ori r13, r13, lo(\val)
+ be r3, r13, 1f
+ tc_fail
+ bi 2f
+1:
+ tc_pass
+2:
+.endm
+
+.macro check_mem adr val
+ mvhi r13, hi(\adr)
+ ori r13, r13, lo(\adr)
+ mvhi r14, hi(\val)
+ ori r14, r14, lo(\val)
+ lw r13, (r13+0)
+ be r13, r14, 1f
+ tc_fail
+ bi 2f
+1:
+ tc_pass
+2:
+.endm
+
+.macro check_excp excp
+ andi r13, r25, \excp
+ bne r13, r0, 1f
+ tc_fail
+ bi 2f
+1:
+ tc_pass
+2:
+.endm
+
+.macro start
+ .global _main
+ .text
+_main:
+ mvhi r12, hi(0xffff0000) # base address of test block
+ ori r12, r12, lo(0xffff0000)
+.endm
+
+.macro end
+ sw (r12+0), r0
+1:
+ bi 1b
+.endm
+
+# base +
+# 0 ctrl
+# 4 pass/fail
+# 8 ptr to test name
diff --git a/tests/tcg/lm32/test_add.S b/tests/tcg/lm32/test_add.S
new file mode 100644
index 0000000000..030ad197bb
--- /dev/null
+++ b/tests/tcg/lm32/test_add.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name ADD_1
+mvi r1, 0
+mvi r2, 0
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_2
+mvi r1, 0
+mvi r2, 1
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_3
+mvi r1, 1
+mvi r2, 0
+add r3, r1, r2
+check_r3 1
+
+test_name ADD_4
+mvi r1, 1
+mvi r2, -1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_5
+mvi r1, -1
+mvi r2, 1
+add r3, r1, r2
+check_r3 0
+
+test_name ADD_6
+mvi r1, -1
+mvi r2, 0
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_7
+mvi r1, 0
+mvi r2, -1
+add r3, r1, r2
+check_r3 -1
+
+test_name ADD_8
+mvi r3, 2
+add r3, r3, r3
+check_r3 4
+
+test_name ADD_9
+mvi r1, 4
+mvi r3, 2
+add r3, r1, r3
+check_r3 6
+
+test_name ADD_10
+mvi r1, 4
+mvi r3, 2
+add r3, r3, r1
+check_r3 6
+
+test_name ADD_11
+mvi r1, 4
+add r3, r1, r1
+check_r3 8
+
+test_name ADD_12
+load r1 0x12345678
+load r2 0xabcdef97
+add r3, r1, r2
+check_r3 0xbe02460f
+
+end
diff --git a/tests/tcg/lm32/test_addi.S b/tests/tcg/lm32/test_addi.S
new file mode 100644
index 0000000000..68e766d1e5
--- /dev/null
+++ b/tests/tcg/lm32/test_addi.S
@@ -0,0 +1,56 @@
+.include "macros.inc"
+
+start
+
+test_name ADDI_1
+mvi r1, 0
+addi r3, r1, 0
+check_r3 0
+
+test_name ADDI_2
+mvi r1, 0
+addi r3, r1, 1
+check_r3 1
+
+test_name ADDI_3
+mvi r1, 1
+addi r3, r1, 0
+check_r3 1
+
+test_name ADDI_4
+mvi r1, 1
+addi r3, r1, -1
+check_r3 0
+
+test_name ADDI_5
+mvi r1, -1
+addi r3, r1, 1
+check_r3 0
+
+test_name ADDI_6
+mvi r1, -1
+addi r3, r1, 0
+check_r3 -1
+
+test_name ADDI_7
+mvi r1, 0
+addi r3, r1, -1
+check_r3 -1
+
+test_name ADDI_8
+mvi r3, 4
+addi r3, r3, 4
+check_r3 8
+
+test_name ADDI_9
+mvi r3, 4
+addi r3, r3, -4
+check_r3 0
+
+test_name ADDI_10
+mvi r3, 4
+addi r3, r3, -5
+check_r3 -1
+
+end
+
diff --git a/tests/tcg/lm32/test_and.S b/tests/tcg/lm32/test_and.S
new file mode 100644
index 0000000000..80962ce7a2
--- /dev/null
+++ b/tests/tcg/lm32/test_and.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name AND_1
+mvi r1, 0
+mvi r2, 0
+and r3, r1, r2
+check_r3 0
+
+test_name AND_2
+mvi r1, 0
+mvi r2, 1
+and r3, r1, r2
+check_r3 0
+
+test_name AND_3
+mvi r1, 1
+mvi r2, 1
+and r3, r1, r2
+check_r3 1
+
+test_name AND_4
+mvi r3, 7
+and r3, r3, r3
+check_r3 7
+
+test_name AND_5
+mvi r1, 7
+and r3, r1, r1
+check_r3 7
+
+test_name AND_6
+mvi r1, 7
+mvi r3, 0
+and r3, r1, r3
+check_r3 0
+
+test_name AND_7
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+and r3, r1, r2
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_andhi.S b/tests/tcg/lm32/test_andhi.S
new file mode 100644
index 0000000000..4f73af550b
--- /dev/null
+++ b/tests/tcg/lm32/test_andhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDHI_1
+mvi r1, 0
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_2
+mvi r1, 1
+andhi r3, r1, 1
+check_r3 0
+
+test_name ANDHI_3
+load r1 0x000f0000
+andhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ANDHI_4
+load r1 0xffffffff
+andhi r3, r1, 0xffff
+check_r3 0xffff0000
+
+test_name ANDHI_5
+load r1 0xffffffff
+andhi r3, r1, 0
+check_r3 0
+
+test_name ANDHI_6
+load r3 0x55aaffff
+andhi r3, r3, 0xaaaa
+check_r3 0x00aa0000
+
+end
diff --git a/tests/tcg/lm32/test_andi.S b/tests/tcg/lm32/test_andi.S
new file mode 100644
index 0000000000..da1b0a32f7
--- /dev/null
+++ b/tests/tcg/lm32/test_andi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ANDI_1
+mvi r1, 0
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_2
+mvi r1, 1
+andi r3, r1, 1
+check_r3 1
+
+test_name ANDI_3
+load r1 0x000f0000
+andi r3, r1, 1
+check_r3 0
+
+test_name ANDI_4
+load r1 0xffffffff
+andi r3, r1, 0xffff
+check_r3 0xffff
+
+test_name ANDI_5
+load r1 0xffffffff
+andi r3, r1, 0
+check_r3 0
+
+test_name ANDI_6
+load r3 0xffff55aa
+andi r3, r3, 0xaaaa
+check_r3 0x000000aa
+
+end
diff --git a/tests/tcg/lm32/test_b.S b/tests/tcg/lm32/test_b.S
new file mode 100644
index 0000000000..98172d8a95
--- /dev/null
+++ b/tests/tcg/lm32/test_b.S
@@ -0,0 +1,13 @@
+.include "macros.inc"
+
+start
+
+test_name B_1
+load r1 jump
+b r1
+tc_fail
+end
+
+jump:
+tc_pass
+end
diff --git a/tests/tcg/lm32/test_be.S b/tests/tcg/lm32/test_be.S
new file mode 100644
index 0000000000..635cabacad
--- /dev/null
+++ b/tests/tcg/lm32/test_be.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BE_1
+mvi r1, 0
+mvi r2, 0
+be r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BE_2
+mvi r1, 1
+mvi r2, 0
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BE_3
+mvi r1, 0
+mvi r2, 1
+be r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BE_4
+mvi r1, 1
+mvi r2, 1
+be r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bg.S b/tests/tcg/lm32/test_bg.S
new file mode 100644
index 0000000000..81823c2304
--- /dev/null
+++ b/tests/tcg/lm32/test_bg.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BG_1
+mvi r1, 0
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_2
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_3
+mvi r1, 0
+mvi r2, 1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_4
+mvi r1, 0
+mvi r2, -1
+bg r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BG_5
+mvi r1, -1
+mvi r2, 0
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BG_6
+mvi r1, -1
+mvi r2, -1
+bg r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BG_7
+mvi r1, 1
+mvi r2, 0
+bg r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bge.S b/tests/tcg/lm32/test_bge.S
new file mode 100644
index 0000000000..6684d15a55
--- /dev/null
+++ b/tests/tcg/lm32/test_bge.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGE_1
+mvi r1, 0
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_2
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_3
+mvi r1, 0
+mvi r2, 1
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_4
+mvi r1, 0
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGE_5
+mvi r1, -1
+mvi r2, 0
+bge r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGE_6
+mvi r1, -1
+mvi r2, -1
+bge r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGE_7
+mvi r1, 1
+mvi r2, 0
+bge r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bgeu.S b/tests/tcg/lm32/test_bgeu.S
new file mode 100644
index 0000000000..be440308fd
--- /dev/null
+++ b/tests/tcg/lm32/test_bgeu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGEU_1
+mvi r1, 0
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_2
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_3
+mvi r1, 0
+mvi r2, 1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_4
+mvi r1, 0
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGEU_5
+mvi r1, -1
+mvi r2, 0
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGEU_6
+mvi r1, -1
+mvi r2, -1
+bgeu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGEU_7
+mvi r1, 1
+mvi r2, 0
+bgeu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bgu.S b/tests/tcg/lm32/test_bgu.S
new file mode 100644
index 0000000000..8cc695b310
--- /dev/null
+++ b/tests/tcg/lm32/test_bgu.S
@@ -0,0 +1,78 @@
+.include "macros.inc"
+
+start
+
+test_name BGU_1
+mvi r1, 0
+mvi r2, 0
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_2
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_3
+mvi r1, 0
+mvi r2, 1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_4
+mvi r1, 0
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BGU_5
+mvi r1, -1
+mvi r2, 0
+bgu r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BGU_6
+mvi r1, -1
+mvi r2, -1
+bgu r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+bi 2f
+1:
+tc_pass
+bi 3f
+2:
+test_name BGU_7
+mvi r1, 1
+mvi r2, 0
+bgu r1, r2, 1b
+tc_fail
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_bi.S b/tests/tcg/lm32/test_bi.S
new file mode 100644
index 0000000000..a1fbd6fc07
--- /dev/null
+++ b/tests/tcg/lm32/test_bi.S
@@ -0,0 +1,23 @@
+.include "macros.inc"
+
+start
+
+test_name BI_1
+bi jump
+tc_fail
+end
+
+jump_back:
+tc_pass
+end
+
+jump:
+tc_pass
+
+test_name BI_2
+bi jump_back
+tc_fail
+
+end
+
+
diff --git a/tests/tcg/lm32/test_bne.S b/tests/tcg/lm32/test_bne.S
new file mode 100644
index 0000000000..871a006755
--- /dev/null
+++ b/tests/tcg/lm32/test_bne.S
@@ -0,0 +1,48 @@
+.include "macros.inc"
+
+start
+
+test_name BNE_1
+mvi r1, 0
+mvi r2, 0
+bne r1, r2, 1f
+tc_pass
+bi 2f
+1:
+tc_fail
+2:
+
+test_name BNE_2
+mvi r1, 1
+mvi r2, 0
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+test_name BNE_3
+mvi r1, 0
+mvi r2, 1
+bne r1, r2, 1f
+tc_fail
+bi 2f
+1:
+tc_pass
+2:
+
+bi 2f
+1:
+tc_fail
+bi 3f
+2:
+test_name BNE_4
+mvi r1, 1
+mvi r2, 1
+bne r1, r2, 1b
+tc_pass
+3:
+
+end
+
diff --git a/tests/tcg/lm32/test_break.S b/tests/tcg/lm32/test_break.S
new file mode 100644
index 0000000000..0384fc6128
--- /dev/null
+++ b/tests/tcg/lm32/test_break.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name BREAK_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+break
+check_excp 1
+
+test_name BREAK_2
+mv r3, ba
+check_r3 insn
+
+test_name BREAK_3
+rcsr r3, IE
+check_r3 4
+
+end
diff --git a/tests/tcg/lm32/test_bret.S b/tests/tcg/lm32/test_bret.S
new file mode 100644
index 0000000000..645210e434
--- /dev/null
+++ b/tests/tcg/lm32/test_bret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name BRET_1
+mvi r1, 4
+wcsr IE, r1
+load ba mark
+bret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name BRET_2
+rcsr r3, IE
+check_r3 5
+
+test_name BRET_3
+mvi r1, 0
+wcsr IE, r1
+load ba mark2
+bret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name BRET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/tests/tcg/lm32/test_call.S b/tests/tcg/lm32/test_call.S
new file mode 100644
index 0000000000..1b91a5f2be
--- /dev/null
+++ b/tests/tcg/lm32/test_call.S
@@ -0,0 +1,16 @@
+.include "macros.inc"
+
+start
+
+test_name CALL_1
+load r1 mark
+call r1
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/tests/tcg/lm32/test_calli.S b/tests/tcg/lm32/test_calli.S
new file mode 100644
index 0000000000..1d87ae6e21
--- /dev/null
+++ b/tests/tcg/lm32/test_calli.S
@@ -0,0 +1,15 @@
+.include "macros.inc"
+
+start
+
+test_name CALLI_1
+calli mark
+return:
+
+tc_fail
+end
+
+mark:
+mv r3, ra
+check_r3 return
+end
diff --git a/tests/tcg/lm32/test_cmpe.S b/tests/tcg/lm32/test_cmpe.S
new file mode 100644
index 0000000000..60a885500b
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpe.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPE_1
+mvi r1, 0
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 1
+
+test_name CMPE_2
+mvi r1, 0
+mvi r2, 1
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_3
+mvi r1, 1
+mvi r2, 0
+cmpe r3, r1, r2
+check_r3 0
+
+test_name CMPE_4
+mvi r3, 0
+mvi r2, 1
+cmpe r3, r3, r2
+check_r3 0
+
+test_name CMPE_5
+mvi r3, 0
+mvi r2, 0
+cmpe r3, r3, r2
+check_r3 1
+
+test_name CMPE_6
+mvi r3, 0
+cmpe r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpei.S b/tests/tcg/lm32/test_cmpei.S
new file mode 100644
index 0000000000..c3d3566ad3
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPEI_1
+mvi r1, 0
+cmpei r3, r1, 0
+check_r3 1
+
+test_name CMPEI_2
+mvi r1, 0
+cmpei r3, r1, 1
+check_r3 0
+
+test_name CMPEI_3
+mvi r1, 1
+cmpei r3, r1, 0
+check_r3 0
+
+test_name CMPEI_4
+load r1 0xffffffff
+cmpei r3, r1, -1
+check_r3 1
+
+test_name CMPEI_5
+mvi r3, 0
+cmpei r3, r3, 0
+check_r3 1
+
+test_name CMPEI_6
+mvi r3, 0
+cmpei r3, r3, 1
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpg.S b/tests/tcg/lm32/test_cmpg.S
new file mode 100644
index 0000000000..012407874c
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpg.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPG_1
+mvi r1, 0
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_2
+mvi r1, 0
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_3
+mvi r1, 1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_4
+mvi r1, 1
+mvi r2, 1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_5
+mvi r1, 0
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 1
+
+test_name CMPG_6
+mvi r1, -1
+mvi r2, 0
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_7
+mvi r1, -1
+mvi r2, -1
+cmpg r3, r1, r2
+check_r3 0
+
+test_name CMPG_8
+mvi r3, 0
+mvi r2, 1
+cmpg r3, r3, r2
+check_r3 0
+
+test_name CMPG_9
+mvi r3, 1
+mvi r2, 0
+cmpg r3, r3, r2
+check_r3 1
+
+test_name CMPG_10
+mvi r3, 0
+cmpg r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpge.S b/tests/tcg/lm32/test_cmpge.S
new file mode 100644
index 0000000000..84620a00e3
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpge.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGE_1
+mvi r1, 0
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_2
+mvi r1, 0
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_3
+mvi r1, 1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_4
+mvi r1, 1
+mvi r2, 1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_5
+mvi r1, 0
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_6
+mvi r1, -1
+mvi r2, 0
+cmpge r3, r1, r2
+check_r3 0
+
+test_name CMPGE_7
+mvi r1, -1
+mvi r2, -1
+cmpge r3, r1, r2
+check_r3 1
+
+test_name CMPGE_8
+mvi r3, 0
+mvi r2, 1
+cmpge r3, r3, r2
+check_r3 0
+
+test_name CMPGE_9
+mvi r3, 1
+mvi r2, 0
+cmpge r3, r3, r2
+check_r3 1
+
+test_name CMPGE_10
+mvi r3, 0
+cmpge r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgei.S b/tests/tcg/lm32/test_cmpgei.S
new file mode 100644
index 0000000000..6a8870f4c3
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgei.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEI_1
+mvi r1, 0
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_2
+mvi r1, 0
+cmpgei r3, r1, 1
+check_r3 0
+
+test_name CMPGEI_3
+mvi r1, 1
+cmpgei r3, r1, 0
+check_r3 1
+
+test_name CMPGEI_4
+mvi r1, 1
+cmpgei r3, r1, 1
+check_r3 1
+
+test_name CMPGEI_5
+mvi r1, 0
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_6
+mvi r1, -1
+cmpgei r3, r1, 0
+check_r3 0
+
+test_name CMPGEI_7
+mvi r1, -1
+cmpgei r3, r1, -1
+check_r3 1
+
+test_name CMPGEI_8
+mvi r3, 0
+cmpgei r3, r3, 1
+check_r3 0
+
+test_name CMPGEI_9
+mvi r3, 1
+cmpgei r3, r3, 0
+check_r3 1
+
+test_name CMPGEI_10
+mvi r3, 0
+cmpgei r3, r3, 0
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgeu.S b/tests/tcg/lm32/test_cmpgeu.S
new file mode 100644
index 0000000000..2110ccb6b7
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgeu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEU_1
+mvi r1, 0
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_2
+mvi r1, 0
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_3
+mvi r1, 1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_4
+mvi r1, 1
+mvi r2, 1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_5
+mvi r1, 0
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 0
+
+test_name CMPGEU_6
+mvi r1, -1
+mvi r2, 0
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_7
+mvi r1, -1
+mvi r2, -1
+cmpgeu r3, r1, r2
+check_r3 1
+
+test_name CMPGEU_8
+mvi r3, 0
+mvi r2, 1
+cmpgeu r3, r3, r2
+check_r3 0
+
+test_name CMPGEU_9
+mvi r3, 1
+mvi r2, 0
+cmpgeu r3, r3, r2
+check_r3 1
+
+test_name CMPGEU_10
+mvi r3, 0
+cmpgeu r3, r3, r3
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgeui.S b/tests/tcg/lm32/test_cmpgeui.S
new file mode 100644
index 0000000000..b9d1755e22
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgeui.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGEUI_1
+mvi r1, 0
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_2
+mvi r1, 0
+cmpgeui r3, r1, 1
+check_r3 0
+
+test_name CMPGEUI_3
+mvi r1, 1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_4
+mvi r1, 1
+cmpgeui r3, r1, 1
+check_r3 1
+
+test_name CMPGEUI_5
+mvi r1, 0
+cmpgeui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGEUI_6
+mvi r1, -1
+cmpgeui r3, r1, 0
+check_r3 1
+
+test_name CMPGEUI_7
+mvi r1, -1
+cmpgeui r3, r1, 0xffff
+check_r3 1
+
+test_name CMPGEUI_8
+mvi r3, 0
+cmpgeui r3, r3, 1
+check_r3 0
+
+test_name CMPGEUI_9
+mvi r3, 1
+cmpgeui r3, r3, 0
+check_r3 1
+
+test_name CMPGEUI_10
+mvi r3, 0
+cmpgeui r3, r3, 0
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_cmpgi.S b/tests/tcg/lm32/test_cmpgi.S
new file mode 100644
index 0000000000..1f622d2900
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgi.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGI_1
+mvi r1, 0
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_2
+mvi r1, 0
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_3
+mvi r1, 1
+cmpgi r3, r1, 0
+check_r3 1
+
+test_name CMPGI_4
+mvi r1, 1
+cmpgi r3, r1, 1
+check_r3 0
+
+test_name CMPGI_5
+mvi r1, 0
+cmpgi r3, r1, -1
+check_r3 1
+
+test_name CMPGI_6
+mvi r1, -1
+cmpgi r3, r1, 0
+check_r3 0
+
+test_name CMPGI_7
+mvi r1, -1
+cmpgi r3, r1, -1
+check_r3 0
+
+test_name CMPGI_8
+mvi r3, 0
+cmpgi r3, r3, 1
+check_r3 0
+
+test_name CMPGI_9
+mvi r3, 1
+cmpgi r3, r3, 0
+check_r3 1
+
+test_name CMPGI_10
+mvi r3, 0
+cmpgi r3, r3, 0
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpgu.S b/tests/tcg/lm32/test_cmpgu.S
new file mode 100644
index 0000000000..dd465471ea
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgu.S
@@ -0,0 +1,64 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGU_1
+mvi r1, 0
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_2
+mvi r1, 0
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_3
+mvi r1, 1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_4
+mvi r1, 1
+mvi r2, 1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_5
+mvi r1, 0
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_6
+mvi r1, -1
+mvi r2, 0
+cmpgu r3, r1, r2
+check_r3 1
+
+test_name CMPGU_7
+mvi r1, -1
+mvi r2, -1
+cmpgu r3, r1, r2
+check_r3 0
+
+test_name CMPGU_8
+mvi r3, 0
+mvi r2, 1
+cmpgu r3, r3, r2
+check_r3 0
+
+test_name CMPGU_9
+mvi r3, 1
+mvi r2, 0
+cmpgu r3, r3, r2
+check_r3 1
+
+test_name CMPGU_10
+mvi r3, 0
+cmpgu r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpgui.S b/tests/tcg/lm32/test_cmpgui.S
new file mode 100644
index 0000000000..759bb64b3c
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpgui.S
@@ -0,0 +1,55 @@
+.include "macros.inc"
+
+start
+
+test_name CMPGUI_1
+mvi r1, 0
+cmpgui r3, r1, 0
+check_r3 0
+
+test_name CMPGUI_2
+mvi r1, 0
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_3
+mvi r1, 1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_4
+mvi r1, 1
+cmpgui r3, r1, 1
+check_r3 0
+
+test_name CMPGUI_5
+mvi r1, 0
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_6
+mvi r1, -1
+cmpgui r3, r1, 0
+check_r3 1
+
+test_name CMPGUI_7
+mvi r1, -1
+cmpgui r3, r1, 0xffff
+check_r3 0
+
+test_name CMPGUI_8
+mvi r3, 0
+cmpgui r3, r3, 1
+check_r3 0
+
+test_name CMPGUI_9
+mvi r3, 1
+cmpgui r3, r3, 0
+check_r3 1
+
+test_name CMPGUI_10
+mvi r3, 0
+cmpgui r3, r3, 0
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpne.S b/tests/tcg/lm32/test_cmpne.S
new file mode 100644
index 0000000000..0f1078114c
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpne.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNE_1
+mvi r1, 0
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 0
+
+test_name CMPNE_2
+mvi r1, 0
+mvi r2, 1
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_3
+mvi r1, 1
+mvi r2, 0
+cmpne r3, r1, r2
+check_r3 1
+
+test_name CMPNE_4
+mvi r3, 0
+mvi r2, 1
+cmpne r3, r3, r2
+check_r3 1
+
+test_name CMPNE_5
+mvi r3, 0
+mvi r2, 0
+cmpne r3, r3, r2
+check_r3 0
+
+test_name CMPNE_6
+mvi r3, 0
+cmpne r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_cmpnei.S b/tests/tcg/lm32/test_cmpnei.S
new file mode 100644
index 0000000000..060dd9d394
--- /dev/null
+++ b/tests/tcg/lm32/test_cmpnei.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name CMPNEI_1
+mvi r1, 0
+cmpnei r3, r1, 0
+check_r3 0
+
+test_name CMPNEI_2
+mvi r1, 0
+cmpnei r3, r1, 1
+check_r3 1
+
+test_name CMPNEI_3
+mvi r1, 1
+cmpnei r3, r1, 0
+check_r3 1
+
+test_name CMPNEI_4
+load r1 0xffffffff
+cmpnei r3, r1, -1
+check_r3 0
+
+test_name CMPNEI_5
+mvi r3, 0
+cmpnei r3, r3, 0
+check_r3 0
+
+test_name CMPNEI_6
+mvi r3, 0
+cmpnei r3, r3, 1
+check_r3 1
+
+end
diff --git a/tests/tcg/lm32/test_divu.S b/tests/tcg/lm32/test_divu.S
new file mode 100644
index 0000000000..f381d095c5
--- /dev/null
+++ b/tests/tcg/lm32/test_divu.S
@@ -0,0 +1,29 @@
+.include "macros.inc"
+
+start
+
+test_name DIVU_1
+mvi r1, 0
+mvi r2, 1
+divu r3, r1, r2
+check_r3 0
+
+test_name DIVU_2
+mvi r1, 1
+mvi r2, 1
+divu r3, r1, r2
+check_r3 1
+
+test_name DIVU_3
+mvi r1, 0
+mvi r2, 0
+divu r3, r1, r2
+check_excp 16
+
+test_name DIVU_4
+load r1 0xabcdef12
+load r2 0x12345
+divu r3, r1, r2
+check_r3 0x9700
+
+end
diff --git a/tests/tcg/lm32/test_eret.S b/tests/tcg/lm32/test_eret.S
new file mode 100644
index 0000000000..6830bd1abf
--- /dev/null
+++ b/tests/tcg/lm32/test_eret.S
@@ -0,0 +1,38 @@
+.include "macros.inc"
+
+start
+
+test_name ERET_1
+mvi r1, 2
+wcsr IE, r1
+load ea mark
+eret
+tc_fail
+bi 1f
+
+mark:
+tc_pass
+
+1:
+test_name ERET_2
+rcsr r3, IE
+check_r3 3
+
+test_name ERET_3
+mvi r1, 0
+wcsr IE, r1
+load ea mark2
+eret
+tc_fail
+bi 1f
+
+mark2:
+tc_pass
+
+1:
+test_name ERET_4
+rcsr r3, IE
+check_r3 0
+
+end
+
diff --git a/tests/tcg/lm32/test_lb.S b/tests/tcg/lm32/test_lb.S
new file mode 100644
index 0000000000..f84d21ead9
--- /dev/null
+++ b/tests/tcg/lm32/test_lb.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LB_1
+load r1 data
+lb r3, (r1+0)
+check_r3 0x7e
+
+test_name LB_2
+lb r3, (r1+1)
+check_r3 0x7f
+
+test_name LB_3
+lb r3, (r1+-1)
+check_r3 0x7d
+
+test_name LB_4
+load r1 data_msb
+lb r3, (r1+0)
+check_r3 0xfffffffe
+
+test_name LB_5
+lb r3, (r1+1)
+check_r3 0xffffffff
+
+test_name LB_6
+lb r3, (r1+-1)
+check_r3 0xfffffffd
+
+test_name LB_7
+load r3 data
+lb r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lbu.S b/tests/tcg/lm32/test_lbu.S
new file mode 100644
index 0000000000..4c1786ad71
--- /dev/null
+++ b/tests/tcg/lm32/test_lbu.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LBU_1
+load r1 data
+lbu r3, (r1+0)
+check_r3 0x7e
+
+test_name LBU_2
+lbu r3, (r1+1)
+check_r3 0x7f
+
+test_name LBU_3
+lbu r3, (r1+-1)
+check_r3 0x7d
+
+test_name LBU_4
+load r1 data_msb
+lbu r3, (r1+0)
+check_r3 0xfe
+
+test_name LBU_5
+lbu r3, (r1+1)
+check_r3 0xff
+
+test_name LBU_6
+lbu r3, (r1+-1)
+check_r3 0xfd
+
+test_name LBU_7
+load r3 data
+lbu r3, (r3+0)
+check_r3 0x7e
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lh.S b/tests/tcg/lm32/test_lh.S
new file mode 100644
index 0000000000..e57d9e35cf
--- /dev/null
+++ b/tests/tcg/lm32/test_lh.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LH_1
+load r1 data
+lh r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LH_2
+lh r3, (r1+2)
+check_r3 0x7071
+
+test_name LH_3
+lh r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LH_4
+load r1 data_msb
+lh r3, (r1+0)
+check_r3 0xfffffeff
+
+test_name LH_5
+lh r3, (r1+2)
+check_r3 0xfffff0f1
+
+test_name LH_6
+lh r3, (r1+-2)
+check_r3 0xfffffcfd
+
+test_name LH_7
+load r3 data
+lh r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lhu.S b/tests/tcg/lm32/test_lhu.S
new file mode 100644
index 0000000000..e648775d94
--- /dev/null
+++ b/tests/tcg/lm32/test_lhu.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name LHU_1
+load r1 data
+lhu r3, (r1+0)
+check_r3 0x7e7f
+
+test_name LHU_2
+lhu r3, (r1+2)
+check_r3 0x7071
+
+test_name LHU_3
+lhu r3, (r1+-2)
+check_r3 0x7c7d
+
+test_name LHU_4
+load r1 data_msb
+lhu r3, (r1+0)
+check_r3 0xfeff
+
+test_name LHU_5
+lhu r3, (r1+2)
+check_r3 0xf0f1
+
+test_name LHU_6
+lhu r3, (r1+-2)
+check_r3 0xfcfd
+
+test_name LHU_7
+load r3 data
+lhu r3, (r3+0)
+check_r3 0x7e7f
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0xfa, 0xfb, 0xfc, 0xfd
+data_msb:
+ .byte 0xfe, 0xff, 0xf0, 0xf1
diff --git a/tests/tcg/lm32/test_lw.S b/tests/tcg/lm32/test_lw.S
new file mode 100644
index 0000000000..f8c919d2b8
--- /dev/null
+++ b/tests/tcg/lm32/test_lw.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name LW_1
+load r1 data
+lw r3, (r1+0)
+check_r3 0x7e7f7071
+
+test_name LW_2
+lw r3, (r1+4)
+check_r3 0x72737475
+
+test_name LW_3
+lw r3, (r1+-4)
+check_r3 0x7a7b7c7d
+
+test_name LW_4
+load r3 data
+lw r3, (r3+0)
+check_r3 0x7e7f7071
+
+end
+
+.data
+ .align 4
+ .byte 0x7a, 0x7b, 0x7c, 0x7d
+data:
+ .byte 0x7e, 0x7f, 0x70, 0x71
+ .byte 0x72, 0x73, 0x74, 0x75
diff --git a/tests/tcg/lm32/test_modu.S b/tests/tcg/lm32/test_modu.S
new file mode 100644
index 0000000000..42486900b4
--- /dev/null
+++ b/tests/tcg/lm32/test_modu.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name MODU_1
+mvi r1, 0
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_2
+mvi r1, 1
+mvi r2, 1
+modu r3, r1, r2
+check_r3 0
+
+test_name MODU_3
+mvi r1, 3
+mvi r2, 2
+modu r3, r1, r2
+check_r3 1
+
+test_name MODU_4
+mvi r1, 0
+mvi r2, 0
+modu r3, r1, r2
+check_excp 16
+
+test_name MODU_5
+load r1 0xabcdef12
+load r2 0x12345
+modu r3, r1, r2
+check_r3 0x3c12
+
+end
diff --git a/tests/tcg/lm32/test_mul.S b/tests/tcg/lm32/test_mul.S
new file mode 100644
index 0000000000..e9b937e648
--- /dev/null
+++ b/tests/tcg/lm32/test_mul.S
@@ -0,0 +1,70 @@
+.include "macros.inc"
+
+start
+
+test_name MUL_1
+mvi r1, 0
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_2
+mvi r1, 1
+mvi r2, 0
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_3
+mvi r1, 0
+mvi r2, 1
+mul r3, r1, r2
+check_r3 0
+
+test_name MUL_4
+mvi r1, 1
+mvi r2, 1
+mul r3, r1, r2
+check_r3 1
+
+test_name MUL_5
+mvi r1, 2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 -2
+
+test_name MUL_6
+mvi r1, -2
+mvi r2, -1
+mul r3, r1, r2
+check_r3 2
+
+test_name MUL_7
+mvi r1, 0x1234
+mvi r2, 0x789
+mul r3, r1, r2
+check_r3 0x8929d4
+
+test_name MUL_8
+mvi r3, 4
+mul r3, r3, r3
+check_r3 16
+
+test_name MUL_9
+mvi r2, 2
+mvi r3, 4
+mul r3, r3, r2
+check_r3 8
+
+test_name MUL_10
+load r1 0x12345678
+load r2 0x7bcdef12
+mul r3, r1, r2
+check_r3 0xa801c70
+
+test_name MUL_11
+load r1 0x12345678
+load r2 0xabcdef12
+mul r3, r1, r2
+check_r3 0x8a801c70
+
+end
diff --git a/tests/tcg/lm32/test_muli.S b/tests/tcg/lm32/test_muli.S
new file mode 100644
index 0000000000..d6dd4a0f7e
--- /dev/null
+++ b/tests/tcg/lm32/test_muli.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name MULI_1
+mvi r1, 0
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_2
+mvi r1, 1
+muli r3, r1, 0
+check_r3 0
+
+test_name MULI_3
+mvi r1, 0
+muli r3, r1, 1
+check_r3 0
+
+test_name MULI_4
+mvi r1, 1
+muli r3, r1, 1
+check_r3 1
+
+test_name MULI_5
+mvi r1, 2
+muli r3, r1, -1
+check_r3 -2
+
+test_name MULI_6
+mvi r1, -2
+muli r3, r1, -1
+check_r3 2
+
+test_name MULI_7
+mvi r1, 0x1234
+muli r3, r1, 0x789
+check_r3 0x8929d4
+
+test_name MULI_8
+mvi r3, 4
+muli r3, r3, 4
+check_r3 16
+
+end
diff --git a/tests/tcg/lm32/test_nor.S b/tests/tcg/lm32/test_nor.S
new file mode 100644
index 0000000000..74d7592565
--- /dev/null
+++ b/tests/tcg/lm32/test_nor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name NOR_1
+mvi r1, 0
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xffffffff
+
+test_name NOR_2
+mvi r1, 0
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_3
+mvi r1, 1
+mvi r2, 1
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_4
+mvi r1, 1
+mvi r2, 0
+nor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name NOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+nor r3, r1, r2
+check_r3 0
+
+test_name NOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+nor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name NOR_7
+load r1 0xaa55aa55
+nor r3, r1, r1
+check_r3 0x55aa55aa
+
+test_name NOR_8
+load r3 0xaa55aa55
+nor r3, r3, r3
+check_r3 0x55aa55aa
+
+end
diff --git a/tests/tcg/lm32/test_nori.S b/tests/tcg/lm32/test_nori.S
new file mode 100644
index 0000000000..d00309c73e
--- /dev/null
+++ b/tests/tcg/lm32/test_nori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name NORI_1
+mvi r1, 0
+nori r3, r1, 0
+check_r3 0xffffffff
+
+test_name NORI_2
+mvi r1, 0
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_3
+mvi r1, 1
+nori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name NORI_4
+mvi r1, 1
+nori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name NORI_5
+load r1 0xaa55aa55
+nori r3, r1, 0x55aa
+check_r3 0x55aa0000
+
+test_name NORI_6
+load r3 0xaa55aa55
+nori r3, r3, 0x55aa
+check_r3 0x55aa0000
+
+end
diff --git a/tests/tcg/lm32/test_or.S b/tests/tcg/lm32/test_or.S
new file mode 100644
index 0000000000..4ed292330e
--- /dev/null
+++ b/tests/tcg/lm32/test_or.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name OR_1
+mvi r1, 0
+mvi r2, 0
+or r3, r1, r2
+check_r3 0
+
+test_name OR_2
+mvi r1, 0
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_3
+mvi r1, 1
+mvi r2, 1
+or r3, r1, r2
+check_r3 1
+
+test_name OR_4
+mvi r1, 1
+mvi r2, 0
+or r3, r1, r2
+check_r3 1
+
+test_name OR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+or r3, r1, r2
+check_r3 0xffffffff
+
+test_name OR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+or r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name OR_7
+load r1 0xaa55aa55
+or r3, r1, r1
+check_r3 0xaa55aa55
+
+test_name OR_8
+load r3 0xaa55aa55
+or r3, r3, r3
+check_r3 0xaa55aa55
+
+end
diff --git a/tests/tcg/lm32/test_orhi.S b/tests/tcg/lm32/test_orhi.S
new file mode 100644
index 0000000000..78b7600e03
--- /dev/null
+++ b/tests/tcg/lm32/test_orhi.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORHI_1
+mvi r1, 0
+orhi r3, r1, 0
+check_r3 0
+
+test_name ORHI_2
+mvi r1, 0
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_3
+load r1 0x00010000
+orhi r3, r1, 1
+check_r3 0x00010000
+
+test_name ORHI_4
+mvi r1, 1
+orhi r3, r1, 0
+check_r3 1
+
+test_name ORHI_5
+load r1 0xaa55aa55
+orhi r3, r1, 0x55aa
+check_r3 0xffffaa55
+
+test_name ORHI_6
+load r3 0xaa55aa55
+orhi r3, r3, 0x55aa
+check_r3 0xffffaa55
+
+end
diff --git a/tests/tcg/lm32/test_ori.S b/tests/tcg/lm32/test_ori.S
new file mode 100644
index 0000000000..3d576cdb8b
--- /dev/null
+++ b/tests/tcg/lm32/test_ori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name ORI_1
+mvi r1, 0
+ori r3, r1, 0
+check_r3 0
+
+test_name ORI_2
+mvi r1, 0
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_3
+mvi r1, 1
+ori r3, r1, 1
+check_r3 1
+
+test_name ORI_4
+mvi r1, 1
+ori r3, r1, 0
+check_r3 1
+
+test_name ORI_5
+load r1 0xaa55aa55
+ori r3, r1, 0x55aa
+check_r3 0xaa55ffff
+
+test_name ORI_6
+load r3 0xaa55aa55
+ori r3, r3, 0x55aa
+check_r3 0xaa55ffff
+
+end
diff --git a/tests/tcg/lm32/test_ret.S b/tests/tcg/lm32/test_ret.S
new file mode 100644
index 0000000000..320264f148
--- /dev/null
+++ b/tests/tcg/lm32/test_ret.S
@@ -0,0 +1,14 @@
+.include "macros.inc"
+
+start
+
+test_name RET_1
+load ra mark
+ret
+
+tc_fail
+end
+
+mark:
+tc_pass
+end
diff --git a/tests/tcg/lm32/test_sb.S b/tests/tcg/lm32/test_sb.S
new file mode 100644
index 0000000000..89e39d621d
--- /dev/null
+++ b/tests/tcg/lm32/test_sb.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SB_1
+load r1 data
+load r2 0xf0f1f2aa
+sb (r1+0), r2
+check_mem data 0xaa000000
+
+test_name SB_2
+load r2 0xf0f1f2bb
+sb (r1+1), r2
+check_mem data 0xaabb0000
+
+test_name SB_3
+load r2 0xf0f1f2cc
+sb (r1+-1), r2
+check_mem data0 0x000000cc
+
+end
+
+.data
+ .align 4
+data0:
+ .byte 0, 0, 0, 0
+data:
+ .byte 0, 0, 0, 0
+data1:
+ .byte 0, 0, 0, 0
diff --git a/tests/tcg/lm32/test_scall.S b/tests/tcg/lm32/test_scall.S
new file mode 100644
index 0000000000..b442e32374
--- /dev/null
+++ b/tests/tcg/lm32/test_scall.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SCALL_1
+mvi r1, 1
+wcsr IE, r1
+insn:
+scall
+check_excp 64
+
+test_name SCALL_2
+mv r3, ea
+check_r3 insn
+
+test_name SCALL_3
+rcsr r3, IE
+check_r3 2
+
+end
diff --git a/tests/tcg/lm32/test_sextb.S b/tests/tcg/lm32/test_sextb.S
new file mode 100644
index 0000000000..58db8ee8b9
--- /dev/null
+++ b/tests/tcg/lm32/test_sextb.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTB_1
+mvi r1, 0
+sextb r3, r1
+check_r3 0
+
+test_name SEXTB_2
+mvi r1, 0x7f
+sextb r3, r1
+check_r3 0x0000007f
+
+test_name SEXTB_3
+mvi r1, 0x80
+sextb r3, r1
+check_r3 0xffffff80
+
+end
diff --git a/tests/tcg/lm32/test_sexth.S b/tests/tcg/lm32/test_sexth.S
new file mode 100644
index 0000000000..a059ec3ee6
--- /dev/null
+++ b/tests/tcg/lm32/test_sexth.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+start
+
+test_name SEXTH_1
+mvi r1, 0
+sexth r3, r1
+check_r3 0
+
+test_name SEXTH_2
+load r1 0x7fff
+sexth r3, r1
+check_r3 0x00007fff
+
+test_name SEXTH_3
+load r1 0x8000
+sexth r3, r1
+check_r3 0xffff8000
+
+end
diff --git a/tests/tcg/lm32/test_sh.S b/tests/tcg/lm32/test_sh.S
new file mode 100644
index 0000000000..ea8b3f2067
--- /dev/null
+++ b/tests/tcg/lm32/test_sh.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SH_1
+load r1 data
+load r2 0xf0f1aaaa
+sh (r1+0), r2
+check_mem data 0xaaaa0000
+
+test_name SH_2
+load r2 0xf0f1bbbb
+sh (r1+2), r2
+check_mem data 0xaaaabbbb
+
+test_name SH_3
+load r2 0xf0f1cccc
+sh (r1+-2), r2
+check_mem data0 0x0000cccc
+
+end
+
+.data
+ .align 4
+data0:
+ .byte 0, 0, 0, 0
+data:
+ .byte 0, 0, 0, 0
+data1:
+ .byte 0, 0, 0, 0
diff --git a/tests/tcg/lm32/test_sl.S b/tests/tcg/lm32/test_sl.S
new file mode 100644
index 0000000000..0aee17fdb8
--- /dev/null
+++ b/tests/tcg/lm32/test_sl.S
@@ -0,0 +1,45 @@
+.include "macros.inc"
+
+start
+
+test_name SL_1
+mvi r1, 1
+mvi r2, 0
+sl r3, r1, r2
+check_r3 1
+
+test_name SL_2
+mvi r1, 0
+mvi r2, 1
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_3
+mvi r1, 1
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0x80000000
+
+test_name SL_4
+mvi r1, 16
+mvi r2, 31
+sl r3, r1, r2
+check_r3 0
+
+test_name SL_5
+mvi r1, 1
+mvi r2, 34
+sl r3, r1, r2
+check_r3 4
+
+test_name SL_6
+mvi r1, 2
+sl r3, r1, r1
+check_r3 8
+
+test_name SL_7
+mvi r3, 2
+sl r3, r3, r3
+check_r3 8
+
+end
diff --git a/tests/tcg/lm32/test_sli.S b/tests/tcg/lm32/test_sli.S
new file mode 100644
index 0000000000..a421de9014
--- /dev/null
+++ b/tests/tcg/lm32/test_sli.S
@@ -0,0 +1,30 @@
+.include "macros.inc"
+
+start
+
+test_name SLI_1
+mvi r1, 1
+sli r3, r1, 0
+check_r3 1
+
+test_name SLI_2
+mvi r1, 0
+sli r3, r1, 1
+check_r3 0
+
+test_name SLI_3
+mvi r1, 1
+sli r3, r1, 31
+check_r3 0x80000000
+
+test_name SLI_4
+mvi r1, 16
+sli r3, r1, 31
+check_r3 0
+
+test_name SLI_7
+mvi r3, 2
+sli r3, r3, 2
+check_r3 8
+
+end
diff --git a/tests/tcg/lm32/test_sr.S b/tests/tcg/lm32/test_sr.S
new file mode 100644
index 0000000000..62431a9864
--- /dev/null
+++ b/tests/tcg/lm32/test_sr.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SR_1
+mvi r1, 1
+mvi r2, 0
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_2
+mvi r1, 0
+mvi r2, 1
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_3
+load r1 0x40000000
+mvi r2, 30
+sr r3, r1, r2
+check_r3 1
+
+test_name SR_4
+load r1 0x40000000
+mvi r2, 31
+sr r3, r1, r2
+check_r3 0
+
+test_name SR_5
+mvi r1, 16
+mvi r2, 34
+sr r3, r1, r2
+check_r3 4
+
+test_name SR_6
+mvi r1, 2
+sr r3, r1, r1
+check_r3 0
+
+test_name SR_7
+mvi r3, 2
+sr r3, r3, r3
+check_r3 0
+
+test_name SR_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sr r3, r1, r2
+check_r3 0xfffffffc
+
+test_name SR_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sr r3, r1, r2
+check_r3 0xffffffff
+
+end
diff --git a/tests/tcg/lm32/test_sri.S b/tests/tcg/lm32/test_sri.S
new file mode 100644
index 0000000000..c1be907b5b
--- /dev/null
+++ b/tests/tcg/lm32/test_sri.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRI_1
+mvi r1, 1
+sri r3, r1, 0
+check_r3 1
+
+test_name SRI_2
+mvi r1, 0
+sri r3, r1, 1
+check_r3 0
+
+test_name SRI_3
+load r1 0x40000000
+sri r3, r1, 30
+check_r3 1
+
+test_name SRI_4
+load r1 0x40000000
+sri r3, r1, 31
+check_r3 0
+
+test_name SRI_5
+mvi r3, 2
+sri r3, r3, 2
+check_r3 0
+
+test_name SRI_6
+mvi r1, 0xfffffff0
+sri r3, r1, 2
+check_r3 0xfffffffc
+
+test_name SRI_7
+mvi r1, 0xfffffff0
+sri r3, r1, 4
+check_r3 0xffffffff
+
+end
diff --git a/tests/tcg/lm32/test_sru.S b/tests/tcg/lm32/test_sru.S
new file mode 100644
index 0000000000..2ab0b54c77
--- /dev/null
+++ b/tests/tcg/lm32/test_sru.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+start
+
+test_name SRU_1
+mvi r1, 1
+mvi r2, 0
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_2
+mvi r1, 0
+mvi r2, 1
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_3
+load r1 0x40000000
+mvi r2, 30
+sru r3, r1, r2
+check_r3 1
+
+test_name SRU_4
+load r1 0x40000000
+mvi r2, 31
+sru r3, r1, r2
+check_r3 0
+
+test_name SRU_5
+mvi r1, 16
+mvi r2, 34
+sru r3, r1, r2
+check_r3 4
+
+test_name SRU_6
+mvi r1, 2
+sru r3, r1, r1
+check_r3 0
+
+test_name SRU_7
+mvi r3, 2
+sru r3, r3, r3
+check_r3 0
+
+test_name SRU_8
+mvi r1, 0xfffffff0
+mvi r2, 2
+sru r3, r1, r2
+check_r3 0x3ffffffc
+
+test_name SRU_9
+mvi r1, 0xfffffff0
+mvi r2, 4
+sru r3, r1, r2
+check_r3 0x0fffffff
+
+end
diff --git a/tests/tcg/lm32/test_srui.S b/tests/tcg/lm32/test_srui.S
new file mode 100644
index 0000000000..872c374121
--- /dev/null
+++ b/tests/tcg/lm32/test_srui.S
@@ -0,0 +1,40 @@
+.include "macros.inc"
+
+start
+
+test_name SRUI_1
+mvi r1, 1
+srui r3, r1, 0
+check_r3 1
+
+test_name SRUI_2
+mvi r1, 0
+srui r3, r1, 1
+check_r3 0
+
+test_name SRUI_3
+load r1 0x40000000
+srui r3, r1, 30
+check_r3 1
+
+test_name SRUI_4
+load r1 0x40000000
+srui r3, r1, 31
+check_r3 0
+
+test_name SRUI_5
+mvi r3, 2
+srui r3, r3, 2
+check_r3 0
+
+test_name SRUI_6
+mvi r1, 0xfffffff0
+srui r3, r1, 2
+check_r3 0x3ffffffc
+
+test_name SRUI_7
+mvi r1, 0xfffffff0
+srui r3, r1, 4
+check_r3 0x0fffffff
+
+end
diff --git a/tests/tcg/lm32/test_sub.S b/tests/tcg/lm32/test_sub.S
new file mode 100644
index 0000000000..44b74a9e10
--- /dev/null
+++ b/tests/tcg/lm32/test_sub.S
@@ -0,0 +1,75 @@
+.include "macros.inc"
+
+start
+
+test_name SUB_1
+mvi r1, 0
+mvi r2, 0
+sub r3, r1, r2
+check_r3 0
+
+test_name SUB_2
+mvi r1, 0
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_3
+mvi r1, 1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_4
+mvi r1, 1
+mvi r2, -1
+sub r3, r1, r2
+check_r3 2
+
+test_name SUB_5
+mvi r1, -1
+mvi r2, 1
+sub r3, r1, r2
+check_r3 -2
+
+test_name SUB_6
+mvi r1, -1
+mvi r2, 0
+sub r3, r1, r2
+check_r3 -1
+
+test_name SUB_7
+mvi r1, 0
+mvi r2, -1
+sub r3, r1, r2
+check_r3 1
+
+test_name SUB_8
+mvi r3, 2
+sub r3, r3, r3
+check_r3 0
+
+test_name SUB_9
+mvi r1, 4
+mvi r3, 2
+sub r3, r1, r3
+check_r3 2
+
+test_name SUB_10
+mvi r1, 4
+mvi r3, 2
+sub r3, r3, r1
+check_r3 -2
+
+test_name SUB_11
+mvi r1, 4
+sub r3, r1, r1
+check_r3 0
+
+test_name SUB_12
+load r1 0x12345678
+load r2 0xabcdef97
+sub r3, r1, r2
+check_r3 0x666666e1
+
+end
diff --git a/tests/tcg/lm32/test_sw.S b/tests/tcg/lm32/test_sw.S
new file mode 100644
index 0000000000..d1fdadce61
--- /dev/null
+++ b/tests/tcg/lm32/test_sw.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name SW_1
+load r1 data
+load r2 0xaabbccdd
+sw (r1+0), r2
+check_mem data 0xaabbccdd
+
+test_name SW_2
+load r2 0x00112233
+sw (r1+4), r2
+check_mem data1 0x00112233
+
+test_name SW_3
+load r2 0x44556677
+sw (r1+-4), r2
+check_mem data0 0x44556677
+
+test_name SW_4
+sw (r1+0), r1
+lw r3, (r1+0)
+check_r3 data
+
+end
+
+.data
+ .align 4
+data0:
+ .byte 0, 0, 0, 0
+data:
+ .byte 0, 0, 0, 0
+data1:
+ .byte 0, 0, 0, 0
diff --git a/tests/tcg/lm32/test_xnor.S b/tests/tcg/lm32/test_xnor.S
new file mode 100644
index 0000000000..14a62075f6
--- /dev/null
+++ b/tests/tcg/lm32/test_xnor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XNOR_1
+mvi r1, 0
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_2
+mvi r1, 0
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_3
+mvi r1, 1
+mvi r2, 1
+xnor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XNOR_4
+mvi r1, 1
+mvi r2, 0
+xnor r3, r1, r2
+check_r3 0xfffffffe
+
+test_name XNOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xnor r3, r1, r2
+check_r3 0
+
+test_name XNOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xnor r3, r1, r2
+check_r3 0x55aa55aa
+
+test_name XNOR_7
+load r1 0xaa55aa55
+xnor r3, r1, r1
+check_r3 0xffffffff
+
+test_name XNOR_8
+load r3 0xaa55aa55
+xnor r3, r3, r3
+check_r3 0xffffffff
+
+end
diff --git a/tests/tcg/lm32/test_xnori.S b/tests/tcg/lm32/test_xnori.S
new file mode 100644
index 0000000000..9d9c3c6780
--- /dev/null
+++ b/tests/tcg/lm32/test_xnori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XNORI_1
+mvi r1, 0
+xnori r3, r1, 0
+check_r3 0xffffffff
+
+test_name XNORI_2
+mvi r1, 0
+xnori r3, r1, 1
+check_r3 0xfffffffe
+
+test_name XNORI_3
+mvi r1, 1
+xnori r3, r1, 1
+check_r3 0xffffffff
+
+test_name XNORI_4
+mvi r1, 1
+xnori r3, r1, 0
+check_r3 0xfffffffe
+
+test_name XNORI_5
+load r1 0xaa55aa55
+xnori r3, r1, 0x5555
+check_r3 0x55aa00ff
+
+test_name XNORI_6
+load r3 0xaa55aa55
+xnori r3, r3, 0x5555
+check_r3 0x55aa00ff
+
+end
diff --git a/tests/tcg/lm32/test_xor.S b/tests/tcg/lm32/test_xor.S
new file mode 100644
index 0000000000..6c6e712bae
--- /dev/null
+++ b/tests/tcg/lm32/test_xor.S
@@ -0,0 +1,51 @@
+.include "macros.inc"
+
+start
+
+test_name XOR_1
+mvi r1, 0
+mvi r2, 0
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_2
+mvi r1, 0
+mvi r2, 1
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_3
+mvi r1, 1
+mvi r2, 1
+xor r3, r1, r2
+check_r3 0
+
+test_name XOR_4
+mvi r1, 1
+mvi r2, 0
+xor r3, r1, r2
+check_r3 1
+
+test_name XOR_5
+load r1 0xaa55aa55
+load r2 0x55aa55aa
+xor r3, r1, r2
+check_r3 0xffffffff
+
+test_name XOR_6
+load r1 0xaa550000
+load r2 0x0000aa55
+xor r3, r1, r2
+check_r3 0xaa55aa55
+
+test_name XOR_7
+load r1 0xaa55aa55
+xor r3, r1, r1
+check_r3 0
+
+test_name XOR_8
+load r3 0xaa55aa55
+xor r3, r3, r3
+check_r3 0
+
+end
diff --git a/tests/tcg/lm32/test_xori.S b/tests/tcg/lm32/test_xori.S
new file mode 100644
index 0000000000..2051699f12
--- /dev/null
+++ b/tests/tcg/lm32/test_xori.S
@@ -0,0 +1,35 @@
+.include "macros.inc"
+
+start
+
+test_name XORI_1
+mvi r1, 0
+xori r3, r1, 0
+check_r3 0
+
+test_name XORI_2
+mvi r1, 0
+xori r3, r1, 1
+check_r3 1
+
+test_name XORI_3
+mvi r1, 1
+xori r3, r1, 1
+check_r3 0
+
+test_name XORI_4
+mvi r1, 1
+xori r3, r1, 0
+check_r3 1
+
+test_name XORI_5
+load r1 0xaa55aa55
+xori r3, r1, 0x5555
+check_r3 0xaa55ff00
+
+test_name XORI_6
+load r3 0xaa55aa55
+xori r3, r3, 0x5555
+check_r3 0xaa55ff00
+
+end
diff --git a/tests/tcg/pi_10.com b/tests/tcg/pi_10.com
new file mode 100644
index 0000000000..8993ba1a51
--- /dev/null
+++ b/tests/tcg/pi_10.com
Binary files differ
diff --git a/tests/tcg/runcom.c b/tests/tcg/runcom.c
new file mode 100644
index 0000000000..d60342bfc6
--- /dev/null
+++ b/tests/tcg/runcom.c
@@ -0,0 +1,192 @@
+/*
+ * Simple example of use of vm86: launch a basic .com DOS executable
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#include <linux/unistd.h>
+#include <asm/vm86.h>
+
+extern int vm86 (unsigned long int subfunction,
+ struct vm86plus_struct *info);
+
+#define VIF_MASK 0x00080000
+
+//#define SIGTEST
+
+#define COM_BASE_ADDR 0x10100
+
+static void usage(void)
+{
+ printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
+ "usage: runcom file.com\n"
+ "VM86 Run simple .com DOS executables (linux vm86 test mode)\n");
+ exit(1);
+}
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+ r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+void dump_regs(struct vm86_regs *r)
+{
+ fprintf(stderr,
+ "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
+ "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
+ "EIP=%08lx EFL=%08lx\n"
+ "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n",
+ r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp,
+ r->eip, r->eflags,
+ r->cs, r->ds, r->es, r->ss, r->fs, r->gs);
+}
+
+#ifdef SIGTEST
+void alarm_handler(int sig)
+{
+ fprintf(stderr, "alarm signal=%d\n", sig);
+ alarm(1);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ uint8_t *vm86_mem;
+ const char *filename;
+ int fd, ret, seg;
+ struct vm86plus_struct ctx;
+ struct vm86_regs *r;
+
+ if (argc != 2)
+ usage();
+ filename = argv[1];
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+#ifdef SIGTEST
+ {
+ struct sigaction act;
+
+ act.sa_handler = alarm_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGALRM, &act, NULL);
+ alarm(1);
+ }
+#endif
+
+ /* load the MSDOS .com executable */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ exit(1);
+ }
+ ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
+ if (ret < 0) {
+ perror("read");
+ exit(1);
+ }
+ close(fd);
+
+ memset(&ctx, 0, sizeof(ctx));
+ /* init basic registers */
+ r = &ctx.regs;
+ r->eip = 0x100;
+ r->esp = 0xfffe;
+ seg = (COM_BASE_ADDR - 0x100) >> 4;
+ r->cs = seg;
+ r->ss = seg;
+ r->ds = seg;
+ r->es = seg;
+ r->fs = seg;
+ r->gs = seg;
+ r->eflags = VIF_MASK;
+
+ /* put return code */
+ set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+ *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */
+ *seg_to_linear(r->cs, 1) = 0x00;
+ *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */
+ *seg_to_linear(r->cs, 3) = 0x21;
+ pushw(&ctx.regs, 0x0000);
+
+ /* the value of these registers seem to be assumed by pi_10.com */
+ r->esi = 0x100;
+ r->ecx = 0xff;
+ r->ebp = 0x0900;
+ r->edi = 0xfffe;
+
+ for(;;) {
+ ret = vm86(VM86_ENTER, &ctx);
+ switch(VM86_TYPE(ret)) {
+ case VM86_INTx:
+ {
+ int int_num, ah;
+
+ int_num = VM86_ARG(ret);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (r->eax >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ exit(0);
+ case 0x02: /* write char */
+ {
+ uint8_t c = r->edx;
+ write(1, &c, 1);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c;
+ for(;;) {
+ c = *seg_to_linear(r->ds, r->edx);
+ if (c == '$')
+ break;
+ write(1, &c, 1);
+ }
+ r->eax = (r->eax & ~0xff) | '$';
+ }
+ break;
+ default:
+ unknown_int:
+ fprintf(stderr, "unsupported int 0x%02x\n", int_num);
+ dump_regs(&ctx.regs);
+ // exit(1);
+ }
+ }
+ break;
+ case VM86_SIGNAL:
+ /* a signal came, we just ignore that */
+ break;
+ case VM86_STI:
+ break;
+ default:
+ fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
+ dump_regs(&ctx.regs);
+ exit(1);
+ }
+ }
+}
diff --git a/tests/tcg/sha1.c b/tests/tcg/sha1.c
new file mode 100644
index 0000000000..93b7c8e808
--- /dev/null
+++ b/tests/tcg/sha1.c
@@ -0,0 +1,240 @@
+
+/* from valgrind tests */
+
+/* ================ sha1.c ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#define SHA1HANDSOFF
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+/* ================ sha1.h ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+*/
+
+typedef struct {
+ uint32_t state[5];
+ uint32_t count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+/* ================ end of sha1.h ================ */
+#include <endian.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#elif BYTE_ORDER == BIG_ENDIAN
+#define blk0(i) block->l[i]
+#else
+#error "Endianness not defined!"
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
+{
+uint32_t a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ uint32_t l[16];
+} CHAR64LONG16;
+#ifdef SHA1HANDSOFF
+CHAR64LONG16 block[1]; /* use array to appear as a pointer */
+ memcpy(block, buffer, 64);
+#else
+ /* The following had better never be used because it causes the
+ * pointer-to-const buffer to be cast into a pointer to non-const.
+ * And the result is written through. I threw a "const" in, hoping
+ * this will cause a diagnostic.
+ */
+CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+ memset(block, '\0', sizeof(block));
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)
+{
+uint32_t i;
+uint32_t j;
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1]++;
+ context->count[1] += (len>>29);
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned i;
+unsigned char finalcount[8];
+unsigned char c;
+
+#if 0 /* untested "improvement" by DHR */
+ /* Convert context->count to a sequence of bytes
+ * in finalcount. Second element first, but
+ * big-endian order within element.
+ * But we do it all backwards.
+ */
+ unsigned char *fcp = &finalcount[8];
+
+ for (i = 0; i < 2; i++)
+ {
+ uint32_t t = context->count[i];
+ int j;
+
+ for (j = 0; j < 4; t >>= 8, j++)
+ *--fcp = (unsigned char) t;
+ }
+#else
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+#endif
+ c = 0200;
+ SHA1Update(context, &c, 1);
+ while ((context->count[0] & 504) != 448) {
+ c = 0000;
+ SHA1Update(context, &c, 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ memset(context, '\0', sizeof(*context));
+ memset(&finalcount, '\0', sizeof(finalcount));
+}
+/* ================ end of sha1.c ================ */
+
+#define BUFSIZE 4096
+
+int
+main(int argc, char **argv)
+{
+ SHA1_CTX ctx;
+ unsigned char hash[20], buf[BUFSIZE];
+ int i;
+
+ for(i=0;i<BUFSIZE;i++)
+ buf[i] = i;
+
+ SHA1Init(&ctx);
+ for(i=0;i<1000;i++)
+ SHA1Update(&ctx, buf, BUFSIZE);
+ SHA1Final(hash, &ctx);
+
+ printf("SHA1=");
+ for(i=0;i<20;i++)
+ printf("%02x", hash[i]);
+ printf("\n");
+ return 0;
+}
diff --git a/tests/tcg/test-arm-iwmmxt.s b/tests/tcg/test-arm-iwmmxt.s
new file mode 100644
index 0000000000..d647f9404a
--- /dev/null
+++ b/tests/tcg/test-arm-iwmmxt.s
@@ -0,0 +1,49 @@
+@ Checks whether iwMMXt is functional.
+.code 32
+.globl main
+
+main:
+ldr r0, =data0
+ldr r1, =data1
+ldr r2, =data2
+#ifndef FPA
+wldrd wr0, [r0, #0]
+wldrd wr1, [r0, #8]
+wldrd wr2, [r1, #0]
+wldrd wr3, [r1, #8]
+wsubb wr2, wr2, wr0
+wsubb wr3, wr3, wr1
+wldrd wr0, [r2, #0]
+wldrd wr1, [r2, #8]
+waddb wr0, wr0, wr2
+waddb wr1, wr1, wr3
+wstrd wr0, [r2, #0]
+wstrd wr1, [r2, #8]
+#else
+ldfe f0, [r0, #0]
+ldfe f1, [r0, #8]
+ldfe f2, [r1, #0]
+ldfe f3, [r1, #8]
+adfdp f2, f2, f0
+adfdp f3, f3, f1
+ldfe f0, [r2, #0]
+ldfe f1, [r2, #8]
+adfd f0, f0, f2
+adfd f1, f1, f3
+stfe f0, [r2, #0]
+stfe f1, [r2, #8]
+#endif
+mov r0, #1
+mov r1, r2
+mov r2, #0x11
+swi #0x900004
+mov r0, #0
+swi #0x900001
+
+.data
+data0:
+.string "aaaabbbbccccdddd"
+data1:
+.string "bbbbccccddddeeee"
+data2:
+.string "hvLLWs\x1fsdrs9\x1fNJ-\n"
diff --git a/tests/tcg/test-i386-code16.S b/tests/tcg/test-i386-code16.S
new file mode 100644
index 0000000000..816c24b96f
--- /dev/null
+++ b/tests/tcg/test-i386-code16.S
@@ -0,0 +1,79 @@
+ .code16
+ .globl code16_start
+ .globl code16_end
+
+CS_SEG = 0xf
+
+code16_start:
+
+ .globl code16_func1
+
+ /* basic test */
+code16_func1 = . - code16_start
+ mov $1, %eax
+ data32 lret
+
+/* test push/pop in 16 bit mode */
+ .globl code16_func2
+code16_func2 = . - code16_start
+ xor %eax, %eax
+ mov $0x12345678, %ebx
+ movl %esp, %ecx
+ push %bx
+ subl %esp, %ecx
+ pop %ax
+ data32 lret
+
+/* test various jmp opcodes */
+ .globl code16_func3
+code16_func3 = . - code16_start
+ jmp 1f
+ nop
+1:
+ mov $4, %eax
+ mov $0x12345678, %ebx
+ xor %bx, %bx
+ jz 2f
+ add $2, %ax
+2:
+
+ call myfunc
+
+ lcall $CS_SEG, $(myfunc2 - code16_start)
+
+ ljmp $CS_SEG, $(myjmp1 - code16_start)
+myjmp1_next:
+
+ cs lcall *myfunc2_addr - code16_start
+
+ cs ljmp *myjmp2_addr - code16_start
+myjmp2_next:
+
+ data32 lret
+
+myfunc2_addr:
+ .short myfunc2 - code16_start
+ .short CS_SEG
+
+myjmp2_addr:
+ .short myjmp2 - code16_start
+ .short CS_SEG
+
+myjmp1:
+ add $8, %ax
+ jmp myjmp1_next
+
+myjmp2:
+ add $16, %ax
+ jmp myjmp2_next
+
+myfunc:
+ add $1, %ax
+ ret
+
+myfunc2:
+ add $4, %ax
+ lret
+
+
+code16_end:
diff --git a/tests/tcg/test-i386-muldiv.h b/tests/tcg/test-i386-muldiv.h
new file mode 100644
index 0000000000..015f59e157
--- /dev/null
+++ b/tests/tcg/test-i386-muldiv.h
@@ -0,0 +1,76 @@
+
+void glue(glue(test_, OP), b)(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm ("push %4\n\t"
+ "popf\n\t"
+ stringify(OP)"b %b2\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ stringify(OP) "b", s0, s1, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), w)(long op0h, long op0, long op1)
+{
+ long res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "w %w3\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+ stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), l)(long op0h, long op0, long op1)
+{
+ long res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "l %k3\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+ stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+#if defined(__x86_64__)
+void glue(glue(test_, OP), q)(long op0h, long op0, long op1)
+{
+ long res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "q %3\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
+ stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+#endif
+
+#undef OP
diff --git a/tests/tcg/test-i386-shift.h b/tests/tcg/test-i386-shift.h
new file mode 100644
index 0000000000..3d8f84bffe
--- /dev/null
+++ b/tests/tcg/test-i386-shift.h
@@ -0,0 +1,185 @@
+
+#define exec_op glue(exec_, OP)
+#define exec_opq glue(glue(exec_, OP), q)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#ifndef OP_SHIFTD
+
+#ifdef OP_NOBYTE
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=g" (res), "=g" (flags)\
+ : "r" (s1), "0" (res), "1" (flags));
+#else
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %%cl, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "c" (s1), "0" (res), "1" (flags));
+#endif
+
+#if defined(__x86_64__)
+void exec_opq(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("q", "", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "q", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_opl(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("l", "k", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("w", "w", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+#else
+#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %%cl, %" rsize "5, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=g" (res), "=g" (flags)\
+ : "c" (s1), "0" (res), "1" (flags), "r" (s2));
+
+#if defined(__x86_64__)
+void exec_opq(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("q", "", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "q", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_opl(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("l", "k", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(long s2, long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("w", "w", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+#endif
+
+#ifndef OP_NOBYTE
+void exec_opb(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("b", "b", res, s1, 0, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
+ stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_op(long s2, long s0, long s1)
+{
+ s2 = i2l(s2);
+ s0 = i2l(s0);
+#if defined(__x86_64__)
+ exec_opq(s2, s0, s1, 0);
+#endif
+ exec_opl(s2, s0, s1, 0);
+#ifdef OP_SHIFTD
+ exec_opw(s2, s0, s1, 0);
+#else
+ exec_opw(s2, s0, s1, 0);
+#endif
+#ifndef OP_NOBYTE
+ exec_opb(s0, s1, 0);
+#endif
+#ifdef OP_CC
+#if defined(__x86_64__)
+ exec_opq(s2, s0, s1, CC_C);
+#endif
+ exec_opl(s2, s0, s1, CC_C);
+ exec_opw(s2, s0, s1, CC_C);
+ exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+ int i, n;
+#if defined(__x86_64__)
+ n = 64;
+#else
+ n = 32;
+#endif
+ for(i = 0; i < n; i++)
+ exec_op(0x21ad3d34, 0x12345678, i);
+ for(i = 0; i < n; i++)
+ exec_op(0x813f3421, 0x82345679, i);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
+#undef OP_SHIFTD
+#undef OP_NOBYTE
+#undef EXECSHIFT
diff --git a/tests/tcg/test-i386-ssse3.c b/tests/tcg/test-i386-ssse3.c
new file mode 100644
index 0000000000..0a42bd03e2
--- /dev/null
+++ b/tests/tcg/test-i386-ssse3.c
@@ -0,0 +1,57 @@
+/* See if various MMX/SSE SSSE3 instructions give expected results */
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+int main(int argc, char *argv[]) {
+ char hello[16];
+ const char ehlo[8] = "EHLO ";
+ uint64_t mask = 0x8080800302020001;
+
+ uint64_t a = 0x0000000000090007;
+ uint64_t b = 0x0000000000000000;
+ uint32_t c;
+ uint16_t d;
+
+ const char e[16] = "LLOaaaaaaaaaaaaa";
+ const char f[16] = "aaaaaaaaaaaaaaHE";
+
+ /* pshufb mm1/xmm1, mm2/xmm2 */
+ asm volatile ("movq (%0), %%mm0" : : "r" (ehlo) : "mm0", "mm1");
+ asm volatile ("movq %0, %%mm1" : : "m" (mask));
+ asm volatile ("pshufb %mm1, %mm0");
+ asm volatile ("movq %%mm0, %0" : "=m" (hello));
+ printf("%s\n", hello);
+
+ /* pshufb mm1/xmm1, m64/m128 */
+ asm volatile ("movq (%0), %%mm0" : : "r" (ehlo) : "mm0");
+ asm volatile ("pshufb %0, %%mm0" : : "m" (mask));
+ asm volatile ("movq %%mm0, %0" : "=m" (hello));
+ printf("%s\n", hello);
+
+ /* psubsw mm1/xmm1, m64/m128 */
+ asm volatile ("movq %0, %%mm0" : : "r" (a) : "mm0");
+ asm volatile ("phsubsw %0, %%mm0" : : "m" (b));
+ asm volatile ("movq %%mm0, %0" : "=m" (a));
+ printf("%i - %i = %i\n", 9, 7, -(int16_t) a);
+
+ /* palignr mm1/xmm1, m64/m128, imm8 */
+ asm volatile ("movdqa (%0), %%xmm0" : : "r" (e) : "xmm0");
+ asm volatile ("palignr $14, (%0), %%xmm0" : : "r" (f));
+ asm volatile ("movdqa %%xmm0, (%0)" : : "r" (hello));
+ printf("%5.5s\n", hello);
+
+#if 1 /* SSE4 */
+ /* popcnt r64, r/m64 */
+ asm volatile ("movq $0x8421000010009c63, %%rax" : : : "rax");
+ asm volatile ("popcnt %%ax, %%dx" : : : "dx");
+ asm volatile ("popcnt %%eax, %%ecx" : : : "ecx");
+ asm volatile ("popcnt %rax, %rax");
+ asm volatile ("movq %%rax, %0" : "=m" (a));
+ asm volatile ("movl %%ecx, %0" : "=m" (c));
+ asm volatile ("movw %%dx, %0" : "=m" (d));
+ printf("%i = %i\n%i = %i = %i\n", 13, (int) a, 9, c, d + 1);
+#endif
+
+ return 0;
+}
diff --git a/tests/tcg/test-i386-vm86.S b/tests/tcg/test-i386-vm86.S
new file mode 100644
index 0000000000..3bb96c9927
--- /dev/null
+++ b/tests/tcg/test-i386-vm86.S
@@ -0,0 +1,103 @@
+ .code16
+ .globl vm86_code_start
+ .globl vm86_code_end
+
+#define GET_OFFSET(x) ((x) - vm86_code_start + 0x100)
+
+vm86_code_start:
+ movw $GET_OFFSET(hello_world), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ /* prepare int 0x90 vector */
+ xorw %ax, %ax
+ movw %ax, %es
+ es movw $GET_OFFSET(int90_test), 0x90 * 4
+ es movw %cs, 0x90 * 4 + 2
+
+ /* launch int 0x90 */
+
+ int $0x90
+
+ /* test IF support */
+ movw $GET_OFFSET(IF_msg), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ cli
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ sti
+ pushfl
+ popl %edx
+ movb $0xff, %ah
+ int $0x21
+
+#if 0
+ movw $GET_OFFSET(IF_msg1), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ pushf
+ movw %sp, %bx
+ andw $~0x200, (%bx)
+ popf
+#else
+ cli
+#endif
+
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ pushfl
+ movw %sp, %bx
+ orw $0x200, (%bx)
+ popfl
+
+ pushfl
+ popl %edx
+ movb $0xff, %ah
+ int $0x21
+
+ movb $0x00, %ah
+ int $0x21
+
+int90_test:
+ pushf
+ pop %dx
+ movb $0xff, %ah
+ int $0x21
+
+ movw %sp, %bx
+ movw 4(%bx), %dx
+ movb $0xff, %ah
+ int $0x21
+
+ movw $GET_OFFSET(int90_msg), %dx
+ movb $0x09, %ah
+ int $0x21
+ iret
+
+int90_msg:
+ .string "INT90 started\n$"
+
+hello_world:
+ .string "Hello VM86 world\n$"
+
+IF_msg:
+ .string "VM86 IF test\n$"
+
+IF_msg1:
+ .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$"
+
+vm86_code_end:
diff --git a/tests/tcg/test-i386.c b/tests/tcg/test-i386.c
new file mode 100644
index 0000000000..8e64bbaf38
--- /dev/null
+++ b/tests/tcg/test-i386.c
@@ -0,0 +1,2764 @@
+/*
+ * x86 CPU test
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+#include <sys/mman.h>
+
+#if !defined(__x86_64__)
+//#define TEST_VM86
+#define TEST_SEGS
+#endif
+//#define LINUX_VM86_IOPL_FIX
+//#define TEST_P4_FLAGS
+#ifdef __SSE__
+#define TEST_SSE
+#define TEST_CMOV 1
+#define TEST_FCOMI 1
+#else
+#undef TEST_SSE
+#define TEST_CMOV 1
+#define TEST_FCOMI 1
+#endif
+
+#if defined(__x86_64__)
+#define FMT64X "%016lx"
+#define FMTLX "%016lx"
+#define X86_64_ONLY(x) x
+#else
+#define FMT64X "%016" PRIx64
+#define FMTLX "%08lx"
+#define X86_64_ONLY(x)
+#endif
+
+#ifdef TEST_VM86
+#include <asm/vm86.h>
+#endif
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+#define CC_C 0x0001
+#define CC_P 0x0004
+#define CC_A 0x0010
+#define CC_Z 0x0040
+#define CC_S 0x0080
+#define CC_O 0x0800
+
+#define __init_call __attribute__ ((unused,__section__ ("initcall")))
+
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+
+#if defined(__x86_64__)
+static inline long i2l(long v)
+{
+ return v | ((v ^ 0xabcd) << 32);
+}
+#else
+static inline long i2l(long v)
+{
+ return v;
+}
+#endif
+
+#define OP add
+#include "test-i386.h"
+
+#define OP sub
+#include "test-i386.h"
+
+#define OP xor
+#include "test-i386.h"
+
+#define OP and
+#include "test-i386.h"
+
+#define OP or
+#include "test-i386.h"
+
+#define OP cmp
+#include "test-i386.h"
+
+#define OP adc
+#define OP_CC
+#include "test-i386.h"
+
+#define OP sbb
+#define OP_CC
+#include "test-i386.h"
+
+#define OP inc
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP dec
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP neg
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP not
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#undef CC_MASK
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
+
+#define OP shl
+#include "test-i386-shift.h"
+
+#define OP shr
+#include "test-i386-shift.h"
+
+#define OP sar
+#include "test-i386-shift.h"
+
+#define OP rol
+#include "test-i386-shift.h"
+
+#define OP ror
+#include "test-i386-shift.h"
+
+#define OP rcr
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP rcl
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP shld
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP shrd
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* XXX: should be more precise ? */
+#undef CC_MASK
+#define CC_MASK (CC_C)
+
+#define OP bt
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP bts
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btr
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btc
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* lea test (modrm support) */
+#define TEST_LEAQ(STR)\
+{\
+ asm("lea " STR ", %0"\
+ : "=r" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = " FMTLX "\n", STR, res);\
+}
+
+#define TEST_LEA(STR)\
+{\
+ asm("lea " STR ", %0"\
+ : "=r" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = " FMTLX "\n", STR, res);\
+}
+
+#define TEST_LEA16(STR)\
+{\
+ asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
+ : "=wq" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = %08lx\n", STR, res);\
+}
+
+
+void test_lea(void)
+{
+ long eax, ebx, ecx, edx, esi, edi, res;
+ eax = i2l(0x0001);
+ ebx = i2l(0x0002);
+ ecx = i2l(0x0004);
+ edx = i2l(0x0008);
+ esi = i2l(0x0010);
+ edi = i2l(0x0020);
+
+ TEST_LEA("0x4000");
+
+ TEST_LEA("(%%eax)");
+ TEST_LEA("(%%ebx)");
+ TEST_LEA("(%%ecx)");
+ TEST_LEA("(%%edx)");
+ TEST_LEA("(%%esi)");
+ TEST_LEA("(%%edi)");
+
+ TEST_LEA("0x40(%%eax)");
+ TEST_LEA("0x40(%%ebx)");
+ TEST_LEA("0x40(%%ecx)");
+ TEST_LEA("0x40(%%edx)");
+ TEST_LEA("0x40(%%esi)");
+ TEST_LEA("0x40(%%edi)");
+
+ TEST_LEA("0x4000(%%eax)");
+ TEST_LEA("0x4000(%%ebx)");
+ TEST_LEA("0x4000(%%ecx)");
+ TEST_LEA("0x4000(%%edx)");
+ TEST_LEA("0x4000(%%esi)");
+ TEST_LEA("0x4000(%%edi)");
+
+ TEST_LEA("(%%eax, %%ecx)");
+ TEST_LEA("(%%ebx, %%edx)");
+ TEST_LEA("(%%ecx, %%ecx)");
+ TEST_LEA("(%%edx, %%ecx)");
+ TEST_LEA("(%%esi, %%ecx)");
+ TEST_LEA("(%%edi, %%ecx)");
+
+ TEST_LEA("0x40(%%eax, %%ecx)");
+ TEST_LEA("0x4000(%%ebx, %%edx)");
+
+ TEST_LEA("(%%ecx, %%ecx, 2)");
+ TEST_LEA("(%%edx, %%ecx, 4)");
+ TEST_LEA("(%%esi, %%ecx, 8)");
+
+ TEST_LEA("(,%%eax, 2)");
+ TEST_LEA("(,%%ebx, 4)");
+ TEST_LEA("(,%%ecx, 8)");
+
+ TEST_LEA("0x40(,%%eax, 2)");
+ TEST_LEA("0x40(,%%ebx, 4)");
+ TEST_LEA("0x40(,%%ecx, 8)");
+
+
+ TEST_LEA("-10(%%ecx, %%ecx, 2)");
+ TEST_LEA("-10(%%edx, %%ecx, 4)");
+ TEST_LEA("-10(%%esi, %%ecx, 8)");
+
+ TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
+ TEST_LEA("0x4000(%%edx, %%ecx, 4)");
+ TEST_LEA("0x4000(%%esi, %%ecx, 8)");
+
+#if defined(__x86_64__)
+ TEST_LEAQ("0x4000");
+ TEST_LEAQ("0x4000(%%rip)");
+
+ TEST_LEAQ("(%%rax)");
+ TEST_LEAQ("(%%rbx)");
+ TEST_LEAQ("(%%rcx)");
+ TEST_LEAQ("(%%rdx)");
+ TEST_LEAQ("(%%rsi)");
+ TEST_LEAQ("(%%rdi)");
+
+ TEST_LEAQ("0x40(%%rax)");
+ TEST_LEAQ("0x40(%%rbx)");
+ TEST_LEAQ("0x40(%%rcx)");
+ TEST_LEAQ("0x40(%%rdx)");
+ TEST_LEAQ("0x40(%%rsi)");
+ TEST_LEAQ("0x40(%%rdi)");
+
+ TEST_LEAQ("0x4000(%%rax)");
+ TEST_LEAQ("0x4000(%%rbx)");
+ TEST_LEAQ("0x4000(%%rcx)");
+ TEST_LEAQ("0x4000(%%rdx)");
+ TEST_LEAQ("0x4000(%%rsi)");
+ TEST_LEAQ("0x4000(%%rdi)");
+
+ TEST_LEAQ("(%%rax, %%rcx)");
+ TEST_LEAQ("(%%rbx, %%rdx)");
+ TEST_LEAQ("(%%rcx, %%rcx)");
+ TEST_LEAQ("(%%rdx, %%rcx)");
+ TEST_LEAQ("(%%rsi, %%rcx)");
+ TEST_LEAQ("(%%rdi, %%rcx)");
+
+ TEST_LEAQ("0x40(%%rax, %%rcx)");
+ TEST_LEAQ("0x4000(%%rbx, %%rdx)");
+
+ TEST_LEAQ("(%%rcx, %%rcx, 2)");
+ TEST_LEAQ("(%%rdx, %%rcx, 4)");
+ TEST_LEAQ("(%%rsi, %%rcx, 8)");
+
+ TEST_LEAQ("(,%%rax, 2)");
+ TEST_LEAQ("(,%%rbx, 4)");
+ TEST_LEAQ("(,%%rcx, 8)");
+
+ TEST_LEAQ("0x40(,%%rax, 2)");
+ TEST_LEAQ("0x40(,%%rbx, 4)");
+ TEST_LEAQ("0x40(,%%rcx, 8)");
+
+
+ TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
+ TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
+ TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
+
+ TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
+ TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
+ TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
+#else
+ /* limited 16 bit addressing test */
+ TEST_LEA16("0x4000");
+ TEST_LEA16("(%%bx)");
+ TEST_LEA16("(%%si)");
+ TEST_LEA16("(%%di)");
+ TEST_LEA16("0x40(%%bx)");
+ TEST_LEA16("0x40(%%si)");
+ TEST_LEA16("0x40(%%di)");
+ TEST_LEA16("0x4000(%%bx)");
+ TEST_LEA16("0x4000(%%si)");
+ TEST_LEA16("(%%bx,%%si)");
+ TEST_LEA16("(%%bx,%%di)");
+ TEST_LEA16("0x40(%%bx,%%si)");
+ TEST_LEA16("0x40(%%bx,%%di)");
+ TEST_LEA16("0x4000(%%bx,%%si)");
+ TEST_LEA16("0x4000(%%bx,%%di)");
+#endif
+}
+
+#define TEST_JCC(JCC, v1, v2)\
+{\
+ int res;\
+ asm("movl $1, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "j" JCC " 1f\n\t"\
+ "movl $0, %0\n\t"\
+ "1:\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2));\
+ printf("%-10s %d\n", "j" JCC, res);\
+\
+ asm("movl $0, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "set" JCC " %b0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2));\
+ printf("%-10s %d\n", "set" JCC, res);\
+ if (TEST_CMOV) {\
+ long val = i2l(1);\
+ long res = i2l(0x12345678);\
+X86_64_ONLY(\
+ asm("cmpl %2, %1\n\t"\
+ "cmov" JCC "q %3, %0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "m" (val), "0" (res));\
+ printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
+ asm("cmpl %2, %1\n\t"\
+ "cmov" JCC "l %k3, %k0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "m" (val), "0" (res));\
+ printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
+ asm("cmpl %2, %1\n\t"\
+ "cmov" JCC "w %w3, %w0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "r" (1), "0" (res));\
+ printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
+ } \
+}
+
+/* various jump tests */
+void test_jcc(void)
+{
+ TEST_JCC("ne", 1, 1);
+ TEST_JCC("ne", 1, 0);
+
+ TEST_JCC("e", 1, 1);
+ TEST_JCC("e", 1, 0);
+
+ TEST_JCC("l", 1, 1);
+ TEST_JCC("l", 1, 0);
+ TEST_JCC("l", 1, -1);
+
+ TEST_JCC("le", 1, 1);
+ TEST_JCC("le", 1, 0);
+ TEST_JCC("le", 1, -1);
+
+ TEST_JCC("ge", 1, 1);
+ TEST_JCC("ge", 1, 0);
+ TEST_JCC("ge", -1, 1);
+
+ TEST_JCC("g", 1, 1);
+ TEST_JCC("g", 1, 0);
+ TEST_JCC("g", 1, -1);
+
+ TEST_JCC("b", 1, 1);
+ TEST_JCC("b", 1, 0);
+ TEST_JCC("b", 1, -1);
+
+ TEST_JCC("be", 1, 1);
+ TEST_JCC("be", 1, 0);
+ TEST_JCC("be", 1, -1);
+
+ TEST_JCC("ae", 1, 1);
+ TEST_JCC("ae", 1, 0);
+ TEST_JCC("ae", 1, -1);
+
+ TEST_JCC("a", 1, 1);
+ TEST_JCC("a", 1, 0);
+ TEST_JCC("a", 1, -1);
+
+
+ TEST_JCC("p", 1, 1);
+ TEST_JCC("p", 1, 0);
+
+ TEST_JCC("np", 1, 1);
+ TEST_JCC("np", 1, 0);
+
+ TEST_JCC("o", 0x7fffffff, 0);
+ TEST_JCC("o", 0x7fffffff, -1);
+
+ TEST_JCC("no", 0x7fffffff, 0);
+ TEST_JCC("no", 0x7fffffff, -1);
+
+ TEST_JCC("s", 0, 1);
+ TEST_JCC("s", 0, -1);
+ TEST_JCC("s", 0, 0);
+
+ TEST_JCC("ns", 0, 1);
+ TEST_JCC("ns", 0, -1);
+ TEST_JCC("ns", 0, 0);
+}
+
+#define TEST_LOOP(insn) \
+{\
+ for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\
+ ecx = ecx_vals[i];\
+ for(zf = 0; zf < 2; zf++) {\
+ asm("test %2, %2\n\t"\
+ "movl $1, %0\n\t"\
+ insn " 1f\n\t" \
+ "movl $0, %0\n\t"\
+ "1:\n\t"\
+ : "=a" (res)\
+ : "c" (ecx), "b" (!zf)); \
+ printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res); \
+ }\
+ }\
+}
+
+void test_loop(void)
+{
+ long ecx, zf;
+ const long ecx_vals[] = {
+ 0,
+ 1,
+ 0x10000,
+ 0x10001,
+#if defined(__x86_64__)
+ 0x100000000L,
+ 0x100000001L,
+#endif
+ };
+ int i, res;
+
+#if !defined(__x86_64__)
+ TEST_LOOP("jcxz");
+ TEST_LOOP("loopw");
+ TEST_LOOP("loopzw");
+ TEST_LOOP("loopnzw");
+#endif
+
+ TEST_LOOP("jecxz");
+ TEST_LOOP("loopl");
+ TEST_LOOP("loopzl");
+ TEST_LOOP("loopnzl");
+}
+
+#undef CC_MASK
+#ifdef TEST_P4_FLAGS
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+#else
+#define CC_MASK (CC_O | CC_C)
+#endif
+
+#define OP mul
+#include "test-i386-muldiv.h"
+
+#define OP imul
+#include "test-i386-muldiv.h"
+
+void test_imulw2(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm volatile ("push %4\n\t"
+ "popf\n\t"
+ "imulw %w2, %w0\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ "imulw", s0, s1, res, flags & CC_MASK);
+}
+
+void test_imull2(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm volatile ("push %4\n\t"
+ "popf\n\t"
+ "imull %k2, %k0\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ "imull", s0, s1, res, flags & CC_MASK);
+}
+
+#if defined(__x86_64__)
+void test_imulq2(long op0, long op1)
+{
+ long res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm volatile ("push %4\n\t"
+ "popf\n\t"
+ "imulq %2, %0\n\t"
+ "pushf\n\t"
+ "pop %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
+ "imulq", s0, s1, res, flags & CC_MASK);
+}
+#endif
+
+#define TEST_IMUL_IM(size, rsize, op0, op1)\
+{\
+ long res, flags, s1;\
+ flags = 0;\
+ res = 0;\
+ s1 = op1;\
+ asm volatile ("push %3\n\t"\
+ "popf\n\t"\
+ "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=r" (res), "=g" (flags)\
+ : "r" (s1), "1" (flags), "0" (res));\
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
+ "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
+}
+
+
+#undef CC_MASK
+#define CC_MASK (0)
+
+#define OP div
+#include "test-i386-muldiv.h"
+
+#define OP idiv
+#include "test-i386-muldiv.h"
+
+void test_mul(void)
+{
+ test_imulb(0x1234561d, 4);
+ test_imulb(3, -4);
+ test_imulb(0x80, 0x80);
+ test_imulb(0x10, 0x10);
+
+ test_imulw(0, 0x1234001d, 45);
+ test_imulw(0, 23, -45);
+ test_imulw(0, 0x8000, 0x8000);
+ test_imulw(0, 0x100, 0x100);
+
+ test_imull(0, 0x1234001d, 45);
+ test_imull(0, 23, -45);
+ test_imull(0, 0x80000000, 0x80000000);
+ test_imull(0, 0x10000, 0x10000);
+
+ test_mulb(0x1234561d, 4);
+ test_mulb(3, -4);
+ test_mulb(0x80, 0x80);
+ test_mulb(0x10, 0x10);
+
+ test_mulw(0, 0x1234001d, 45);
+ test_mulw(0, 23, -45);
+ test_mulw(0, 0x8000, 0x8000);
+ test_mulw(0, 0x100, 0x100);
+
+ test_mull(0, 0x1234001d, 45);
+ test_mull(0, 23, -45);
+ test_mull(0, 0x80000000, 0x80000000);
+ test_mull(0, 0x10000, 0x10000);
+
+ test_imulw2(0x1234001d, 45);
+ test_imulw2(23, -45);
+ test_imulw2(0x8000, 0x8000);
+ test_imulw2(0x100, 0x100);
+
+ test_imull2(0x1234001d, 45);
+ test_imull2(23, -45);
+ test_imull2(0x80000000, 0x80000000);
+ test_imull2(0x10000, 0x10000);
+
+ TEST_IMUL_IM("w", "w", 45, 0x1234);
+ TEST_IMUL_IM("w", "w", -45, 23);
+ TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
+ TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
+
+ TEST_IMUL_IM("l", "k", 45, 0x1234);
+ TEST_IMUL_IM("l", "k", -45, 23);
+ TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
+ TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
+
+ test_idivb(0x12341678, 0x127e);
+ test_idivb(0x43210123, -5);
+ test_idivb(0x12340004, -1);
+
+ test_idivw(0, 0x12345678, 12347);
+ test_idivw(0, -23223, -45);
+ test_idivw(0, 0x12348000, -1);
+ test_idivw(0x12343, 0x12345678, 0x81238567);
+
+ test_idivl(0, 0x12345678, 12347);
+ test_idivl(0, -233223, -45);
+ test_idivl(0, 0x80000000, -1);
+ test_idivl(0x12343, 0x12345678, 0x81234567);
+
+ test_divb(0x12341678, 0x127e);
+ test_divb(0x43210123, -5);
+ test_divb(0x12340004, -1);
+
+ test_divw(0, 0x12345678, 12347);
+ test_divw(0, -23223, -45);
+ test_divw(0, 0x12348000, -1);
+ test_divw(0x12343, 0x12345678, 0x81238567);
+
+ test_divl(0, 0x12345678, 12347);
+ test_divl(0, -233223, -45);
+ test_divl(0, 0x80000000, -1);
+ test_divl(0x12343, 0x12345678, 0x81234567);
+
+#if defined(__x86_64__)
+ test_imulq(0, 0x1234001d1234001d, 45);
+ test_imulq(0, 23, -45);
+ test_imulq(0, 0x8000000000000000, 0x8000000000000000);
+ test_imulq(0, 0x100000000, 0x100000000);
+
+ test_mulq(0, 0x1234001d1234001d, 45);
+ test_mulq(0, 23, -45);
+ test_mulq(0, 0x8000000000000000, 0x8000000000000000);
+ test_mulq(0, 0x100000000, 0x100000000);
+
+ test_imulq2(0x1234001d1234001d, 45);
+ test_imulq2(23, -45);
+ test_imulq2(0x8000000000000000, 0x8000000000000000);
+ test_imulq2(0x100000000, 0x100000000);
+
+ TEST_IMUL_IM("q", "", 45, 0x12341234);
+ TEST_IMUL_IM("q", "", -45, 23);
+ TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
+ TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
+
+ test_idivq(0, 0x12345678abcdef, 12347);
+ test_idivq(0, -233223, -45);
+ test_idivq(0, 0x8000000000000000, -1);
+ test_idivq(0x12343, 0x12345678, 0x81234567);
+
+ test_divq(0, 0x12345678abcdef, 12347);
+ test_divq(0, -233223, -45);
+ test_divq(0, 0x8000000000000000, -1);
+ test_divq(0x12343, 0x12345678, 0x81234567);
+#endif
+}
+
+#define TEST_BSX(op, size, op0)\
+{\
+ long res, val, resz;\
+ val = op0;\
+ asm("xor %1, %1\n"\
+ "mov $0x12345678, %0\n"\
+ #op " %" size "2, %" size "0 ; setz %b1" \
+ : "=&r" (res), "=&q" (resz)\
+ : "r" (val));\
+ printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
+}
+
+void test_bsx(void)
+{
+ TEST_BSX(bsrw, "w", 0);
+ TEST_BSX(bsrw, "w", 0x12340128);
+ TEST_BSX(bsfw, "w", 0);
+ TEST_BSX(bsfw, "w", 0x12340128);
+ TEST_BSX(bsrl, "k", 0);
+ TEST_BSX(bsrl, "k", 0x00340128);
+ TEST_BSX(bsfl, "k", 0);
+ TEST_BSX(bsfl, "k", 0x00340128);
+#if defined(__x86_64__)
+ TEST_BSX(bsrq, "", 0);
+ TEST_BSX(bsrq, "", 0x003401281234);
+ TEST_BSX(bsfq, "", 0);
+ TEST_BSX(bsfq, "", 0x003401281234);
+#endif
+}
+
+/**********************************************/
+
+union float64u {
+ double d;
+ uint64_t l;
+};
+
+union float64u q_nan = { .l = 0xFFF8000000000000LL };
+union float64u s_nan = { .l = 0xFFF0000000000000LL };
+
+void test_fops(double a, double b)
+{
+ printf("a=%f b=%f a+b=%f\n", a, b, a + b);
+ printf("a=%f b=%f a-b=%f\n", a, b, a - b);
+ printf("a=%f b=%f a*b=%f\n", a, b, a * b);
+ printf("a=%f b=%f a/b=%f\n", a, b, a / b);
+ printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
+ printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
+ printf("a=%f sin(a)=%f\n", a, sin(a));
+ printf("a=%f cos(a)=%f\n", a, cos(a));
+ printf("a=%f tan(a)=%f\n", a, tan(a));
+ printf("a=%f log(a)=%f\n", a, log(a));
+ printf("a=%f exp(a)=%f\n", a, exp(a));
+ printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
+ /* just to test some op combining */
+ printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
+ printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
+ printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
+
+}
+
+void fpu_clear_exceptions(void)
+{
+ struct QEMU_PACKED {
+ uint16_t fpuc;
+ uint16_t dummy1;
+ uint16_t fpus;
+ uint16_t dummy2;
+ uint16_t fptag;
+ uint16_t dummy3;
+ uint32_t ignored[4];
+ long double fpregs[8];
+ } float_env32;
+
+ asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+ float_env32.fpus &= ~0x7f;
+ asm volatile ("fldenv %0\n" : : "m" (float_env32));
+}
+
+/* XXX: display exception bits when supported */
+#define FPUS_EMASK 0x0000
+//#define FPUS_EMASK 0x007f
+
+void test_fcmp(double a, double b)
+{
+ long eflags, fpus;
+
+ fpu_clear_exceptions();
+ asm("fcom %2\n"
+ "fstsw %%ax\n"
+ : "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fcom(%f %f)=%04lx\n",
+ a, b, fpus & (0x4500 | FPUS_EMASK));
+ fpu_clear_exceptions();
+ asm("fucom %2\n"
+ "fstsw %%ax\n"
+ : "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fucom(%f %f)=%04lx\n",
+ a, b, fpus & (0x4500 | FPUS_EMASK));
+ if (TEST_FCOMI) {
+ /* test f(u)comi instruction */
+ fpu_clear_exceptions();
+ asm("fcomi %3, %2\n"
+ "fstsw %%ax\n"
+ "pushf\n"
+ "pop %0\n"
+ : "=r" (eflags), "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fcomi(%f %f)=%04lx %02lx\n",
+ a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
+ fpu_clear_exceptions();
+ asm("fucomi %3, %2\n"
+ "fstsw %%ax\n"
+ "pushf\n"
+ "pop %0\n"
+ : "=r" (eflags), "=a" (fpus)
+ : "t" (a), "u" (b));
+ printf("fucomi(%f %f)=%04lx %02lx\n",
+ a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
+ }
+ fpu_clear_exceptions();
+ asm volatile("fxam\n"
+ "fstsw %%ax\n"
+ : "=a" (fpus)
+ : "t" (a));
+ printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
+ fpu_clear_exceptions();
+}
+
+void test_fcvt(double a)
+{
+ float fa;
+ long double la;
+ int16_t fpuc;
+ int i;
+ int64_t lla;
+ int ia;
+ int16_t wa;
+ double ra;
+
+ fa = a;
+ la = a;
+ printf("(float)%f = %f\n", a, fa);
+ printf("(long double)%f = %Lf\n", a, la);
+ printf("a=" FMT64X "\n", *(uint64_t *)&a);
+ printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
+ *(unsigned short *)((char *)(&la) + 8));
+
+ /* test all roundings */
+ asm volatile ("fstcw %0" : "=m" (fpuc));
+ for(i=0;i<4;i++) {
+ uint16_t val16;
+ val16 = (fpuc & ~0x0c00) | (i << 10);
+ asm volatile ("fldcw %0" : : "m" (val16));
+ asm volatile ("fist %0" : "=m" (wa) : "t" (a));
+ asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
+ asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
+ asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
+ asm volatile ("fldcw %0" : : "m" (fpuc));
+ printf("(short)a = %d\n", wa);
+ printf("(int)a = %d\n", ia);
+ printf("(int64_t)a = " FMT64X "\n", lla);
+ printf("rint(a) = %f\n", ra);
+ }
+}
+
+#define TEST(N) \
+ asm("fld" #N : "=t" (a)); \
+ printf("fld" #N "= %f\n", a);
+
+void test_fconst(void)
+{
+ double a;
+ TEST(1);
+ TEST(l2t);
+ TEST(l2e);
+ TEST(pi);
+ TEST(lg2);
+ TEST(ln2);
+ TEST(z);
+}
+
+void test_fbcd(double a)
+{
+ unsigned short bcd[5];
+ double b;
+
+ asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
+ asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
+ printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
+ a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
+}
+
+#define TEST_ENV(env, save, restore)\
+{\
+ memset((env), 0xaa, sizeof(*(env)));\
+ for(i=0;i<5;i++)\
+ asm volatile ("fldl %0" : : "m" (dtab[i]));\
+ asm volatile (save " %0\n" : : "m" (*(env)));\
+ asm volatile (restore " %0\n": : "m" (*(env)));\
+ for(i=0;i<5;i++)\
+ asm volatile ("fstpl %0" : "=m" (rtab[i]));\
+ for(i=0;i<5;i++)\
+ printf("res[%d]=%f\n", i, rtab[i]);\
+ printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
+ (env)->fpuc,\
+ (env)->fpus & 0xff00,\
+ (env)->fptag);\
+}
+
+void test_fenv(void)
+{
+ struct QEMU_PACKED {
+ uint16_t fpuc;
+ uint16_t dummy1;
+ uint16_t fpus;
+ uint16_t dummy2;
+ uint16_t fptag;
+ uint16_t dummy3;
+ uint32_t ignored[4];
+ long double fpregs[8];
+ } float_env32;
+ struct QEMU_PACKED {
+ uint16_t fpuc;
+ uint16_t fpus;
+ uint16_t fptag;
+ uint16_t ignored[4];
+ long double fpregs[8];
+ } float_env16;
+ double dtab[8];
+ double rtab[8];
+ int i;
+
+ for(i=0;i<8;i++)
+ dtab[i] = i + 1;
+
+ TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
+ TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
+ TEST_ENV(&float_env32, "fnstenv", "fldenv");
+ TEST_ENV(&float_env32, "fnsave", "frstor");
+
+ /* test for ffree */
+ for(i=0;i<5;i++)
+ asm volatile ("fldl %0" : : "m" (dtab[i]));
+ asm volatile("ffree %st(2)");
+ asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+ asm volatile ("fninit");
+ printf("fptag=%04x\n", float_env32.fptag);
+}
+
+
+#define TEST_FCMOV(a, b, eflags, CC)\
+{\
+ double res;\
+ asm("push %3\n"\
+ "popf\n"\
+ "fcmov" CC " %2, %0\n"\
+ : "=t" (res)\
+ : "0" (a), "u" (b), "g" (eflags));\
+ printf("fcmov%s eflags=0x%04lx-> %f\n", \
+ CC, (long)eflags, res);\
+}
+
+void test_fcmov(void)
+{
+ double a, b;
+ long eflags, i;
+
+ a = 1.0;
+ b = 2.0;
+ for(i = 0; i < 4; i++) {
+ eflags = 0;
+ if (i & 1)
+ eflags |= CC_C;
+ if (i & 2)
+ eflags |= CC_Z;
+ TEST_FCMOV(a, b, eflags, "b");
+ TEST_FCMOV(a, b, eflags, "e");
+ TEST_FCMOV(a, b, eflags, "be");
+ TEST_FCMOV(a, b, eflags, "nb");
+ TEST_FCMOV(a, b, eflags, "ne");
+ TEST_FCMOV(a, b, eflags, "nbe");
+ }
+ TEST_FCMOV(a, b, 0, "u");
+ TEST_FCMOV(a, b, CC_P, "u");
+ TEST_FCMOV(a, b, 0, "nu");
+ TEST_FCMOV(a, b, CC_P, "nu");
+}
+
+void test_floats(void)
+{
+ test_fops(2, 3);
+ test_fops(1.4, -5);
+ test_fcmp(2, -1);
+ test_fcmp(2, 2);
+ test_fcmp(2, 3);
+ test_fcmp(2, q_nan.d);
+ test_fcmp(q_nan.d, -1);
+ test_fcmp(-1.0/0.0, -1);
+ test_fcmp(1.0/0.0, -1);
+ test_fcvt(0.5);
+ test_fcvt(-0.5);
+ test_fcvt(1.0/7.0);
+ test_fcvt(-1.0/9.0);
+ test_fcvt(32768);
+ test_fcvt(-1e20);
+ test_fcvt(-1.0/0.0);
+ test_fcvt(1.0/0.0);
+ test_fcvt(q_nan.d);
+ test_fconst();
+ test_fbcd(1234567890123456.0);
+ test_fbcd(-123451234567890.0);
+ test_fenv();
+ if (TEST_CMOV) {
+ test_fcmov();
+ }
+}
+
+/**********************************************/
+#if !defined(__x86_64__)
+
+#define TEST_BCD(op, op0, cc_in, cc_mask)\
+{\
+ int res, flags;\
+ res = op0;\
+ flags = cc_in;\
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ #op "\n\t"\
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=a" (res), "=g" (flags)\
+ : "0" (res), "1" (flags));\
+ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
+ #op, op0, res, cc_in, flags & cc_mask);\
+}
+
+void test_bcd(void)
+{
+ TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+ TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+ TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
+
+ TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
+
+ TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+ TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+}
+#endif
+
+#define TEST_XCHG(op, size, opconst)\
+{\
+ long op0, op1;\
+ op0 = i2l(0x12345678);\
+ op1 = i2l(0xfbca7654);\
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
+ : "0" (op0));\
+ printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
+ #op, op0, op1);\
+}
+
+#define TEST_CMPXCHG(op, size, opconst, eax)\
+{\
+ long op0, op1, op2;\
+ op0 = i2l(0x12345678);\
+ op1 = i2l(0xfbca7654);\
+ op2 = i2l(eax);\
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
+ : "0" (op0), "a" (op2));\
+ printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
+ #op, op2, op0, op1);\
+}
+
+void test_xchg(void)
+{
+#if defined(__x86_64__)
+ TEST_XCHG(xchgq, "", "+q");
+#endif
+ TEST_XCHG(xchgl, "k", "+q");
+ TEST_XCHG(xchgw, "w", "+q");
+ TEST_XCHG(xchgb, "b", "+q");
+
+#if defined(__x86_64__)
+ TEST_XCHG(xchgq, "", "=m");
+#endif
+ TEST_XCHG(xchgl, "k", "+m");
+ TEST_XCHG(xchgw, "w", "+m");
+ TEST_XCHG(xchgb, "b", "+m");
+
+#if defined(__x86_64__)
+ TEST_XCHG(xaddq, "", "+q");
+#endif
+ TEST_XCHG(xaddl, "k", "+q");
+ TEST_XCHG(xaddw, "w", "+q");
+ TEST_XCHG(xaddb, "b", "+q");
+
+ {
+ int res;
+ res = 0x12345678;
+ asm("xaddl %1, %0" : "=r" (res) : "0" (res));
+ printf("xaddl same res=%08x\n", res);
+ }
+
+#if defined(__x86_64__)
+ TEST_XCHG(xaddq, "", "+m");
+#endif
+ TEST_XCHG(xaddl, "k", "+m");
+ TEST_XCHG(xaddw, "w", "+m");
+ TEST_XCHG(xaddb, "b", "+m");
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654);
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc);
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654);
+
+#if defined(__x86_64__)
+ TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc);
+#endif
+ TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc);
+
+ {
+ uint64_t op0, op1, op2;
+ long eax, edx;
+ long i, eflags;
+
+ for(i = 0; i < 2; i++) {
+ op0 = 0x123456789abcdLL;
+ eax = i2l(op0 & 0xffffffff);
+ edx = i2l(op0 >> 32);
+ if (i == 0)
+ op1 = 0xfbca765423456LL;
+ else
+ op1 = op0;
+ op2 = 0x6532432432434LL;
+ asm("cmpxchg8b %2\n"
+ "pushf\n"
+ "pop %3\n"
+ : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags)
+ : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
+ printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n",
+ eax, edx, op1, eflags & CC_Z);
+ }
+ }
+}
+
+#ifdef TEST_SEGS
+/**********************************************/
+/* segmentation tests */
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <asm/ldt.h>
+#include <linux/version.h>
+
+static inline int modify_ldt(int func, void * ptr, unsigned long bytecount)
+{
+ return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
+#define modify_ldt_ldt_s user_desc
+#endif
+
+#define MK_SEL(n) (((n) << 3) | 7)
+
+uint8_t seg_data1[4096];
+uint8_t seg_data2[4096];
+
+#define TEST_LR(op, size, seg, mask)\
+{\
+ int res, res2;\
+ uint16_t mseg = seg;\
+ res = 0x12345678;\
+ asm (op " %" size "2, %" size "0\n" \
+ "movl $0, %1\n"\
+ "jnz 1f\n"\
+ "movl $1, %1\n"\
+ "1:\n"\
+ : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\
+ printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
+}
+
+#define TEST_ARPL(op, size, op1, op2)\
+{\
+ long a, b, c; \
+ a = (op1); \
+ b = (op2); \
+ asm volatile(op " %" size "3, %" size "0\n"\
+ "movl $0,%1\n"\
+ "jnz 1f\n"\
+ "movl $1,%1\n"\
+ "1:\n"\
+ : "=r" (a), "=r" (c) : "0" (a), "r" (b)); \
+ printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\
+ (long)(op1), (long)(op2), a, c);\
+}
+
+/* NOTE: we use Linux modify_ldt syscall */
+void test_segs(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ long long ldt_table[3];
+ int res, res2;
+ char tmp;
+ struct {
+ uint32_t offset;
+ uint16_t seg;
+ } QEMU_PACKED segoff;
+
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&seg_data1;
+ ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ ldt.entry_number = 2;
+ ldt.base_addr = (unsigned long)&seg_data2;
+ ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
+#if 0
+ {
+ int i;
+ for(i=0;i<3;i++)
+ printf("%d: %016Lx\n", i, ldt_table[i]);
+ }
+#endif
+ /* do some tests with fs or gs */
+ asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+
+ seg_data1[1] = 0xaa;
+ seg_data2[1] = 0x55;
+
+ asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
+ printf("FS[1] = %02x\n", res);
+
+ asm volatile ("pushl %%gs\n"
+ "movl %1, %%gs\n"
+ "gs movzbl 0x1, %0\n"
+ "popl %%gs\n"
+ : "=r" (res)
+ : "r" (MK_SEL(2)));
+ printf("GS[1] = %02x\n", res);
+
+ /* tests with ds/ss (implicit segment case) */
+ tmp = 0xa5;
+ asm volatile ("pushl %%ebp\n\t"
+ "pushl %%ds\n\t"
+ "movl %2, %%ds\n\t"
+ "movl %3, %%ebp\n\t"
+ "movzbl 0x1, %0\n\t"
+ "movzbl (%%ebp), %1\n\t"
+ "popl %%ds\n\t"
+ "popl %%ebp\n\t"
+ : "=r" (res), "=r" (res2)
+ : "r" (MK_SEL(1)), "r" (&tmp));
+ printf("DS[1] = %02x\n", res);
+ printf("SS[tmp] = %02x\n", res2);
+
+ segoff.seg = MK_SEL(2);
+ segoff.offset = 0xabcdef12;
+ asm volatile("lfs %2, %0\n\t"
+ "movl %%fs, %1\n\t"
+ : "=r" (res), "=g" (res2)
+ : "m" (segoff));
+ printf("FS:reg = %04x:%08x\n", res2, res);
+
+ TEST_LR("larw", "w", MK_SEL(2), 0x0100);
+ TEST_LR("larl", "", MK_SEL(2), 0x0100);
+ TEST_LR("lslw", "w", MK_SEL(2), 0);
+ TEST_LR("lsll", "", MK_SEL(2), 0);
+
+ TEST_LR("larw", "w", 0xfff8, 0);
+ TEST_LR("larl", "", 0xfff8, 0);
+ TEST_LR("lslw", "w", 0xfff8, 0);
+ TEST_LR("lsll", "", 0xfff8, 0);
+
+ TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1);
+ TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3);
+ TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1);
+}
+
+/* 16 bit code test */
+extern char code16_start, code16_end;
+extern char code16_func1;
+extern char code16_func2;
+extern char code16_func3;
+
+void test_code16(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ int res, res2;
+
+ /* build a code segment */
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&code16_start;
+ ldt.limit = &code16_end - &code16_start;
+ ldt.seg_32bit = 0;
+ ldt.contents = MODIFY_LDT_CONTENTS_CODE;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 0;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ /* call the first function */
+ asm volatile ("lcall %1, %2"
+ : "=a" (res)
+ : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
+ printf("func1() = 0x%08x\n", res);
+ asm volatile ("lcall %2, %3"
+ : "=a" (res), "=c" (res2)
+ : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
+ printf("func2() = 0x%08x spdec=%d\n", res, res2);
+ asm volatile ("lcall %1, %2"
+ : "=a" (res)
+ : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
+ printf("func3() = 0x%08x\n", res);
+}
+#endif
+
+#if defined(__x86_64__)
+asm(".globl func_lret\n"
+ "func_lret:\n"
+ "movl $0x87654641, %eax\n"
+ "lretq\n");
+#else
+asm(".globl func_lret\n"
+ "func_lret:\n"
+ "movl $0x87654321, %eax\n"
+ "lret\n"
+
+ ".globl func_iret\n"
+ "func_iret:\n"
+ "movl $0xabcd4321, %eax\n"
+ "iret\n");
+#endif
+
+extern char func_lret;
+extern char func_iret;
+
+void test_misc(void)
+{
+ char table[256];
+ long res, i;
+
+ for(i=0;i<256;i++) table[i] = 256 - i;
+ res = 0x12345678;
+ asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
+ printf("xlat: EAX=" FMTLX "\n", res);
+
+#if defined(__x86_64__)
+#if 0
+ {
+ /* XXX: see if Intel Core2 and AMD64 behavior really
+ differ. Here we implemented the Intel way which is not
+ compatible yet with QEMU. */
+ static struct QEMU_PACKED {
+ uint64_t offset;
+ uint16_t seg;
+ } desc;
+ long cs_sel;
+
+ asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
+
+ asm volatile ("push %1\n"
+ "call func_lret\n"
+ : "=a" (res)
+ : "r" (cs_sel) : "memory", "cc");
+ printf("func_lret=" FMTLX "\n", res);
+
+ desc.offset = (long)&func_lret;
+ desc.seg = cs_sel;
+
+ asm volatile ("xor %%rax, %%rax\n"
+ "rex64 lcall *(%%rcx)\n"
+ : "=a" (res)
+ : "c" (&desc)
+ : "memory", "cc");
+ printf("func_lret2=" FMTLX "\n", res);
+
+ asm volatile ("push %2\n"
+ "mov $ 1f, %%rax\n"
+ "push %%rax\n"
+ "rex64 ljmp *(%%rcx)\n"
+ "1:\n"
+ : "=a" (res)
+ : "c" (&desc), "b" (cs_sel)
+ : "memory", "cc");
+ printf("func_lret3=" FMTLX "\n", res);
+ }
+#endif
+#else
+ asm volatile ("push %%cs ; call %1"
+ : "=a" (res)
+ : "m" (func_lret): "memory", "cc");
+ printf("func_lret=" FMTLX "\n", res);
+
+ asm volatile ("pushf ; push %%cs ; call %1"
+ : "=a" (res)
+ : "m" (func_iret): "memory", "cc");
+ printf("func_iret=" FMTLX "\n", res);
+#endif
+
+#if defined(__x86_64__)
+ /* specific popl test */
+ asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
+ : "=g" (res));
+ printf("popl esp=" FMTLX "\n", res);
+#else
+ /* specific popl test */
+ asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
+ : "=g" (res));
+ printf("popl esp=" FMTLX "\n", res);
+
+ /* specific popw test */
+ asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
+ : "=g" (res));
+ printf("popw esp=" FMTLX "\n", res);
+#endif
+}
+
+uint8_t str_buffer[4096];
+
+#define TEST_STRING1(OP, size, DF, REP)\
+{\
+ long esi, edi, eax, ecx, eflags;\
+\
+ esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
+ edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
+ eax = i2l(0x12345678);\
+ ecx = 17;\
+\
+ asm volatile ("push $0\n\t"\
+ "popf\n\t"\
+ DF "\n\t"\
+ REP #OP size "\n\t"\
+ "cld\n\t"\
+ "pushf\n\t"\
+ "pop %4\n\t"\
+ : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
+ : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
+ printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
+ REP #OP size, esi, edi, eax, ecx,\
+ (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
+}
+
+#define TEST_STRING(OP, REP)\
+ TEST_STRING1(OP, "b", "", REP);\
+ TEST_STRING1(OP, "w", "", REP);\
+ TEST_STRING1(OP, "l", "", REP);\
+ X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
+ TEST_STRING1(OP, "b", "std", REP);\
+ TEST_STRING1(OP, "w", "std", REP);\
+ TEST_STRING1(OP, "l", "std", REP);\
+ X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
+
+void test_string(void)
+{
+ int i;
+ for(i = 0;i < sizeof(str_buffer); i++)
+ str_buffer[i] = i + 0x56;
+ TEST_STRING(stos, "");
+ TEST_STRING(stos, "rep ");
+ TEST_STRING(lods, ""); /* to verify stos */
+ TEST_STRING(lods, "rep ");
+ TEST_STRING(movs, "");
+ TEST_STRING(movs, "rep ");
+ TEST_STRING(lods, ""); /* to verify stos */
+
+ /* XXX: better tests */
+ TEST_STRING(scas, "");
+ TEST_STRING(scas, "repz ");
+ TEST_STRING(scas, "repnz ");
+ TEST_STRING(cmps, "");
+ TEST_STRING(cmps, "repz ");
+ TEST_STRING(cmps, "repnz ");
+}
+
+#ifdef TEST_VM86
+/* VM86 test */
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+ r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+static inline int vm86(int func, struct vm86plus_struct *v86)
+{
+ return syscall(__NR_vm86, func, v86);
+}
+
+extern char vm86_code_start;
+extern char vm86_code_end;
+
+#define VM86_CODE_CS 0x100
+#define VM86_CODE_IP 0x100
+
+void test_vm86(void)
+{
+ struct vm86plus_struct ctx;
+ struct vm86_regs *r;
+ uint8_t *vm86_mem;
+ int seg, ret;
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ printf("ERROR: could not map vm86 memory");
+ return;
+ }
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* init basic registers */
+ r = &ctx.regs;
+ r->eip = VM86_CODE_IP;
+ r->esp = 0xfffe;
+ seg = VM86_CODE_CS;
+ r->cs = seg;
+ r->ss = seg;
+ r->ds = seg;
+ r->es = seg;
+ r->fs = seg;
+ r->gs = seg;
+ r->eflags = VIF_MASK;
+
+ /* move code to proper address. We use the same layout as a .com
+ dos program. */
+ memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
+ &vm86_code_start, &vm86_code_end - &vm86_code_start);
+
+ /* mark int 0x21 as being emulated */
+ set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+
+ for(;;) {
+ ret = vm86(VM86_ENTER, &ctx);
+ switch(VM86_TYPE(ret)) {
+ case VM86_INTx:
+ {
+ int int_num, ah, v;
+
+ int_num = VM86_ARG(ret);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (r->eax >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ goto the_end;
+ case 0x02: /* write char */
+ {
+ uint8_t c = r->edx;
+ putchar(c);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c, *ptr;
+ ptr = seg_to_linear(r->ds, r->edx);
+ for(;;) {
+ c = *ptr++;
+ if (c == '$')
+ break;
+ putchar(c);
+ }
+ r->eax = (r->eax & ~0xff) | '$';
+ }
+ break;
+ case 0xff: /* extension: write eflags number in edx */
+ v = (int)r->edx;
+#ifndef LINUX_VM86_IOPL_FIX
+ v &= ~0x3000;
+#endif
+ printf("%08x\n", v);
+ break;
+ default:
+ unknown_int:
+ printf("unsupported int 0x%02x\n", int_num);
+ goto the_end;
+ }
+ }
+ break;
+ case VM86_SIGNAL:
+ /* a signal came, we just ignore that */
+ break;
+ case VM86_STI:
+ break;
+ default:
+ printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
+ goto the_end;
+ }
+ }
+ the_end:
+ printf("VM86 end\n");
+ munmap(vm86_mem, 0x110000);
+}
+#endif
+
+/* exception tests */
+#if defined(__i386__) && !defined(REG_EAX)
+#define REG_EAX EAX
+#define REG_EBX EBX
+#define REG_ECX ECX
+#define REG_EDX EDX
+#define REG_ESI ESI
+#define REG_EDI EDI
+#define REG_EBP EBP
+#define REG_ESP ESP
+#define REG_EIP EIP
+#define REG_EFL EFL
+#define REG_TRAPNO TRAPNO
+#define REG_ERR ERR
+#endif
+
+#if defined(__x86_64__)
+#define REG_EIP REG_RIP
+#endif
+
+jmp_buf jmp_env;
+int v1;
+int tab[2];
+
+void sig_handler(int sig, siginfo_t *info, void *puc)
+{
+ struct ucontext *uc = puc;
+
+ printf("si_signo=%d si_errno=%d si_code=%d",
+ info->si_signo, info->si_errno, info->si_code);
+ printf(" si_addr=0x%08lx",
+ (unsigned long)info->si_addr);
+ printf("\n");
+
+ printf("trapno=" FMTLX " err=" FMTLX,
+ (long)uc->uc_mcontext.gregs[REG_TRAPNO],
+ (long)uc->uc_mcontext.gregs[REG_ERR]);
+ printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
+ printf("\n");
+ longjmp(jmp_env, 1);
+}
+
+void test_exceptions(void)
+{
+ struct sigaction act;
+ volatile int val;
+
+ act.sa_sigaction = sig_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGILL, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGTRAP, &act, NULL);
+
+ /* test division by zero reporting */
+ printf("DIVZ exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now divide by zero */
+ v1 = 0;
+ v1 = 2 / v1;
+ }
+
+#if !defined(__x86_64__)
+ printf("BOUND exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* bound exception */
+ tab[0] = 1;
+ tab[1] = 10;
+ asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
+ }
+#endif
+
+#ifdef TEST_SEGS
+ printf("segment exceptions:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* load an invalid segment */
+ asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
+ }
+ if (setjmp(jmp_env) == 0) {
+ /* null data segment is valid */
+ asm volatile ("movl %0, %%fs" : : "r" (3));
+ /* null stack segment */
+ asm volatile ("movl %0, %%ss" : : "r" (3));
+ }
+
+ {
+ struct modify_ldt_ldt_s ldt;
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&seg_data1;
+ ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 1;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ if (setjmp(jmp_env) == 0) {
+ /* segment not present */
+ asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+ }
+ }
+#endif
+
+ /* test SEGV reporting */
+ printf("PF exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ val = 1;
+ /* we add a nop to test a weird PC retrieval case */
+ asm volatile ("nop");
+ /* now store in an invalid address */
+ *(char *)0x1234 = 1;
+ }
+
+ /* test SEGV reporting */
+ printf("PF exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ val = 1;
+ /* read from an invalid address */
+ v1 = *(char *)0x1234;
+ }
+
+ /* test illegal instruction reporting */
+ printf("UD2 exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now execute an invalid instruction */
+ asm volatile("ud2");
+ }
+ printf("lock nop exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now execute an invalid instruction */
+ asm volatile("lock nop");
+ }
+
+ printf("INT exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0xfd");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x01");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile (".byte 0xcd, 0x03");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x04");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x05");
+ }
+
+ printf("INT3 exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int3");
+ }
+
+ printf("CLI exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("cli");
+ }
+
+ printf("STI exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("cli");
+ }
+
+#if !defined(__x86_64__)
+ printf("INTO exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* overflow exception */
+ asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
+ }
+#endif
+
+ printf("OUTB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
+ }
+
+ printf("INB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
+ }
+
+ printf("REP OUTSB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
+ }
+
+ printf("REP INSB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
+ }
+
+ printf("HLT exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("hlt");
+ }
+
+ printf("single step exception:\n");
+ val = 0;
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("pushf\n"
+ "orl $0x00100, (%%esp)\n"
+ "popf\n"
+ "movl $0xabcd, %0\n"
+ "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
+ }
+ printf("val=0x%x\n", val);
+}
+
+#if !defined(__x86_64__)
+/* specific precise single step test */
+void sig_trap_handler(int sig, siginfo_t *info, void *puc)
+{
+ struct ucontext *uc = puc;
+ printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
+}
+
+const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
+uint8_t sstep_buf2[4];
+
+void test_single_step(void)
+{
+ struct sigaction act;
+ volatile int val;
+ int i;
+
+ val = 0;
+ act.sa_sigaction = sig_trap_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ sigaction(SIGTRAP, &act, NULL);
+ asm volatile ("pushf\n"
+ "orl $0x00100, (%%esp)\n"
+ "popf\n"
+ "movl $0xabcd, %0\n"
+
+ /* jmp test */
+ "movl $3, %%ecx\n"
+ "1:\n"
+ "addl $1, %0\n"
+ "decl %%ecx\n"
+ "jnz 1b\n"
+
+ /* movsb: the single step should stop at each movsb iteration */
+ "movl $sstep_buf1, %%esi\n"
+ "movl $sstep_buf2, %%edi\n"
+ "movl $0, %%ecx\n"
+ "rep movsb\n"
+ "movl $3, %%ecx\n"
+ "rep movsb\n"
+ "movl $1, %%ecx\n"
+ "rep movsb\n"
+
+ /* cmpsb: the single step should stop at each cmpsb iteration */
+ "movl $sstep_buf1, %%esi\n"
+ "movl $sstep_buf2, %%edi\n"
+ "movl $0, %%ecx\n"
+ "rep cmpsb\n"
+ "movl $4, %%ecx\n"
+ "rep cmpsb\n"
+
+ /* getpid() syscall: single step should skip one
+ instruction */
+ "movl $20, %%eax\n"
+ "int $0x80\n"
+ "movl $0, %%eax\n"
+
+ /* when modifying SS, trace is not done on the next
+ instruction */
+ "movl %%ss, %%ecx\n"
+ "movl %%ecx, %%ss\n"
+ "addl $1, %0\n"
+ "movl $1, %%eax\n"
+ "movl %%ecx, %%ss\n"
+ "jmp 1f\n"
+ "addl $1, %0\n"
+ "1:\n"
+ "movl $1, %%eax\n"
+ "pushl %%ecx\n"
+ "popl %%ss\n"
+ "addl $1, %0\n"
+ "movl $1, %%eax\n"
+
+ "pushf\n"
+ "andl $~0x00100, (%%esp)\n"
+ "popf\n"
+ : "=m" (val)
+ :
+ : "cc", "memory", "eax", "ecx", "esi", "edi");
+ printf("val=%d\n", val);
+ for(i = 0; i < 4; i++)
+ printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
+}
+
+/* self modifying code test */
+uint8_t code[] = {
+ 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
+ 0xc3, /* ret */
+};
+
+asm(".section \".data\"\n"
+ "smc_code2:\n"
+ "movl 4(%esp), %eax\n"
+ "movl %eax, smc_patch_addr2 + 1\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "smc_patch_addr2:\n"
+ "movl $1, %eax\n"
+ "ret\n"
+ ".previous\n"
+ );
+
+typedef int FuncType(void);
+extern int smc_code2(int);
+void test_self_modifying_code(void)
+{
+ int i;
+ printf("self modifying code:\n");
+ printf("func1 = 0x%x\n", ((FuncType *)code)());
+ for(i = 2; i <= 4; i++) {
+ code[1] = i;
+ printf("func%d = 0x%x\n", i, ((FuncType *)code)());
+ }
+
+ /* more difficult test : the modified code is just after the
+ modifying instruction. It is forbidden in Intel specs, but it
+ is used by old DOS programs */
+ for(i = 2; i <= 4; i++) {
+ printf("smc_code2(%d) = %d\n", i, smc_code2(i));
+ }
+}
+#endif
+
+long enter_stack[4096];
+
+#if defined(__x86_64__)
+#define RSP "%%rsp"
+#define RBP "%%rbp"
+#else
+#define RSP "%%esp"
+#define RBP "%%ebp"
+#endif
+
+#if !defined(__x86_64__)
+/* causes an infinite loop, disable it for now. */
+#define TEST_ENTER(size, stack_type, level)
+#else
+#define TEST_ENTER(size, stack_type, level)\
+{\
+ long esp_save, esp_val, ebp_val, ebp_save, i;\
+ stack_type *ptr, *stack_end, *stack_ptr;\
+ memset(enter_stack, 0, sizeof(enter_stack));\
+ stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
+ ebp_val = (long)stack_ptr;\
+ for(i=1;i<=32;i++)\
+ *--stack_ptr = i;\
+ esp_val = (long)stack_ptr;\
+ asm("mov " RSP ", %[esp_save]\n"\
+ "mov " RBP ", %[ebp_save]\n"\
+ "mov %[esp_val], " RSP "\n"\
+ "mov %[ebp_val], " RBP "\n"\
+ "enter" size " $8, $" #level "\n"\
+ "mov " RSP ", %[esp_val]\n"\
+ "mov " RBP ", %[ebp_val]\n"\
+ "mov %[esp_save], " RSP "\n"\
+ "mov %[ebp_save], " RBP "\n"\
+ : [esp_save] "=r" (esp_save),\
+ [ebp_save] "=r" (ebp_save),\
+ [esp_val] "=r" (esp_val),\
+ [ebp_val] "=r" (ebp_val)\
+ : "[esp_val]" (esp_val),\
+ "[ebp_val]" (ebp_val));\
+ printf("level=%d:\n", level);\
+ printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
+ printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
+ for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
+ printf(FMTLX "\n", (long)ptr[0]);\
+}
+#endif
+
+static void test_enter(void)
+{
+#if defined(__x86_64__)
+ TEST_ENTER("q", uint64_t, 0);
+ TEST_ENTER("q", uint64_t, 1);
+ TEST_ENTER("q", uint64_t, 2);
+ TEST_ENTER("q", uint64_t, 31);
+#else
+ TEST_ENTER("l", uint32_t, 0);
+ TEST_ENTER("l", uint32_t, 1);
+ TEST_ENTER("l", uint32_t, 2);
+ TEST_ENTER("l", uint32_t, 31);
+#endif
+
+ TEST_ENTER("w", uint16_t, 0);
+ TEST_ENTER("w", uint16_t, 1);
+ TEST_ENTER("w", uint16_t, 2);
+ TEST_ENTER("w", uint16_t, 31);
+}
+
+#ifdef TEST_SSE
+
+typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
+typedef float __m128 __attribute__ ((__mode__(__V4SF__)));
+
+typedef union {
+ double d[2];
+ float s[4];
+ uint32_t l[4];
+ uint64_t q[2];
+ __m128 dq;
+} XMMReg;
+
+static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
+ { 0x456723c698694873, 0xdc515cff944a58ec },
+ { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
+ { 0x007c62c2085427f8, 0x231be9e8cde7438d },
+ { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
+};
+
+#define SSE_OP(op)\
+{\
+ asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ b.q[1], b.q[0],\
+ r.q[1], r.q[0]);\
+}
+
+#define SSE_OP2(op)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ b.q[0] = test_values[2*i+1][0];\
+ b.q[1] = test_values[2*i+1][1];\
+ SSE_OP(op);\
+ }\
+}
+
+#define MMX_OP2(op)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ b.q[0] = test_values[2*i+1][0];\
+ asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
+ printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
+ #op,\
+ a.q[0],\
+ b.q[0],\
+ r.q[0]);\
+ }\
+ SSE_OP2(op);\
+}
+
+#define SHUF_OP(op, ib)\
+{\
+ a.q[0] = test_values[0][0];\
+ a.q[1] = test_values[0][1];\
+ b.q[0] = test_values[1][0];\
+ b.q[1] = test_values[1][1];\
+ asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ b.q[1], b.q[0],\
+ ib,\
+ r.q[1], r.q[0]);\
+}
+
+#define PSHUF_OP(op, ib)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ ib,\
+ r.q[1], r.q[0]);\
+ }\
+}
+
+#define SHIFT_IM(op, ib)\
+{\
+ int i;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ ib,\
+ r.q[1], r.q[0]);\
+ }\
+}
+
+#define SHIFT_OP(op, ib)\
+{\
+ int i;\
+ SHIFT_IM(op, ib);\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ b.q[0] = ib;\
+ b.q[1] = 0;\
+ asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ b.q[1], b.q[0],\
+ r.q[1], r.q[0]);\
+ }\
+}
+
+#define MOVMSK(op)\
+{\
+ int i, reg;\
+ for(i=0;i<2;i++) {\
+ a.q[0] = test_values[2*i][0];\
+ a.q[1] = test_values[2*i][1];\
+ asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ reg);\
+ }\
+}
+
+#define SSE_OPS(a) \
+SSE_OP(a ## ps);\
+SSE_OP(a ## ss);
+
+#define SSE_OPD(a) \
+SSE_OP(a ## pd);\
+SSE_OP(a ## sd);
+
+#define SSE_COMI(op, field)\
+{\
+ unsigned int eflags;\
+ XMMReg a, b;\
+ a.field[0] = a1;\
+ b.field[0] = b1;\
+ asm volatile (#op " %2, %1\n"\
+ "pushf\n"\
+ "pop %0\n"\
+ : "=m" (eflags)\
+ : "x" (a.dq), "x" (b.dq));\
+ printf("%-9s: a=%f b=%f cc=%04x\n",\
+ #op, a1, b1,\
+ eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
+}
+
+void test_sse_comi(double a1, double b1)
+{
+ SSE_COMI(ucomiss, s);
+ SSE_COMI(ucomisd, d);
+ SSE_COMI(comiss, s);
+ SSE_COMI(comisd, d);
+}
+
+#define CVT_OP_XMM(op)\
+{\
+ asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ r.q[1], r.q[0]);\
+}
+
+/* Force %xmm0 usage to avoid the case where both register index are 0
+ to test instruction decoding more extensively */
+#define CVT_OP_XMM2MMX(op)\
+{\
+ asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
+ : "%xmm0"); \
+ asm volatile("emms\n"); \
+ printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ r.q[0]);\
+}
+
+#define CVT_OP_MMX2XMM(op)\
+{\
+ asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
+ asm volatile("emms\n"); \
+ printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.q[0],\
+ r.q[1], r.q[0]);\
+}
+
+#define CVT_OP_REG2XMM(op)\
+{\
+ asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
+ printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
+ #op,\
+ a.l[0],\
+ r.q[1], r.q[0]);\
+}
+
+#define CVT_OP_XMM2REG(op)\
+{\
+ asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
+ printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
+ #op,\
+ a.q[1], a.q[0],\
+ r.l[0]);\
+}
+
+struct fpxstate {
+ uint16_t fpuc;
+ uint16_t fpus;
+ uint16_t fptag;
+ uint16_t fop;
+ uint32_t fpuip;
+ uint16_t cs_sel;
+ uint16_t dummy0;
+ uint32_t fpudp;
+ uint16_t ds_sel;
+ uint16_t dummy1;
+ uint32_t mxcsr;
+ uint32_t mxcsr_mask;
+ uint8_t fpregs1[8 * 16];
+ uint8_t xmm_regs[8 * 16];
+ uint8_t dummy2[224];
+};
+
+static struct fpxstate fpx_state __attribute__((aligned(16)));
+static struct fpxstate fpx_state2 __attribute__((aligned(16)));
+
+void test_fxsave(void)
+{
+ struct fpxstate *fp = &fpx_state;
+ struct fpxstate *fp2 = &fpx_state2;
+ int i, nb_xmm;
+ XMMReg a, b;
+ a.q[0] = test_values[0][0];
+ a.q[1] = test_values[0][1];
+ b.q[0] = test_values[1][0];
+ b.q[1] = test_values[1][1];
+
+ asm("movdqa %2, %%xmm0\n"
+ "movdqa %3, %%xmm7\n"
+#if defined(__x86_64__)
+ "movdqa %2, %%xmm15\n"
+#endif
+ " fld1\n"
+ " fldpi\n"
+ " fldln2\n"
+ " fxsave %0\n"
+ " fxrstor %0\n"
+ " fxsave %1\n"
+ " fninit\n"
+ : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
+ : "m" (a), "m" (b));
+ printf("fpuc=%04x\n", fp->fpuc);
+ printf("fpus=%04x\n", fp->fpus);
+ printf("fptag=%04x\n", fp->fptag);
+ for(i = 0; i < 3; i++) {
+ printf("ST%d: " FMT64X " %04x\n",
+ i,
+ *(uint64_t *)&fp->fpregs1[i * 16],
+ *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
+ }
+ printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
+#if defined(__x86_64__)
+ nb_xmm = 16;
+#else
+ nb_xmm = 8;
+#endif
+ for(i = 0; i < nb_xmm; i++) {
+ printf("xmm%d: " FMT64X "" FMT64X "\n",
+ i,
+ *(uint64_t *)&fp->xmm_regs[i * 16],
+ *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
+ }
+}
+
+void test_sse(void)
+{
+ XMMReg r, a, b;
+ int i;
+
+ MMX_OP2(punpcklbw);
+ MMX_OP2(punpcklwd);
+ MMX_OP2(punpckldq);
+ MMX_OP2(packsswb);
+ MMX_OP2(pcmpgtb);
+ MMX_OP2(pcmpgtw);
+ MMX_OP2(pcmpgtd);
+ MMX_OP2(packuswb);
+ MMX_OP2(punpckhbw);
+ MMX_OP2(punpckhwd);
+ MMX_OP2(punpckhdq);
+ MMX_OP2(packssdw);
+ MMX_OP2(pcmpeqb);
+ MMX_OP2(pcmpeqw);
+ MMX_OP2(pcmpeqd);
+
+ MMX_OP2(paddq);
+ MMX_OP2(pmullw);
+ MMX_OP2(psubusb);
+ MMX_OP2(psubusw);
+ MMX_OP2(pminub);
+ MMX_OP2(pand);
+ MMX_OP2(paddusb);
+ MMX_OP2(paddusw);
+ MMX_OP2(pmaxub);
+ MMX_OP2(pandn);
+
+ MMX_OP2(pmulhuw);
+ MMX_OP2(pmulhw);
+
+ MMX_OP2(psubsb);
+ MMX_OP2(psubsw);
+ MMX_OP2(pminsw);
+ MMX_OP2(por);
+ MMX_OP2(paddsb);
+ MMX_OP2(paddsw);
+ MMX_OP2(pmaxsw);
+ MMX_OP2(pxor);
+ MMX_OP2(pmuludq);
+ MMX_OP2(pmaddwd);
+ MMX_OP2(psadbw);
+ MMX_OP2(psubb);
+ MMX_OP2(psubw);
+ MMX_OP2(psubd);
+ MMX_OP2(psubq);
+ MMX_OP2(paddb);
+ MMX_OP2(paddw);
+ MMX_OP2(paddd);
+
+ MMX_OP2(pavgb);
+ MMX_OP2(pavgw);
+
+ asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
+ printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
+
+ asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
+ printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
+
+ a.q[0] = test_values[0][0];
+ a.q[1] = test_values[0][1];
+ asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
+ printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
+
+ asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
+ printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
+
+ asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
+ printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
+
+ asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
+ printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
+
+ {
+ r.q[0] = -1;
+ r.q[1] = -1;
+
+ a.q[0] = test_values[0][0];
+ a.q[1] = test_values[0][1];
+ b.q[0] = test_values[1][0];
+ b.q[1] = test_values[1][1];
+ asm volatile("maskmovq %1, %0" :
+ : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
+ : "memory");
+ printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
+ "maskmov",
+ r.q[0],
+ a.q[0],
+ b.q[0]);
+ asm volatile("maskmovdqu %1, %0" :
+ : "x" (a.dq), "x" (b.dq), "D" (&r)
+ : "memory");
+ printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
+ "maskmov",
+ r.q[1], r.q[0],
+ a.q[1], a.q[0],
+ b.q[1], b.q[0]);
+ }
+
+ asm volatile ("emms");
+
+ SSE_OP2(punpcklqdq);
+ SSE_OP2(punpckhqdq);
+ SSE_OP2(andps);
+ SSE_OP2(andpd);
+ SSE_OP2(andnps);
+ SSE_OP2(andnpd);
+ SSE_OP2(orps);
+ SSE_OP2(orpd);
+ SSE_OP2(xorps);
+ SSE_OP2(xorpd);
+
+ SSE_OP2(unpcklps);
+ SSE_OP2(unpcklpd);
+ SSE_OP2(unpckhps);
+ SSE_OP2(unpckhpd);
+
+ SHUF_OP(shufps, 0x78);
+ SHUF_OP(shufpd, 0x02);
+
+ PSHUF_OP(pshufd, 0x78);
+ PSHUF_OP(pshuflw, 0x78);
+ PSHUF_OP(pshufhw, 0x78);
+
+ SHIFT_OP(psrlw, 7);
+ SHIFT_OP(psrlw, 16);
+ SHIFT_OP(psraw, 7);
+ SHIFT_OP(psraw, 16);
+ SHIFT_OP(psllw, 7);
+ SHIFT_OP(psllw, 16);
+
+ SHIFT_OP(psrld, 7);
+ SHIFT_OP(psrld, 32);
+ SHIFT_OP(psrad, 7);
+ SHIFT_OP(psrad, 32);
+ SHIFT_OP(pslld, 7);
+ SHIFT_OP(pslld, 32);
+
+ SHIFT_OP(psrlq, 7);
+ SHIFT_OP(psrlq, 32);
+ SHIFT_OP(psllq, 7);
+ SHIFT_OP(psllq, 32);
+
+ SHIFT_IM(psrldq, 16);
+ SHIFT_IM(psrldq, 7);
+ SHIFT_IM(pslldq, 16);
+ SHIFT_IM(pslldq, 7);
+
+ MOVMSK(movmskps);
+ MOVMSK(movmskpd);
+
+ /* FPU specific ops */
+
+ {
+ uint32_t mxcsr;
+ asm volatile("stmxcsr %0" : "=m" (mxcsr));
+ printf("mxcsr=%08x\n", mxcsr & 0x1f80);
+ asm volatile("ldmxcsr %0" : : "m" (mxcsr));
+ }
+
+ test_sse_comi(2, -1);
+ test_sse_comi(2, 2);
+ test_sse_comi(2, 3);
+ test_sse_comi(2, q_nan.d);
+ test_sse_comi(q_nan.d, -1);
+
+ for(i = 0; i < 2; i++) {
+ a.s[0] = 2.7;
+ a.s[1] = 3.4;
+ a.s[2] = 4;
+ a.s[3] = -6.3;
+ b.s[0] = 45.7;
+ b.s[1] = 353.4;
+ b.s[2] = 4;
+ b.s[3] = 56.3;
+ if (i == 1) {
+ a.s[0] = q_nan.d;
+ b.s[3] = q_nan.d;
+ }
+
+ SSE_OPS(add);
+ SSE_OPS(mul);
+ SSE_OPS(sub);
+ SSE_OPS(min);
+ SSE_OPS(div);
+ SSE_OPS(max);
+ SSE_OPS(sqrt);
+ SSE_OPS(cmpeq);
+ SSE_OPS(cmplt);
+ SSE_OPS(cmple);
+ SSE_OPS(cmpunord);
+ SSE_OPS(cmpneq);
+ SSE_OPS(cmpnlt);
+ SSE_OPS(cmpnle);
+ SSE_OPS(cmpord);
+
+
+ a.d[0] = 2.7;
+ a.d[1] = -3.4;
+ b.d[0] = 45.7;
+ b.d[1] = -53.4;
+ if (i == 1) {
+ a.d[0] = q_nan.d;
+ b.d[1] = q_nan.d;
+ }
+ SSE_OPD(add);
+ SSE_OPD(mul);
+ SSE_OPD(sub);
+ SSE_OPD(min);
+ SSE_OPD(div);
+ SSE_OPD(max);
+ SSE_OPD(sqrt);
+ SSE_OPD(cmpeq);
+ SSE_OPD(cmplt);
+ SSE_OPD(cmple);
+ SSE_OPD(cmpunord);
+ SSE_OPD(cmpneq);
+ SSE_OPD(cmpnlt);
+ SSE_OPD(cmpnle);
+ SSE_OPD(cmpord);
+ }
+
+ /* float to float/int */
+ a.s[0] = 2.7;
+ a.s[1] = 3.4;
+ a.s[2] = 4;
+ a.s[3] = -6.3;
+ CVT_OP_XMM(cvtps2pd);
+ CVT_OP_XMM(cvtss2sd);
+ CVT_OP_XMM2MMX(cvtps2pi);
+ CVT_OP_XMM2MMX(cvttps2pi);
+ CVT_OP_XMM2REG(cvtss2si);
+ CVT_OP_XMM2REG(cvttss2si);
+ CVT_OP_XMM(cvtps2dq);
+ CVT_OP_XMM(cvttps2dq);
+
+ a.d[0] = 2.6;
+ a.d[1] = -3.4;
+ CVT_OP_XMM(cvtpd2ps);
+ CVT_OP_XMM(cvtsd2ss);
+ CVT_OP_XMM2MMX(cvtpd2pi);
+ CVT_OP_XMM2MMX(cvttpd2pi);
+ CVT_OP_XMM2REG(cvtsd2si);
+ CVT_OP_XMM2REG(cvttsd2si);
+ CVT_OP_XMM(cvtpd2dq);
+ CVT_OP_XMM(cvttpd2dq);
+
+ /* sse/mmx moves */
+ CVT_OP_XMM2MMX(movdq2q);
+ CVT_OP_MMX2XMM(movq2dq);
+
+ /* int to float */
+ a.l[0] = -6;
+ a.l[1] = 2;
+ a.l[2] = 100;
+ a.l[3] = -60000;
+ CVT_OP_MMX2XMM(cvtpi2ps);
+ CVT_OP_MMX2XMM(cvtpi2pd);
+ CVT_OP_REG2XMM(cvtsi2ss);
+ CVT_OP_REG2XMM(cvtsi2sd);
+ CVT_OP_XMM(cvtdq2ps);
+ CVT_OP_XMM(cvtdq2pd);
+
+ /* XXX: test PNI insns */
+#if 0
+ SSE_OP2(movshdup);
+#endif
+ asm volatile ("emms");
+}
+
+#endif
+
+#define TEST_CONV_RAX(op)\
+{\
+ unsigned long a, r;\
+ a = i2l(0x8234a6f8);\
+ r = a;\
+ asm volatile(#op : "=a" (r) : "0" (r));\
+ printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
+}
+
+#define TEST_CONV_RAX_RDX(op)\
+{\
+ unsigned long a, d, r, rh; \
+ a = i2l(0x8234a6f8);\
+ d = i2l(0x8345a1f2);\
+ r = a;\
+ rh = d;\
+ asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh)); \
+ printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh); \
+}
+
+void test_conv(void)
+{
+ TEST_CONV_RAX(cbw);
+ TEST_CONV_RAX(cwde);
+#if defined(__x86_64__)
+ TEST_CONV_RAX(cdqe);
+#endif
+
+ TEST_CONV_RAX_RDX(cwd);
+ TEST_CONV_RAX_RDX(cdq);
+#if defined(__x86_64__)
+ TEST_CONV_RAX_RDX(cqo);
+#endif
+
+ {
+ unsigned long a, r;
+ a = i2l(0x12345678);
+ asm volatile("bswapl %k0" : "=r" (r) : "0" (a));
+ printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r);
+ }
+#if defined(__x86_64__)
+ {
+ unsigned long a, r;
+ a = i2l(0x12345678);
+ asm volatile("bswapq %0" : "=r" (r) : "0" (a));
+ printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r);
+ }
+#endif
+}
+
+extern void *__start_initcall;
+extern void *__stop_initcall;
+
+
+int main(int argc, char **argv)
+{
+ void **ptr;
+ void (*func)(void);
+
+ ptr = &__start_initcall;
+ while (ptr != &__stop_initcall) {
+ func = *ptr++;
+ func();
+ }
+ test_bsx();
+ test_mul();
+ test_jcc();
+ test_loop();
+ test_floats();
+#if !defined(__x86_64__)
+ test_bcd();
+#endif
+ test_xchg();
+ test_string();
+ test_misc();
+ test_lea();
+#ifdef TEST_SEGS
+ test_segs();
+ test_code16();
+#endif
+#ifdef TEST_VM86
+ test_vm86();
+#endif
+#if !defined(__x86_64__)
+ test_exceptions();
+ test_self_modifying_code();
+ test_single_step();
+#endif
+ test_enter();
+ test_conv();
+#ifdef TEST_SSE
+ test_sse();
+ test_fxsave();
+#endif
+ return 0;
+}
diff --git a/tests/tcg/test-i386.h b/tests/tcg/test-i386.h
new file mode 100644
index 0000000000..75106b8ce2
--- /dev/null
+++ b/tests/tcg/test-i386.h
@@ -0,0 +1,152 @@
+
+#define exec_op glue(exec_, OP)
+#define exec_opq glue(glue(exec_, OP), q)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#define EXECOP2(size, rsize, res, s1, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "q" (s1), "0" (res), "1" (flags)); \
+ printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
+ stringify(OP) size, s0, s1, res, iflags, flags & CC_MASK);
+
+#define EXECOP1(size, rsize, res, flags) \
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" rsize "0\n\t" \
+ "pushf\n\t"\
+ "pop %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "0" (res), "1" (flags)); \
+ printf("%-10s A=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
+ stringify(OP) size, s0, res, iflags, flags & CC_MASK);
+
+#ifdef OP1
+#if defined(__x86_64__)
+void exec_opq(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("q", "", res, flags);
+}
+#endif
+
+void exec_opl(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("l", "k", res, flags);
+}
+
+void exec_opw(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("w", "w", res, flags);
+}
+
+void exec_opb(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("b", "b", res, flags);
+}
+#else
+#if defined(__x86_64__)
+void exec_opq(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("q", "", res, s1, flags);
+}
+#endif
+
+void exec_opl(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("l", "k", res, s1, flags);
+}
+
+void exec_opw(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("w", "w", res, s1, flags);
+}
+
+void exec_opb(long s0, long s1, long iflags)
+{
+ long res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("b", "b", res, s1, flags);
+}
+#endif
+
+void exec_op(long s0, long s1)
+{
+ s0 = i2l(s0);
+ s1 = i2l(s1);
+#if defined(__x86_64__)
+ exec_opq(s0, s1, 0);
+#endif
+ exec_opl(s0, s1, 0);
+ exec_opw(s0, s1, 0);
+ exec_opb(s0, s1, 0);
+#ifdef OP_CC
+#if defined(__x86_64__)
+ exec_opq(s0, s1, CC_C);
+#endif
+ exec_opl(s0, s1, CC_C);
+ exec_opw(s0, s1, CC_C);
+ exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+ exec_op(0x12345678, 0x812FADA);
+ exec_op(0x12341, 0x12341);
+ exec_op(0x12341, -0x12341);
+ exec_op(0xffffffff, 0);
+ exec_op(0xffffffff, -1);
+ exec_op(0xffffffff, 1);
+ exec_op(0xffffffff, 2);
+ exec_op(0x7fffffff, 0);
+ exec_op(0x7fffffff, 1);
+ exec_op(0x7fffffff, -1);
+ exec_op(0x80000000, -1);
+ exec_op(0x80000000, 1);
+ exec_op(0x80000000, -2);
+ exec_op(0x12347fff, 0);
+ exec_op(0x12347fff, 1);
+ exec_op(0x12347fff, -1);
+ exec_op(0x12348000, -1);
+ exec_op(0x12348000, 1);
+ exec_op(0x12348000, -2);
+ exec_op(0x12347f7f, 0);
+ exec_op(0x12347f7f, 1);
+ exec_op(0x12347f7f, -1);
+ exec_op(0x12348080, -1);
+ exec_op(0x12348080, 1);
+ exec_op(0x12348080, -2);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
diff --git a/tests/tcg/test-mmap.c b/tests/tcg/test-mmap.c
new file mode 100644
index 0000000000..c67174a260
--- /dev/null
+++ b/tests/tcg/test-mmap.c
@@ -0,0 +1,476 @@
+/*
+ * Small test program to verify simulated mmap behaviour.
+ *
+ * When running qemu-linux-user with the -p flag, you may need to tell
+ * this test program about the pagesize because getpagesize() will not reflect
+ * the -p choice. Simply pass one argument beeing the pagesize.
+ *
+ * Copyright (c) 2007 AXIS Communications AB
+ * Written by Edgar E. Iglesias.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#define D(x)
+
+#define fail_unless(x) \
+do \
+{ \
+ if (!(x)) { \
+ fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
+ exit (EXIT_FAILURE); \
+ } \
+} while (0);
+
+unsigned char *dummybuf;
+static unsigned int pagesize;
+static unsigned int pagemask;
+int test_fd;
+size_t test_fsize;
+
+void check_aligned_anonymous_unfixed_mmaps(void)
+{
+ void *p1;
+ void *p2;
+ void *p3;
+ void *p4;
+ void *p5;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x1fff; i++)
+ {
+ size_t len;
+
+ len = pagesize + (pagesize * i & 7);
+ p1 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p2 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p3 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p4 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ p5 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ fail_unless (p1 != MAP_FAILED);
+ fail_unless (p2 != MAP_FAILED);
+ fail_unless (p3 != MAP_FAILED);
+ fail_unless (p4 != MAP_FAILED);
+ fail_unless (p5 != MAP_FAILED);
+ p = (uintptr_t) p1;
+ D(printf ("p=%x\n", p));
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p2;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p3;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p4;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p5;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Make sure we can read from the entire area. */
+ memcpy (dummybuf, p1, pagesize);
+ memcpy (dummybuf, p2, pagesize);
+ memcpy (dummybuf, p3, pagesize);
+ memcpy (dummybuf, p4, pagesize);
+ memcpy (dummybuf, p5, pagesize);
+
+ munmap (p1, len);
+ munmap (p2, len);
+ munmap (p3, len);
+ munmap (p4, len);
+ munmap (p5, len);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_large_anonymous_unfixed_mmap(void)
+{
+ void *p1;
+ uintptr_t p;
+ size_t len;
+
+ fprintf (stderr, "%s", __func__);
+
+ len = 0x02000000;
+ p1 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ fail_unless (p1 != MAP_FAILED);
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Make sure we can read from the entire area. */
+ memcpy (dummybuf, p1, pagesize);
+ munmap (p1, len);
+ fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_unfixed_colliding_mmaps(void)
+{
+ char *p1;
+ char *p2;
+ char *p3;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x2fff; i++)
+ {
+ int nlen;
+ p1 = mmap(NULL, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p1 != MAP_FAILED);
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+ memcpy (dummybuf, p1, pagesize);
+
+ p2 = mmap(NULL, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p2 != MAP_FAILED);
+ p = (uintptr_t) p2;
+ fail_unless ((p & pagemask) == 0);
+ memcpy (dummybuf, p2, pagesize);
+
+
+ munmap (p1, pagesize);
+ nlen = pagesize * 8;
+ p3 = mmap(NULL, nlen, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ fail_unless (p3 != MAP_FAILED);
+
+ /* Check if the mmaped areas collide. */
+ if (p3 < p2
+ && (p3 + nlen) > p2)
+ fail_unless (0);
+
+ memcpy (dummybuf, p3, pagesize);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p3;
+ fail_unless ((p & pagemask) == 0);
+ munmap (p2, pagesize);
+ munmap (p3, nlen);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_fixed_mmaps(void)
+{
+ char *addr;
+ void *p1;
+ uintptr_t p;
+ int i;
+
+ /* Find a suitable address to start with. */
+ addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ fprintf (stderr, "%s addr=%p", __func__, addr);
+ fail_unless (addr != MAP_FAILED);
+
+ for (i = 0; i < 40; i++)
+ {
+ /* Create submaps within our unfixed map. */
+ p1 = mmap(addr, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ -1, 0);
+ /* Make sure we get pages aligned with the pagesize.
+ The target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless (p1 == addr);
+ fail_unless ((p & pagemask) == 0);
+ memcpy (dummybuf, p1, pagesize);
+ munmap (p1, pagesize);
+ addr += pagesize;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
+{
+ char *addr;
+ void *p1;
+ uintptr_t p;
+ int i;
+
+ /* Find a suitable address to start with. Right were the x86 hosts
+ stack is. */
+ addr = ((void *)0x80000000);
+ fprintf (stderr, "%s addr=%p", __func__, addr);
+ fprintf (stderr, "FIXME: QEMU fails to track pages used by the host.");
+
+ for (i = 0; i < 20; i++)
+ {
+ /* Create submaps within our unfixed map. */
+ p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ -1, 0);
+ /* Make sure we get pages aligned with the pagesize.
+ The target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless (p1 == addr);
+ fail_unless ((p & pagemask) == 0);
+ memcpy (p1, dummybuf, pagesize);
+ munmap (p1, pagesize);
+ addr += pagesize;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_unfixed_mmaps(void)
+{
+ unsigned int *p1, *p2, *p3;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x10; i++)
+ {
+ size_t len;
+
+ len = pagesize;
+ p1 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE,
+ test_fd, 0);
+ p2 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE,
+ test_fd, pagesize);
+ p3 = mmap(NULL, len, PROT_READ,
+ MAP_PRIVATE,
+ test_fd, pagesize * 2);
+
+ fail_unless (p1 != MAP_FAILED);
+ fail_unless (p2 != MAP_FAILED);
+ fail_unless (p3 != MAP_FAILED);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p2;
+ fail_unless ((p & pagemask) == 0);
+ p = (uintptr_t) p3;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Verify that the file maps was made correctly. */
+ D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
+ fail_unless (*p1 == 0);
+ fail_unless (*p2 == (pagesize / sizeof *p2));
+ fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
+
+ memcpy (dummybuf, p1, pagesize);
+ memcpy (dummybuf, p2, pagesize);
+ memcpy (dummybuf, p3, pagesize);
+ munmap (p1, len);
+ munmap (p2, len);
+ munmap (p3, len);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_unfixed_eof_mmaps(void)
+{
+ char *cp;
+ unsigned int *p1;
+ uintptr_t p;
+ int i;
+
+ fprintf (stderr, "%s", __func__);
+ for (i = 0; i < 0x10; i++)
+ {
+ p1 = mmap(NULL, pagesize, PROT_READ,
+ MAP_PRIVATE,
+ test_fd,
+ (test_fsize - sizeof *p1) & ~pagemask);
+
+ fail_unless (p1 != MAP_FAILED);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+ /* Verify that the file maps was made correctly. */
+ fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
+ == ((test_fsize - sizeof *p1) / sizeof *p1));
+
+ /* Verify that the end of page is accessible and zeroed. */
+ cp = (void *) p1;
+ fail_unless (cp[pagesize - 4] == 0);
+ munmap (p1, pagesize);
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_fixed_eof_mmaps(void)
+{
+ char *addr;
+ char *cp;
+ unsigned int *p1;
+ uintptr_t p;
+ int i;
+
+ /* Find a suitable address to start with. */
+ addr = mmap(NULL, pagesize * 44, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+
+ fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
+ fail_unless (addr != MAP_FAILED);
+
+ for (i = 0; i < 0x10; i++)
+ {
+ /* Create submaps within our unfixed map. */
+ p1 = mmap(addr, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd,
+ (test_fsize - sizeof *p1) & ~pagemask);
+
+ fail_unless (p1 != MAP_FAILED);
+
+ /* Make sure we get pages aligned with the pagesize. The
+ target expects this. */
+ p = (uintptr_t) p1;
+ fail_unless ((p & pagemask) == 0);
+
+ /* Verify that the file maps was made correctly. */
+ fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
+ == ((test_fsize - sizeof *p1) / sizeof *p1));
+
+ /* Verify that the end of page is accessible and zeroed. */
+ cp = (void *)p1;
+ fail_unless (cp[pagesize - 4] == 0);
+ munmap (p1, pagesize);
+ addr += pagesize;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+void check_file_fixed_mmaps(void)
+{
+ unsigned char *addr;
+ unsigned int *p1, *p2, *p3, *p4;
+ int i;
+
+ /* Find a suitable address to start with. */
+ addr = mmap(NULL, pagesize * 40 * 4, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
+ fail_unless (addr != MAP_FAILED);
+
+ for (i = 0; i < 40; i++)
+ {
+ p1 = mmap(addr, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, 0);
+ p2 = mmap(addr + pagesize, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, pagesize);
+ p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, pagesize * 2);
+ p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ,
+ MAP_PRIVATE | MAP_FIXED,
+ test_fd, pagesize * 3);
+
+ /* Make sure we get pages aligned with the pagesize.
+ The target expects this. */
+ fail_unless (p1 == (void *)addr);
+ fail_unless (p2 == (void *)addr + pagesize);
+ fail_unless (p3 == (void *)addr + pagesize * 2);
+ fail_unless (p4 == (void *)addr + pagesize * 3);
+
+ /* Verify that the file maps was made correctly. */
+ fail_unless (*p1 == 0);
+ fail_unless (*p2 == (pagesize / sizeof *p2));
+ fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
+ fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
+
+ memcpy (dummybuf, p1, pagesize);
+ memcpy (dummybuf, p2, pagesize);
+ memcpy (dummybuf, p3, pagesize);
+ memcpy (dummybuf, p4, pagesize);
+
+ munmap (p1, pagesize);
+ munmap (p2, pagesize);
+ munmap (p3, pagesize);
+ munmap (p4, pagesize);
+ addr += pagesize * 4;
+ }
+ fprintf (stderr, " passed\n");
+}
+
+int main(int argc, char **argv)
+{
+ char tempname[] = "/tmp/.cmmapXXXXXX";
+ unsigned int i;
+
+ /* Trust the first argument, otherwise probe the system for our
+ pagesize. */
+ if (argc > 1)
+ pagesize = strtoul(argv[1], NULL, 0);
+ else
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ /* Assume pagesize is a power of two. */
+ pagemask = pagesize - 1;
+ dummybuf = malloc (pagesize);
+ printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
+
+ test_fd = mkstemp(tempname);
+ unlink(tempname);
+
+ /* Fill the file with int's counting from zero and up. */
+ for (i = 0; i < (pagesize * 4) / sizeof i; i++)
+ write (test_fd, &i, sizeof i);
+ /* Append a few extra writes to make the file end at non
+ page boundary. */
+ write (test_fd, &i, sizeof i); i++;
+ write (test_fd, &i, sizeof i); i++;
+ write (test_fd, &i, sizeof i); i++;
+
+ test_fsize = lseek(test_fd, 0, SEEK_CUR);
+
+ /* Run the tests. */
+ check_aligned_anonymous_unfixed_mmaps();
+ check_aligned_anonymous_unfixed_colliding_mmaps();
+ check_aligned_anonymous_fixed_mmaps();
+ check_file_unfixed_mmaps();
+ check_file_fixed_mmaps();
+ check_file_fixed_eof_mmaps();
+ check_file_unfixed_eof_mmaps();
+
+ /* Fails at the moment. */
+ /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/test_path.c b/tests/tcg/test_path.c
new file mode 100644
index 0000000000..7265a9445d
--- /dev/null
+++ b/tests/tcg/test_path.c
@@ -0,0 +1,160 @@
+/* Test path override code */
+#include "../config-host.h"
+#include "../qemu-malloc.c"
+#include "../cutils.c"
+#include "../path.c"
+#include "../trace.c"
+#ifdef CONFIG_TRACE_SIMPLE
+#include "../simpletrace.c"
+#endif
+
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void qemu_log(const char *fmt, ...);
+
+/* Any log message kills the test. */
+void qemu_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "FATAL: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+#define NO_CHANGE(_path) \
+ do { \
+ if (strcmp(path(_path), _path) != 0) return __LINE__; \
+ } while(0)
+
+#define CHANGE_TO(_path, _newpath) \
+ do { \
+ if (strcmp(path(_path), _newpath) != 0) return __LINE__; \
+ } while(0)
+
+static void cleanup(void)
+{
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+ rmdir("/tmp/qemu-test_path/DIR1/DIR2");
+ rmdir("/tmp/qemu-test_path/DIR1/DIR3");
+ rmdir("/tmp/qemu-test_path/DIR1");
+ rmdir("/tmp/qemu-test_path");
+}
+
+static unsigned int do_test(void)
+{
+ if (mkdir("/tmp/qemu-test_path", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1/DIR2", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1/DIR3", 0700) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE2", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE3", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE4", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0)
+ return __LINE__;
+
+ init_paths("/tmp/qemu-test_path");
+
+ NO_CHANGE("/tmp");
+ NO_CHANGE("/tmp/");
+ NO_CHANGE("/tmp/qemu-test_path");
+ NO_CHANGE("/tmp/qemu-test_path/");
+ NO_CHANGE("/tmp/qemu-test_path/D");
+ NO_CHANGE("/tmp/qemu-test_path/DI");
+ NO_CHANGE("/tmp/qemu-test_path/DIR");
+ NO_CHANGE("/tmp/qemu-test_path/DIR1");
+ NO_CHANGE("/tmp/qemu-test_path/DIR1/");
+
+ NO_CHANGE("/D");
+ NO_CHANGE("/DI");
+ NO_CHANGE("/DIR");
+ NO_CHANGE("/DIR2");
+ NO_CHANGE("/DIR1.");
+
+ CHANGE_TO("/DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/", "/tmp/qemu-test_path/DIR1");
+
+ NO_CHANGE("/DIR1/D");
+ NO_CHANGE("/DIR1/DI");
+ NO_CHANGE("/DIR1/DIR");
+ NO_CHANGE("/DIR1/DIR1");
+
+ CHANGE_TO("/DIR1/DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+ CHANGE_TO("/DIR1/DIR2/", "/tmp/qemu-test_path/DIR1/DIR2");
+
+ CHANGE_TO("/DIR1/DIR3", "/tmp/qemu-test_path/DIR1/DIR3");
+ CHANGE_TO("/DIR1/DIR3/", "/tmp/qemu-test_path/DIR1/DIR3");
+
+ NO_CHANGE("/DIR1/DIR2/F");
+ NO_CHANGE("/DIR1/DIR2/FI");
+ NO_CHANGE("/DIR1/DIR2/FIL");
+ NO_CHANGE("/DIR1/DIR2/FIL.");
+
+ CHANGE_TO("/DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/FILE2", "/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+ CHANGE_TO("/DIR1/DIR2/FILE3", "/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+ CHANGE_TO("/DIR1/DIR2/FILE4", "/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+ CHANGE_TO("/DIR1/DIR2/FILE5", "/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+
+ NO_CHANGE("/DIR1/DIR2/FILE6");
+ NO_CHANGE("/DIR1/DIR2/FILE/X");
+
+ CHANGE_TO("/DIR1/../DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/../DIR1/", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/../DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/../DIR1/", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/DIR2/../DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+ CHANGE_TO("/DIR1/DIR2/../DIR2/../../DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/../DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+ NO_CHANGE("/DIR1/DIR2/../DIR1");
+ NO_CHANGE("/DIR1/DIR2/../FILE");
+
+ CHANGE_TO("/./DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/././DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/./DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/././DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/././FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/./DIR1/./DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ ret = do_test();
+ cleanup();
+ if (ret) {
+ fprintf(stderr, "test_path: failed on line %i\n", ret);
+ return 1;
+ }
+ return 0;
+}
diff --git a/tests/tcg/testthread.c b/tests/tcg/testthread.c
new file mode 100644
index 0000000000..27e4825bc6
--- /dev/null
+++ b/tests/tcg/testthread.c
@@ -0,0 +1,51 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <sys/wait.h>
+#include <sched.h>
+
+void *thread1_func(void *arg)
+{
+ int i;
+ char buf[512];
+
+ for(i=0;i<10;i++) {
+ snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg);
+ write(1, buf, strlen(buf));
+ usleep(100 * 1000);
+ }
+ return NULL;
+}
+
+void *thread2_func(void *arg)
+{
+ int i;
+ char buf[512];
+ for(i=0;i<20;i++) {
+ snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg);
+ write(1, buf, strlen(buf));
+ usleep(150 * 1000);
+ }
+ return NULL;
+}
+
+void test_pthread(void)
+{
+ pthread_t tid1, tid2;
+
+ pthread_create(&tid1, NULL, thread1_func, "hello1");
+ pthread_create(&tid2, NULL, thread2_func, "hello2");
+ pthread_join(tid1, NULL);
+ pthread_join(tid2, NULL);
+ printf("End of pthread test.\n");
+}
+
+int main(int argc, char **argv)
+{
+ test_pthread();
+ return 0;
+}
diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
new file mode 100644
index 0000000000..8713af16eb
--- /dev/null
+++ b/tests/tcg/xtensa/Makefile
@@ -0,0 +1,75 @@
+-include ../../config-host.mak
+
+CROSS=xtensa-dc232b-elf-
+
+ifndef XT
+SIM = qemu-system-xtensa
+SIMFLAGS = -M sim -cpu dc232b -nographic -semihosting $(EXTFLAGS) -kernel
+SIMDEBUG = -s -S
+else
+SIM = xt-run
+SIMFLAGS = --xtensa-core=DC_B_232L --exit_with_target_code $(EXTFLAGS)
+SIMDEBUG = --gdbserve=0
+endif
+
+CC = $(CROSS)gcc
+AS = $(CROSS)gcc -x assembler
+LD = $(CROSS)ld
+
+LDFLAGS = -Tlinker.ld
+
+CRT = crt.o vectors.o
+
+TESTCASES += test_b.tst
+TESTCASES += test_bi.tst
+#TESTCASES += test_boolean.tst
+TESTCASES += test_bz.tst
+TESTCASES += test_clamps.tst
+TESTCASES += test_fail.tst
+TESTCASES += test_interrupt.tst
+TESTCASES += test_loop.tst
+TESTCASES += test_mac16.tst
+TESTCASES += test_max.tst
+TESTCASES += test_min.tst
+TESTCASES += test_mmu.tst
+TESTCASES += test_mul16.tst
+TESTCASES += test_mul32.tst
+TESTCASES += test_nsa.tst
+ifdef XT
+TESTCASES += test_pipeline.tst
+endif
+TESTCASES += test_quo.tst
+TESTCASES += test_rem.tst
+TESTCASES += test_rst0.tst
+TESTCASES += test_sar.tst
+TESTCASES += test_sext.tst
+TESTCASES += test_shift.tst
+TESTCASES += test_timer.tst
+TESTCASES += test_windowed.tst
+
+all: build
+
+%.o: $(SRC_PATH)/tests/xtensa/%.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: $(SRC_PATH)/tests/xtensa/%.S
+ $(AS) $(ASFLAGS) -c $< -o $@
+
+%.tst: %.o macros.inc $(CRT) Makefile
+ $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+
+build: $(TESTCASES)
+
+check: $(addprefix run-, $(TESTCASES))
+
+run-%.tst: %.tst
+ $(SIM) $(SIMFLAGS) ./$<
+
+run-test_fail.tst: test_fail.tst
+ ! $(SIM) $(SIMFLAGS) ./$<
+
+debug-%.tst: %.tst
+ $(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
+
+clean:
+ $(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/tcg/xtensa/crt.S b/tests/tcg/xtensa/crt.S
new file mode 100644
index 0000000000..d9846acace
--- /dev/null
+++ b/tests/tcg/xtensa/crt.S
@@ -0,0 +1,24 @@
+.section .init
+ j 1f
+.section .init.text
+1:
+ movi a2, _start
+ jx a2
+
+.text
+.global _start
+_start:
+ movi a2, 1
+ wsr a2, windowstart
+ movi a2, 0
+ wsr a2, windowbase
+ movi a1, _fstack
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+
+ call0 main
+
+ mov a3, a2
+ movi a2, 1
+ simcall
diff --git a/tests/tcg/xtensa/linker.ld b/tests/tcg/xtensa/linker.ld
new file mode 100644
index 0000000000..4d0b307fd2
--- /dev/null
+++ b/tests/tcg/xtensa/linker.ld
@@ -0,0 +1,112 @@
+OUTPUT_FORMAT("elf32-xtensa-le")
+ENTRY(_start)
+
+__DYNAMIC = 0;
+
+MEMORY {
+ ram : ORIGIN = 0xd0000000, LENGTH = 0x08000000 /* 128M */
+ rom : ORIGIN = 0xfe000000, LENGTH = 0x00001000 /* 4k */
+}
+
+SECTIONS
+{
+ .init :
+ {
+ *(.init)
+ *(.init.*)
+ } > rom
+
+ .vector :
+ {
+ . = 0x00000000;
+ *(.vector.window_overflow_4)
+ *(.vector.window_overflow_4.*)
+ . = 0x00000040;
+ *(.vector.window_underflow_4)
+ *(.vector.window_underflow_4.*)
+ . = 0x00000080;
+ *(.vector.window_overflow_8)
+ *(.vector.window_overflow_8.*)
+ . = 0x000000c0;
+ *(.vector.window_underflow_8)
+ *(.vector.window_underflow_8.*)
+ . = 0x00000100;
+ *(.vector.window_overflow_12)
+ *(.vector.window_overflow_12.*)
+ . = 0x00000140;
+ *(.vector.window_underflow_12)
+ *(.vector.window_underflow_12.*)
+
+ . = 0x00000180;
+ *(.vector.level2)
+ *(.vector.level2.*)
+ . = 0x000001c0;
+ *(.vector.level3)
+ *(.vector.level3.*)
+ . = 0x00000200;
+ *(.vector.level4)
+ *(.vector.level4.*)
+ . = 0x00000240;
+ *(.vector.level5)
+ *(.vector.level5.*)
+ . = 0x00000280;
+ *(.vector.level6)
+ *(.vector.level6.*)
+ . = 0x000002c0;
+ *(.vector.level7)
+ *(.vector.level7.*)
+
+ . = 0x00000300;
+ *(.vector.kernel)
+ *(.vector.kernel.*)
+ . = 0x00000340;
+ *(.vector.user)
+ *(.vector.user.*)
+ . = 0x000003c0;
+ *(.vector.double)
+ *(.vector.double.*)
+ } > ram
+
+ .text :
+ {
+ _ftext = .;
+ *(.text .stub .text.* .gnu.linkonce.t.* .literal .literal.*)
+ _etext = .;
+ } > ram
+
+ .rodata :
+ {
+ . = ALIGN(4);
+ _frodata = .;
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ _erodata = .;
+ } > ram
+
+ .data :
+ {
+ . = ALIGN(4);
+ _fdata = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.data1)
+ _gp = ALIGN(16);
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ _edata = .;
+ } > ram
+
+ .bss :
+ {
+ . = ALIGN(4);
+ _fbss = .;
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ _ebss = .;
+ _end = .;
+ } > ram
+}
+
+PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
new file mode 100644
index 0000000000..2d4515e14f
--- /dev/null
+++ b/tests/tcg/xtensa/macros.inc
@@ -0,0 +1,68 @@
+.macro test_suite name
+.data
+status: .word result
+result: .space 20
+.text
+.global main
+.align 4
+main:
+.endm
+
+.macro reset_ps
+ movi a2, 0x4000f
+ wsr a2, ps
+ isync
+.endm
+
+.macro test_suite_end
+ reset_ps
+ movi a0, status
+ l32i a2, a0, 0
+ movi a0, result
+ sub a2, a2, a0
+ movi a3, 0
+ loopnez a2, 1f
+ l8ui a2, a0, 0
+ or a3, a3, a2
+ addi a0, a0, 1
+1:
+ exit
+.endm
+
+.macro test name
+.endm
+
+.macro test_end
+99:
+ reset_ps
+ movi a2, status
+ l32i a3, a2, 0
+ addi a3, a3, 1
+ s32i a3, a2, 0
+.endm
+
+.macro exit
+ movi a2, 1
+ simcall
+.endm
+
+.macro test_fail
+ movi a2, status
+ l32i a2, a2, 0
+ movi a3, 1
+ s8i a3, a2, 0
+ j 99f
+.endm
+
+.macro assert cond, arg1, arg2
+ b\cond \arg1, \arg2, 90f
+ test_fail
+90:
+ nop
+.endm
+
+.macro set_vector vector, addr
+ movi a2, handler_\vector
+ movi a3, \addr
+ s32i a3, a2, 0
+.endm
diff --git a/tests/tcg/xtensa/test_b.S b/tests/tcg/xtensa/test_b.S
new file mode 100644
index 0000000000..6cbe5f1fca
--- /dev/null
+++ b/tests/tcg/xtensa/test_b.S
@@ -0,0 +1,221 @@
+.include "macros.inc"
+
+test_suite b
+
+test bnone
+ movi a2, 0xa5a5ff00
+ movi a3, 0x5a5a00ff
+ bnone a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5ff01
+ bnone a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test beq
+ movi a2, 0
+ movi a3, 0
+ beq a2, a3, 1f
+ test_fail
+1:
+ movi a2, 1
+ beq a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test blt
+ movi a2, 6
+ movi a3, 7
+ blt a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ blt a2, a3, 1f
+ test_fail
+1:
+ movi a2, 7
+ blt a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bltu
+ movi a2, 6
+ movi a3, 7
+ bltu a2, a3, 1f
+ test_fail
+1:
+ movi a2, 7
+ bltu a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bltu a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test ball
+ movi a2, 0xa5a5ffa5
+ movi a3, 0xa5a5ff00
+ ball a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5a5a5
+ ball a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbc
+ movi a2, 0xfffffffd
+ movi a3, 0xffffff01
+ bbc a2, a3, 1f
+ test_fail
+1:
+ movi a2, 8
+ movi a3, 0xffffff03
+ bbc a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbci
+ movi a2, 0xfffdffff
+ bbci a2, 17, 1f
+ test_fail
+1:
+ movi a2, 0x00020000
+ bbci a2, 17, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bany
+ movi a2, 0xa5a5ff01
+ movi a3, 0x5a5a00ff
+ bany a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5ff00
+ bany a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bne
+ movi a2, 1
+ movi a3, 0
+ bne a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0
+ bne a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bge
+ movi a2, 7
+ movi a3, 7
+ bge a2, a3, 1f
+ test_fail
+1:
+ movi a2, 6
+ bge a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bge a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgeu
+ movi a2, 7
+ movi a3, 7
+ bgeu a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ bgeu a2, a3, 1f
+ test_fail
+1:
+ movi a2, 6
+ bgeu a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bnall
+ movi a2, 0xa5a5a5a5
+ movi a3, 0xa5a5ff00
+ bnall a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xa5a5ffa5
+ bnall a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbs
+ movi a2, 8
+ movi a3, 0xffffff03
+ bbs a2, a3, 1f
+ test_fail
+1:
+ movi a2, 0xfffffffd
+ movi a3, 0xffffff01
+ bbs a2, a3, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bbsi
+ movi a2, 0x00020000
+ bbsi a2, 17, 1f
+ test_fail
+1:
+ movi a2, 0xfffdffff
+ bbsi a2, 17, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_bi.S b/tests/tcg/xtensa/test_bi.S
new file mode 100644
index 0000000000..6a5f1dffc9
--- /dev/null
+++ b/tests/tcg/xtensa/test_bi.S
@@ -0,0 +1,103 @@
+.include "macros.inc"
+
+test_suite bi
+
+test beqi
+ movi a2, 7
+ beqi a2, 7, 1f
+ test_fail
+1:
+ movi a2, 1
+ beqi a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bnei
+ movi a2, 1
+ bnei a2, 7, 1f
+ test_fail
+1:
+ movi a2, 7
+ bnei a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test blti
+ movi a2, 6
+ blti a2, 7, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ blti a2, 7, 1f
+ test_fail
+1:
+ movi a2, 7
+ blti a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgei
+ movi a2, 7
+ bgei a2, 7, 1f
+ test_fail
+1:
+ movi a2, 6
+ bgei a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bgei a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bltui
+ movi a2, 6
+ bltui a2, 7, 1f
+ test_fail
+1:
+ movi a2, 7
+ bltui a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+ movi a2, 0xffffffff
+ bltui a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgeui
+ movi a2, 7
+ bgeui a2, 7, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ bgeui a2, 7, 1f
+ test_fail
+1:
+ movi a2, 6
+ bgeui a2, 7, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_boolean.S b/tests/tcg/xtensa/test_boolean.S
new file mode 100644
index 0000000000..50e6d2c22a
--- /dev/null
+++ b/tests/tcg/xtensa/test_boolean.S
@@ -0,0 +1,23 @@
+.include "macros.inc"
+
+test_suite boolean
+
+test all4
+ movi a2, 0xfec0
+ wsr a2, br
+ all4 b0, b0
+ rsr a3, br
+ assert eq, a2, a3
+ all4 b0, b4
+ rsr a3, br
+ assert eq, a2, a3
+ all4 b0, b8
+ rsr a3, br
+ assert eq, a2, a3
+ all4 b0, b12
+ rsr a3, br
+ addi a2, a2, 1
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_bz.S b/tests/tcg/xtensa/test_bz.S
new file mode 100644
index 0000000000..f9ba6e22e8
--- /dev/null
+++ b/tests/tcg/xtensa/test_bz.S
@@ -0,0 +1,57 @@
+.include "macros.inc"
+
+test_suite bz
+
+test beqz
+ movi a2, 0
+ _beqz a2, 1f
+ test_fail
+1:
+ movi a2, 1
+ _beqz a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bnez
+ movi a2, 1
+ _bnez a2, 1f
+ test_fail
+1:
+ movi a2, 0
+ _bnez a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bltz
+ movi a2, 0xffffffff
+ bltz a2, 1f
+ test_fail
+1:
+ movi a2, 0
+ bltz a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test bgez
+ movi a2, 0
+ bgez a2, 1f
+ test_fail
+1:
+ movi a2, 0xffffffff
+ bgez a2, 1f
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_clamps.S b/tests/tcg/xtensa/test_clamps.S
new file mode 100644
index 0000000000..c186cc98d8
--- /dev/null
+++ b/tests/tcg/xtensa/test_clamps.S
@@ -0,0 +1,42 @@
+.include "macros.inc"
+
+test_suite clamps
+
+test clamps
+ movi a2, 0
+ movi a3, 0
+ clamps a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0x7f
+ movi a3, 0x7f
+ clamps a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0xffffff80
+ movi a3, 0xffffff80
+ clamps a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0x80
+ movi a3, 0x7f
+ clamps a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0xffffff7f
+ movi a3, 0xffffff80
+ clamps a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0x7fffffff
+ movi a3, 0x7f
+ clamps a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0x80000000
+ movi a3, 0xffffff80
+ clamps a2, a2, 7
+ assert eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_fail.S b/tests/tcg/xtensa/test_fail.S
new file mode 100644
index 0000000000..e8d1b425bc
--- /dev/null
+++ b/tests/tcg/xtensa/test_fail.S
@@ -0,0 +1,9 @@
+.include "macros.inc"
+
+test_suite fail
+
+test fail
+ test_fail
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_interrupt.S b/tests/tcg/xtensa/test_interrupt.S
new file mode 100644
index 0000000000..68b3ee1492
--- /dev/null
+++ b/tests/tcg/xtensa/test_interrupt.S
@@ -0,0 +1,194 @@
+.include "macros.inc"
+
+test_suite interrupt
+
+.macro clear_interrupts
+ movi a2, 0
+ wsr a2, intenable
+ wsr a2, ccompare0
+ wsr a2, ccompare1
+ wsr a2, ccompare2
+ esync
+ rsr a2, interrupt
+ wsr a2, intclear
+
+ esync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+.endm
+
+.macro check_l1
+ rsr a2, ps
+ movi a3, 0x1f /* EXCM | INTMASK */
+ and a2, a2, a3
+ assert eqi, a2, 0x10 /* only EXCM is set for level-1 interrupt */
+ rsr a2, exccause
+ assert eqi, a2, 4
+.endm
+
+test rsil
+ clear_interrupts
+
+ rsr a2, ps
+ rsil a3, 7
+ rsr a4, ps
+ assert eq, a2, a3
+ movi a2, 0xf
+ and a2, a4, a2
+ assert eqi, a2, 7
+ xor a3, a3, a4
+ movi a2, 0xfffffff0
+ and a2, a3, a2
+ assert eqi, a2, 0
+test_end
+
+test soft_disabled
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intclear
+ esync
+ rsr a3, interrupt
+ assert eqi, a3, 0
+ j 2f
+1:
+ test_fail
+2:
+test_end
+
+test soft_intenable
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ rsil a3, 0
+ wsr a2, intenable
+ esync
+ test_fail
+1:
+ check_l1
+test_end
+
+test soft_rsil
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intenable
+ rsil a3, 0
+ esync
+ test_fail
+1:
+ check_l1
+test_end
+
+test soft_waiti
+ set_vector kernel, 1f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intenable
+ waiti 0
+ test_fail
+1:
+ check_l1
+test_end
+
+test soft_user
+ set_vector kernel, 1f
+ set_vector user, 2f
+ clear_interrupts
+
+ movi a2, 0x80
+ wsr a2, intset
+ esync
+ rsr a3, interrupt
+ assert eq, a2, a3
+ wsr a2, intenable
+
+ rsr a2, ps
+ movi a3, 0x20
+ or a2, a2, a3
+ wsr a2, ps
+ waiti 0
+1:
+ test_fail
+2:
+ check_l1
+test_end
+
+test soft_priority
+ set_vector kernel, 1f
+ set_vector level3, 2f
+ clear_interrupts
+
+ movi a2, 0x880
+ wsr a2, intenable
+ rsil a3, 0
+ esync
+ wsr a2, intset
+ esync
+1:
+ test_fail
+2:
+ rsr a2, ps
+ movi a3, 0x1f /* EXCM | INTMASK */
+ and a2, a2, a3
+ movi a3, 0x13
+ assert eq, a2, a3 /* EXCM and INTMASK are set
+ for high-priority interrupt */
+test_end
+
+test eps_epc_rfi
+ set_vector level3, 3f
+ clear_interrupts
+ reset_ps
+
+ movi a2, 0x880
+ wsr a2, intenable
+ rsil a3, 0
+ rsr a3, ps
+ esync
+ wsr a2, intset
+1:
+ esync
+2:
+ test_fail
+3:
+ rsr a2, eps3
+ assert eq, a2, a3
+ rsr a2, epc3
+ movi a3, 1b
+ assert ge, a2, a3
+ movi a3, 2b
+ assert ge, a3, a2
+ movi a2, 4f
+ wsr a2, epc3
+ movi a2, 0x40003
+ wsr a2, eps3
+ rfi 3
+ test_fail
+4:
+ rsr a2, ps
+ movi a3, 0x40003
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_loop.S b/tests/tcg/xtensa/test_loop.S
new file mode 100644
index 0000000000..a5ea933913
--- /dev/null
+++ b/tests/tcg/xtensa/test_loop.S
@@ -0,0 +1,77 @@
+.include "macros.inc"
+
+test_suite loop
+
+test loop
+ movi a2, 0
+ movi a3, 5
+ loop a3, 1f
+ addi a2, a2, 1
+1:
+ assert eqi, a2, 5
+test_end
+
+test loop0
+ movi a2, 0
+ loop a2, 1f
+ rsr a2, lcount
+ assert eqi, a2, -1
+ j 1f
+1:
+test_end
+
+test loop_jump
+ movi a2, 0
+ movi a3, 5
+ loop a3, 1f
+ addi a2, a2, 1
+ j 1f
+1:
+ assert eqi, a2, 1
+test_end
+
+test loop_branch
+ movi a2, 0
+ movi a3, 5
+ loop a3, 1f
+ addi a2, a2, 1
+ beqi a2, 3, 1f
+1:
+ assert eqi, a2, 3
+test_end
+
+test loop_manual
+ movi a2, 0
+ movi a3, 5
+ movi a4, 1f
+ movi a5, 2f
+ wsr a3, lcount
+ wsr a4, lbeg
+ wsr a5, lend
+ isync
+ j 1f
+.align 4
+1:
+ addi a2, a2, 1
+2:
+ assert eqi, a2, 6
+test_end
+
+test loop_excm
+ movi a2, 0
+ movi a3, 5
+ rsr a4, ps
+ movi a5, 0x10
+ or a4, a4, a5
+ wsr a4, ps
+ isync
+ loop a3, 1f
+ addi a2, a2, 1
+1:
+ xor a4, a4, a5
+ isync
+ wsr a4, ps
+ assert eqi, a2, 1
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mac16.S b/tests/tcg/xtensa/test_mac16.S
new file mode 100644
index 0000000000..5ddd160ffc
--- /dev/null
+++ b/tests/tcg/xtensa/test_mac16.S
@@ -0,0 +1,243 @@
+.include "macros.inc"
+
+test_suite mac16
+
+#define ext16(v) (((v) & 0xffff) | (((v) & 0x8000) * 0x1ffffffe))
+#define mul16(a, b) ((ext16(a) * ext16(b)))
+
+.macro assert_acc_value v
+ rsr a4, ACCLO
+ movi a5, (\v) & 0xffffffff
+ assert eq, a4, a5
+ rsr a4, ACCHI
+ movi a5, (\v) >> 32
+ sext a5, a5, 7
+ assert eq, a4, a5
+.endm
+
+.macro init_reg sr, reg, val
+ .if (\sr)
+ movi a4, \val
+ wsr a4, \reg
+ .else
+ movi \reg, \val
+ .endif
+.endm
+
+.macro test_mulxx mulop, comb, s, t, a, b
+ init_reg \comb & 2, \s, \a
+ init_reg \comb & 1, \t, \b
+
+ \mulop\().ll \s, \t
+ assert_acc_value mul16(\a, \b)
+
+ \mulop\().lh \s, \t
+ assert_acc_value mul16(\a, (\b >> 16))
+
+ \mulop\().hl \s, \t
+ assert_acc_value mul16((\a >> 16), \b)
+
+ \mulop\().hh \s, \t
+ assert_acc_value mul16((\a >> 16), (\b >> 16))
+.endm
+
+test mul_aa
+ test_mulxx mul.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_ad
+ test_mulxx mul.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_da
+ test_mulxx mul.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+test mul_dd
+ test_mulxx mul.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f
+test_end
+
+
+.macro init_acc iv
+ movi a4, (\iv) & 0xffffffff
+ wsr a4, ACCLO
+ movi a4, (\iv) >> 32
+ wsr a4, ACCHI
+.endm
+
+.macro test_mulxxx mulop, comb, s, t, a, b, iv, op
+ init_reg \comb & 2, \s, \a
+ init_reg \comb & 1, \t, \b
+
+ init_acc \iv
+ \mulop\().ll \s, \t
+ assert_acc_value (\iv \op mul16(\a, \b))
+
+ init_acc \iv
+ \mulop\().lh \s, \t
+ assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
+
+ init_acc \iv
+ \mulop\().hl \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), \b))
+
+ init_acc \iv
+ \mulop\().hh \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
+.endm
+
+
+test mula_aa
+ test_mulxxx mula.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
+test_end
+
+test mula_ad
+ test_mulxxx mula.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, +
+test_end
+
+test mula_da
+ test_mulxxx mula.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+test_end
+
+test mula_dd
+ test_mulxxx mula.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+test_end
+
+
+test muls_aa
+ test_mulxxx muls.aa, 0, a2, a3, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
+test_end
+
+test muls_ad
+ test_mulxxx muls.ad, 1, a2, m2, 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, -
+test_end
+
+test muls_da
+ test_mulxxx muls.da, 2, m1, a3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
+test_end
+
+test muls_dd
+ test_mulxxx muls.dd, 3, m0, m3, 0xf7315a5a, 0xa5a5137f, 0xfff73155aa, -
+test_end
+
+test ldinc
+ movi a2, 1f - 4
+ ldinc m0, a2
+ movi a3, 1f
+ assert eq, a2, a3
+ rsr a3, m0
+ movi a4, 0x55aa137f
+ assert eq, a3, a4
+ ldinc m1, a2
+ movi a3, 1f + 4
+ assert eq, a2, a3
+ rsr a3, m1
+ movi a4, 0x12345678
+ assert eq, a3, a4
+
+.data
+1: .word 0x55aa137f, 0x12345678, 0x137fa5a5
+.text
+test_end
+
+test lddec
+ movi a2, 1f
+ lddec m2, a2
+ movi a3, 1f - 4
+ assert eq, a2, a3
+ rsr a3, m2
+ movi a4, 0x12345678
+ assert eq, a3, a4
+ lddec m3, a2
+ movi a3, 1f - 8
+ assert eq, a2, a3
+ rsr a3, m3
+ movi a4, 0x55aa137f
+ assert eq, a3, a4
+.data
+ .word 0x55aa137f, 0x12345678
+1:
+.text
+test_end
+
+
+.macro test_mulxxx_ld mulop, ldop, comb, w, x, s, t, a, b, iv, op
+ init_reg \comb & 2, \s, \a
+ init_reg \comb & 1, \t, \b
+
+ init_acc \iv
+ \mulop\().ll.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16(\a, \b))
+
+ init_acc \iv
+ \mulop\().lh.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16(\a, (\b >> 16)))
+
+ init_acc \iv
+ \mulop\().hl.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), \b))
+
+ init_acc \iv
+ \mulop\().hh.\ldop \w, \x, \s, \t
+ assert_acc_value (\iv \op mul16((\a >> 16), (\b >> 16)))
+.endm
+
+test mula_da_ldinc
+ movi a2, 1f - 4
+ test_mulxxx_ld mula.da, ldinc, 2, m1, a2, m1, a3, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f + 12
+ assert eq, a2, a3
+ rsr a2, m1
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+1: .word 0xf7315a5a, 0xf7315a5a, 0xf7315a5a, 0x12345678
+.text
+test_end
+
+test mula_dd_ldinc
+ movi a2, 1f - 4
+ test_mulxxx_ld mula.dd, ldinc, 3, m2, a2, m1, m2, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f + 12
+ assert eq, a2, a3
+ rsr a2, m2
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+1: .word 0xa5a5137f, 0xa5a5137f, 0xa5a5137f, 0x12345678
+.text
+test_end
+
+test mula_da_lddec
+ movi a2, 1f
+ test_mulxxx_ld mula.da, lddec, 2, m1, a2, m1, a3, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f - 16
+ assert eq, a2, a3
+ rsr a2, m1
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+ .word 0x12345678, 0xf7315a5a, 0xf7315a5a, 0xf7315a5a
+1:
+.text
+test_end
+
+test mula_dd_lddec
+ movi a2, 1f
+ test_mulxxx_ld mula.dd, lddec, 3, m2, a2, m1, m2, \
+ 0xf7315a5a, 0xa5a5137f, 0x0ff73155aa, +
+ movi a3, 1f - 16
+ assert eq, a2, a3
+ rsr a2, m2
+ movi a3, 0x12345678
+ assert eq, a2, a3
+.data
+ .word 0x12345678, 0xa5a5137f, 0xa5a5137f, 0xa5a5137f
+1:
+.text
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_max.S b/tests/tcg/xtensa/test_max.S
new file mode 100644
index 0000000000..2534c9d90b
--- /dev/null
+++ b/tests/tcg/xtensa/test_max.S
@@ -0,0 +1,81 @@
+.include "macros.inc"
+
+test_suite max
+
+test max
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ max a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ max a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ max a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ max a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ max a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ max a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test maxu
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ maxu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ maxu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ maxu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ maxu a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ maxu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ maxu a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_min.S b/tests/tcg/xtensa/test_min.S
new file mode 100644
index 0000000000..6d9ddeb1ac
--- /dev/null
+++ b/tests/tcg/xtensa/test_min.S
@@ -0,0 +1,81 @@
+.include "macros.inc"
+
+test_suite min
+
+test min
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ min a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ min a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ min a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 0xffffffff
+ min a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ min a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 0xffffffff
+ min a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test minu
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ minu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ minu a5, a2, a3
+ assert eq, a5, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ minu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 0xffffffff
+ movi a3, 1
+ movi a4, 1
+ minu a3, a2, a3
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ minu a2, a2, a3
+ assert eq, a2, a4
+
+ movi a2, 1
+ movi a3, 0xffffffff
+ movi a4, 1
+ minu a3, a2, a3
+ assert eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S
new file mode 100644
index 0000000000..52d5774212
--- /dev/null
+++ b/tests/tcg/xtensa/test_mmu.S
@@ -0,0 +1,318 @@
+.include "macros.inc"
+
+test_suite mmu
+
+.purgem test
+
+.macro test name
+ movi a2, 0x00000004
+ idtlb a2
+ movi a2, 0x00100004
+ idtlb a2
+ movi a2, 0x00200004
+ idtlb a2
+ movi a2, 0x00300004
+ idtlb a2
+ movi a2, 0x00000007
+ idtlb a2
+.endm
+
+test tlb_group
+ movi a2, 0x04000002 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ witlb a2, a3
+ movi a3, 0x00200004
+ rdtlb0 a1, a3
+ ritlb0 a2, a3
+ movi a3, 0x01000001
+ assert eq, a1, a3
+ assert eq, a2, a3
+ movi a3, 0x00200004
+ rdtlb1 a1, a3
+ ritlb1 a2, a3
+ movi a3, 0x04000002
+ assert eq, a1, a3
+ assert eq, a2, a3
+ movi a3, 0x01234567
+ pdtlb a1, a3
+ pitlb a2, a3
+ movi a3, 0x01234014
+ assert eq, a1, a3
+ movi a3, 0x0123400c
+ assert eq, a2, a3
+ movi a3, 0x00200004
+ idtlb a3
+ iitlb a3
+ movi a3, 0x01234567
+ pdtlb a1, a3
+ pitlb a2, a3
+ movi a3, 0x00000010
+ and a1, a1, a3
+ assert eqi, a1, 0
+ movi a3, 0x00000008
+ and a2, a2, a3
+ assert eqi, a2, 0
+test_end
+
+test itlb_miss
+ set_vector kernel, 1f
+
+ movi a3, 0x00100000
+ jx a3
+ test_fail
+1:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 16
+ assert eq, a2, a3
+test_end
+
+test dtlb_miss
+ set_vector kernel, 1f
+
+ movi a3, 0x00100000
+ l8ui a2, a3, 0
+ test_fail
+1:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 24
+ assert eq, a2, a3
+test_end
+
+test itlb_multi_hit
+ set_vector kernel, 1f
+
+ movi a2, 0x04000002 /* PPN */
+ movi a3, 0xf0000004 /* VPN */
+ witlb a2, a3
+ movi a3, 0xf0000000
+ pitlb a2, a3
+ test_fail
+1:
+ rsr a2, exccause
+ movi a3, 17
+ assert eq, a2, a3
+test_end
+
+test dtlb_multi_hit
+ set_vector kernel, 1f
+
+ movi a2, 0x04000002 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200007 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200000
+ pdtlb a2, a3
+ test_fail
+1:
+ rsr a2, exccause
+ movi a3, 25
+ assert eq, a2, a3
+test_end
+
+test inst_fetch_privilege
+ set_vector kernel, 3f
+
+ movi a2, 0x4004f
+ wsr a2, ps
+1:
+ isync
+ nop
+2:
+ test_fail
+3:
+ movi a1, 1b
+ rsr a2, excvaddr
+ rsr a3, epc1
+ assert ge, a2, a1
+ assert ge, a3, a1
+ movi a1, 2b
+ assert lt, a2, a1
+ assert lt, a3, a1
+ rsr a2, exccause
+ movi a3, 18
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4005f
+ assert eq, a2, a3
+test_end
+
+test load_store_privilege
+ set_vector kernel, 2f
+
+ movi a3, 10f
+ pitlb a3, a3
+ ritlb1 a2, a3
+ movi a1, 0x10
+ or a2, a2, a1
+ movi a1, 0x000ff000
+ and a3, a3, a1
+ movi a1, 4
+ or a3, a3, a1
+ witlb a2, a3
+ movi a3, 10f
+ movi a1, 0x000fffff
+ and a1, a3, a1
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200001
+ movi a2, 0x4004f
+ jx a1
+10:
+ wsr a2, ps
+ isync
+1:
+ l8ui a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 1b
+ movi a1, 0x000fffff
+ and a3, a3, a1
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 26
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4005f
+ assert eq, a2, a3
+test_end
+
+test cring_load_store_privilege
+ set_vector kernel, 0
+ set_vector double, 2f
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200004
+ movi a2, 0x4005f /* ring 1 + excm => cring == 0 */
+ wsr a2, ps
+ isync
+ l8ui a2, a3, 0 /* cring used */
+1:
+ l32e a2, a3, -4 /* ring used */
+ test_fail
+2:
+ rsr a2, excvaddr
+ addi a2, a2, 4
+ assert eq, a2, a3
+ rsr a2, depc
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 26
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4005f
+ assert eq, a2, a3
+test_end
+
+test inst_fetch_prohibited
+ set_vector kernel, 2f
+
+ movi a3, 10f
+ pitlb a3, a3
+ ritlb1 a2, a3
+ movi a1, 0xfffff000
+ and a2, a2, a1
+ movi a1, 0x4
+ or a2, a2, a1
+ movi a1, 0x000ff000
+ and a3, a3, a1
+ movi a1, 4
+ or a3, a3, a1
+ witlb a2, a3
+ movi a3, 10f
+ movi a1, 0x000fffff
+ and a1, a3, a1
+ jx a1
+ .align 4
+10:
+ nop
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a1
+ rsr a2, epc1
+ assert eq, a2, a1
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+test_end
+
+test load_prohibited
+ set_vector kernel, 2f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200002
+1:
+ l8ui a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+test_end
+
+test store_prohibited
+ set_vector kernel, 2f
+
+ movi a2, 0x04000001 /* PPN */
+ movi a3, 0x01200004 /* VPN */
+ wdtlb a2, a3
+ movi a3, 0x01200003
+ l8ui a2, a3, 0
+1:
+ s8i a2, a3, 0
+ test_fail
+2:
+ rsr a2, excvaddr
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ rsr a2, exccause
+ movi a3, 29
+ assert eq, a2, a3
+test_end
+
+test dtlb_autoload
+ set_vector kernel, 0
+
+ movi a2, 0xd4000000
+ wsr a2, ptevaddr
+ movi a3, 0x00001013
+ s32i a3, a2, 4
+ pdtlb a2, a3
+ movi a1, 0x10
+ and a1, a1, a2
+ assert eqi, a1, 0
+ l8ui a1, a3, 0
+ pdtlb a2, a3
+ movi a1, 0xfffff010
+ and a1, a1, a2
+ movi a3, 0x00001010
+ assert eq, a1, a3
+ movi a1, 0xf
+ and a1, a1, a2
+ assert lti, a1, 4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mul16.S b/tests/tcg/xtensa/test_mul16.S
new file mode 100644
index 0000000000..bf94376649
--- /dev/null
+++ b/tests/tcg/xtensa/test_mul16.S
@@ -0,0 +1,83 @@
+.include "macros.inc"
+
+test_suite mul16
+
+test mul16u_pp
+ movi a2, 0x137f5a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x06e180a6
+ mul16u a5, a2, a4
+ assert eq, a5, a6
+ mul16u a2, a2, a4
+ assert eq, a2, a6
+ mul16u a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16u_np
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x0c9d6bdb
+ mul16u a5, a2, a4
+ assert eq, a5, a6
+ mul16u a2, a2, a4
+ assert eq, a2, a6
+ mul16u a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16u_nn
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5f731
+ movi a6, 0x9ff1e795
+ mul16u a5, a2, a4
+ assert eq, a5, a6
+ mul16u a2, a2, a4
+ assert eq, a2, a6
+ mul16u a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16s_pp
+ movi a2, 0x137f5a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x06e180a6
+ mul16s a5, a2, a4
+ assert eq, a5, a6
+ mul16s a2, a2, a4
+ assert eq, a2, a6
+ mul16s a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16s_np
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf91e6bdb
+ mul16s a5, a2, a4
+ assert eq, a5, a6
+ mul16s a2, a2, a4
+ assert eq, a2, a6
+ mul16s a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test mul16s_nn
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5f731
+ movi a6, 0x031be795
+ mul16s a5, a2, a4
+ assert eq, a5, a6
+ mul16s a2, a2, a4
+ assert eq, a2, a6
+ mul16s a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_mul32.S b/tests/tcg/xtensa/test_mul32.S
new file mode 100644
index 0000000000..fdaf57331b
--- /dev/null
+++ b/tests/tcg/xtensa/test_mul32.S
@@ -0,0 +1,20 @@
+.include "macros.inc"
+
+test_suite mul32
+
+test mull
+ movi a2, 0x137f5a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x5de480a6
+ mull a5, a2, a4
+ assert eq, a5, a6
+ mull a2, a2, a4
+ assert eq, a2, a6
+ mull a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+/* unfortunately dc232b doesn't have muluh/mulsh*/
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_nsa.S b/tests/tcg/xtensa/test_nsa.S
new file mode 100644
index 0000000000..a5fe5debe4
--- /dev/null
+++ b/tests/tcg/xtensa/test_nsa.S
@@ -0,0 +1,59 @@
+.include "macros.inc"
+
+test_suite nsa
+
+test nsa
+ movi a2, 0
+ movi a3, 31
+ nsa a4, a2
+ assert eq, a3, a4
+
+ movi a2, 0xffffffff
+ movi a3, 31
+ nsa a4, a2
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 30
+ nsa a2, a2
+ assert eq, a3, a2
+
+ movi a2, 0xfffffffe
+ movi a3, 30
+ nsa a2, a2
+ assert eq, a3, a2
+
+ movi a2, 0x5a5a5a5a
+ movi a3, 0
+ nsa a4, a2
+ assert eq, a3, a4
+
+ movi a2, 0xa5a5a5a5
+ movi a3, 0
+ nsa a4, a2
+ assert eq, a3, a4
+test_end
+
+test nsau
+ movi a2, 0
+ movi a3, 32
+ nsau a4, a2
+ assert eq, a3, a4
+
+ movi a2, 0xffffffff
+ movi a3, 0
+ nsau a4, a2
+ assert eq, a3, a4
+
+ movi a2, 1
+ movi a3, 31
+ nsau a2, a2
+ assert eq, a3, a2
+
+ movi a2, 0x5a5a5a5a
+ movi a3, 1
+ nsau a2, a2
+ assert eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_pipeline.S b/tests/tcg/xtensa/test_pipeline.S
new file mode 100644
index 0000000000..6be6085fc3
--- /dev/null
+++ b/tests/tcg/xtensa/test_pipeline.S
@@ -0,0 +1,157 @@
+.include "macros.inc"
+
+.purgem test
+.macro test name
+ movi a2, 1f
+ movi a3, 99f
+0:
+ ipf a2, 0
+ ipf a2, 4
+ ipf a2, 8
+ ipf a2, 12
+ addi a2, a2, 16
+ blt a2, a3, 0b
+ j 1f
+ .align 4
+1:
+.endm
+
+test_suite pipeline
+
+test register_no_stall
+ rsr a3, ccount
+ add a5, a6, a6
+ add a6, a5, a5
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 3
+test_end
+
+test register_stall
+ l32i a5, a1, 0 /* data cache preload */
+ nop
+ rsr a3, ccount
+ l32i a5, a1, 0
+ add a6, a5, a5 /* M-to-E interlock */
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test j0_stall
+ rsr a3, ccount
+ j 1f /* E + 2-cycle penalty */
+1:
+ rsr a4, ccount /* E */
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test j1_stall
+ rsr a3, ccount
+ j 1f
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test j5_stall
+ rsr a3, ccount
+ j 1f
+ nop
+ nop
+ nop
+ nop
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test b_no_stall
+ movi a5, 1
+ rsr a3, ccount
+ beqi a5, 2, 1f
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 2
+1:
+test_end
+
+test b1_stall
+ movi a5, 1
+ rsr a3, ccount
+ beqi a5, 1, 1f
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+test b5_stall
+ movi a5, 1
+ rsr a3, ccount
+ beqi a5, 1, 1f
+ nop
+ nop
+ nop
+ nop
+ nop
+1:
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 4
+test_end
+
+/* PS *SYNC */
+
+test ps_dsync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ dsync
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 5
+test_end
+
+test ps_esync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ esync
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 5
+test_end
+
+test ps_rsync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ rsync
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 5
+test_end
+
+test ps_isync
+ rsr a5, ps
+ isync
+ rsr a3, ccount
+ wsr a5, ps
+ isync
+ rsr a4, ccount
+ sub a3, a4, a3
+ movi a4, 9
+ assert eq, a3, a4
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_quo.S b/tests/tcg/xtensa/test_quo.S
new file mode 100644
index 0000000000..12debf1fe0
--- /dev/null
+++ b/tests/tcg/xtensa/test_quo.S
@@ -0,0 +1,147 @@
+.include "macros.inc"
+
+test_suite quo
+
+test quou_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x4
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x8
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x1
+ quou a5, a2, a4
+ assert eq, a5, a6
+ quou a2, a2, a4
+ assert eq, a2, a6
+ quou a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quou_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ quou a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test quos_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x4
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0xfffffffc
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0xfffffff6
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0
+ quos a5, a2, a4
+ assert eq, a5, a6
+ quos a2, a2, a4
+ assert eq, a2, a6
+ quos a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test quos_over
+ movi a2, 0x80000000
+ movi a4, 0xffffffff
+ movi a6, 0x80000000
+ quos a5, a2, a4
+ assert eq, a5, a6
+test_end
+
+test quos_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ quos a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_rem.S b/tests/tcg/xtensa/test_rem.S
new file mode 100644
index 0000000000..bb0d5fe202
--- /dev/null
+++ b/tests/tcg/xtensa/test_rem.S
@@ -0,0 +1,147 @@
+.include "macros.inc"
+
+test_suite rem
+
+test remu_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x0c5caa17
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x9aa40af
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0x5a5a137f
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x518c46db
+ remu a5, a2, a4
+ assert eq, a5, a6
+ remu a2, a2, a4
+ assert eq, a2, a6
+ remu a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test remu_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ remu a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test rems_pp
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0x0c5caa17
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_np
+ movi a2, 0xa5a5137f
+ mov a3, a2
+ movi a4, 0x137f5a5a
+ movi a6, 0xf3a27ce7
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_pn
+ movi a2, 0x5a5a137f
+ mov a3, a2
+ movi a4, 0xf7315a5a
+ movi a6, 0x02479b03
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_nn
+ movi a2, 0xf7315a5a
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf7315a5a
+ rems a5, a2, a4
+ assert eq, a5, a6
+ rems a2, a2, a4
+ assert eq, a2, a6
+ rems a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test rems_over
+ movi a2, 0x80000000
+ movi a4, 0xffffffff
+ movi a6, 0
+ rems a5, a2, a4
+ assert eq, a5, a6
+test_end
+
+test rems_exc
+ set_vector kernel, 2f
+ movi a2, 0xf7315a5a
+ movi a4, 0x00000000
+1:
+ rems a5, a2, a4
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 6 /* INTEGER_DIVIDE_BY_ZERO_CAUSE */
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_rst0.S b/tests/tcg/xtensa/test_rst0.S
new file mode 100644
index 0000000000..3eda565e8a
--- /dev/null
+++ b/tests/tcg/xtensa/test_rst0.S
@@ -0,0 +1,148 @@
+.include "macros.inc"
+
+test_suite rst0
+
+test and
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x01250125
+ and a5, a2, a4
+ assert eq, a5, a6
+ and a2, a2, a4
+ assert eq, a2, a6
+ and a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test or
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xb7ffb7ff
+ or a5, a2, a4
+ assert eq, a5, a6
+ or a2, a2, a4
+ assert eq, a2, a6
+ or a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test xor
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xb6dab6da
+ xor a5, a2, a4
+ assert eq, a5, a6
+ xor a2, a2, a4
+ assert eq, a2, a6
+ xor a3, a4, a3
+ assert eq, a3, a6
+test_end
+
+test add
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xb924b924
+ add a5, a2, a4
+ assert eq, a5, a6
+ add a2, a2, a4
+ assert eq, a2, a6
+ add a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test addx2
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xcca45ec9
+ addx2 a5, a2, a4
+ assert eq, a5, a6
+ addx2 a2, a2, a4
+ assert eq, a2, a6
+ addx2 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test addx4
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf3a3aa13
+ addx4 a5, a2, a4
+ assert eq, a5, a6
+ addx4 a2, a2, a4
+ assert eq, a2, a6
+ addx4 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test addx8
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x41a240a7
+ addx8 a5, a2, a4
+ assert eq, a5, a6
+ addx8 a2, a2, a4
+ assert eq, a2, a6
+ addx8 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test sub
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x6dda9226
+ sub a5, a2, a4
+ assert eq, a5, a6
+ sub a2, a2, a4
+ assert eq, a2, a6
+ sub a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test subx2
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0x815a37cb
+ subx2 a5, a2, a4
+ assert eq, a5, a6
+ subx2 a2, a2, a4
+ assert eq, a2, a6
+ subx2 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test subx4
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xa8598315
+ subx4 a5, a2, a4
+ assert eq, a5, a6
+ subx4 a2, a2, a4
+ assert eq, a2, a6
+ subx4 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test subx8
+ movi a2, 0x137fa5a5
+ mov a3, a2
+ movi a4, 0xa5a5137f
+ movi a6, 0xf65819a9
+ subx8 a5, a2, a4
+ assert eq, a5, a6
+ subx8 a2, a2, a4
+ assert eq, a2, a6
+ subx8 a4, a3, a4
+ assert eq, a4, a6
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_sar.S b/tests/tcg/xtensa/test_sar.S
new file mode 100644
index 0000000000..40c649ffb8
--- /dev/null
+++ b/tests/tcg/xtensa/test_sar.S
@@ -0,0 +1,111 @@
+.include "macros.inc"
+
+test_suite sar
+
+.macro test_sar prefix, imm
+ \prefix\()_set \imm
+ \prefix\()_ver \imm
+.endm
+
+.macro tests_sar prefix
+ test_sar \prefix, 0
+ test_sar \prefix, 1
+ test_sar \prefix, 2
+ test_sar \prefix, 3
+ test_sar \prefix, 0x1f
+ test_sar \prefix, 0x20
+ test_sar \prefix, 0x3f
+ test_sar \prefix, 0x40
+ test_sar \prefix, 0xfffffffe
+.endm
+
+.macro sar_set imm
+ movi a2, \imm
+ wsr a2, sar
+.endm
+
+.macro sar_ver imm
+ rsr a3, sar
+ movi a2, \imm & 0x3f
+ assert eq, a2, a3
+.endm
+
+test sar
+ tests_sar sar
+test_end
+
+.macro ssr_set imm
+ movi a2, \imm
+ ssr a2
+.endm
+
+.macro ssr_ver imm
+ rsr a3, sar
+ movi a2, \imm & 0x1f
+ assert eq, a2, a3
+.endm
+
+test ssr
+ tests_sar ssr
+test_end
+
+.macro ssl_set imm
+ movi a2, \imm
+ ssl a2
+.endm
+
+.macro ssl_ver imm
+ rsr a3, sar
+ movi a2, 32 - (\imm & 0x1f)
+ assert eq, a2, a3
+.endm
+
+test ssl
+ tests_sar ssl
+test_end
+
+.macro ssa8l_set imm
+ movi a2, \imm
+ ssa8l a2
+.endm
+
+.macro ssa8l_ver imm
+ rsr a3, sar
+ movi a2, (\imm & 0x3) << 3
+ assert eq, a2, a3
+.endm
+
+test ssa8l
+ tests_sar ssa8l
+test_end
+
+.macro ssa8b_set imm
+ movi a2, \imm
+ ssa8b a2
+.endm
+
+.macro ssa8b_ver imm
+ rsr a3, sar
+ movi a2, 32 - ((\imm & 0x3) << 3)
+ assert eq, a2, a3
+.endm
+
+test ssa8b
+ tests_sar ssa8b
+test_end
+
+.macro ssai_set imm
+ ssai \imm & 0x1f
+.endm
+
+.macro ssai_ver imm
+ rsr a3, sar
+ movi a2, \imm & 0x1f
+ assert eq, a2, a3
+.endm
+
+test ssai
+ tests_sar ssai
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_sext.S b/tests/tcg/xtensa/test_sext.S
new file mode 100644
index 0000000000..04dc6500c1
--- /dev/null
+++ b/tests/tcg/xtensa/test_sext.S
@@ -0,0 +1,69 @@
+.include "macros.inc"
+
+test_suite sext
+
+test sext
+ movi a2, 0xffffff5a
+ movi a3, 0x0000005a
+ sext a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0x000000a5
+ movi a3, 0xffffffa5
+ sext a4, a2, 7
+ assert eq, a3, a4
+
+ movi a2, 0xfffffaa5
+ movi a3, 0x000000a5
+ sext a4, a2, 8
+ assert eq, a3, a4
+
+ movi a2, 0x0000055a
+ movi a3, 0xffffff5a
+ sext a4, a2, 8
+ assert eq, a3, a4
+
+ movi a2, 0xffff5a5a
+ movi a3, 0x00005a5a
+ sext a4, a2, 15
+ assert eq, a3, a4
+
+ movi a2, 0x0000a5a5
+ movi a3, 0xffffa5a5
+ sext a4, a2, 15
+ assert eq, a3, a4
+
+ movi a2, 0x00055a5a
+ movi a3, 0xffff5a5a
+ sext a4, a2, 16
+ assert eq, a3, a4
+
+ movi a2, 0x000aa5a5
+ movi a3, 0x0000a5a5
+ sext a4, a2, 16
+ assert eq, a3, a4
+
+ movi a2, 0x005a5a5a
+ movi a3, 0xffda5a5a
+ sext a4, a2, 22
+ assert eq, a3, a4
+
+ movi a2, 0xffa5a5a5
+ movi a3, 0x0025a5a5
+ sext a4, a2, 22
+ assert eq, a3, a4
+test_end
+
+test sext_same_rs
+ movi a2, 0xffffff5a
+ movi a3, 0x0000005a
+ sext a2, a2, 7
+ assert eq, a3, a2
+
+ movi a2, 0x000000a5
+ movi a3, 0xffffffa5
+ sext a2, a2, 7
+ assert eq, a3, a2
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_shift.S b/tests/tcg/xtensa/test_shift.S
new file mode 100644
index 0000000000..a8e43645b7
--- /dev/null
+++ b/tests/tcg/xtensa/test_shift.S
@@ -0,0 +1,206 @@
+.include "macros.inc"
+
+test_suite shift
+
+.macro test_shift prefix, dst, src, v, imm
+ \prefix\()_set \dst, \src, \v, \imm
+ \prefix\()_ver \dst, \v, \imm
+.endm
+
+.macro test_shift_sd prefix, v, imm
+ test_shift \prefix, a3, a2, \v, \imm
+ test_shift \prefix, a2, a2, \v, \imm
+.endm
+
+.macro tests_imm_shift prefix, v
+ test_shift_sd \prefix, \v, 1
+ test_shift_sd \prefix, \v, 2
+ test_shift_sd \prefix, \v, 7
+ test_shift_sd \prefix, \v, 8
+ test_shift_sd \prefix, \v, 15
+ test_shift_sd \prefix, \v, 16
+ test_shift_sd \prefix, \v, 31
+.endm
+
+.macro tests_shift prefix, v
+ test_shift_sd \prefix, \v, 0
+ tests_imm_shift \prefix, \v
+ test_shift_sd \prefix, \v, 32
+.endm
+
+
+.macro slli_set dst, src, v, imm
+ movi \src, \v
+ slli \dst, \src, \imm
+.endm
+
+.macro slli_ver dst, v, imm
+ mov a2, \dst
+ movi a3, ((\v) << (\imm)) & 0xffffffff
+ assert eq, a2, a3
+.endm
+
+test slli
+ tests_imm_shift slli, 0xa3c51249
+test_end
+
+
+.macro srai_set dst, src, v, imm
+ movi \src, \v
+ srai \dst, \src, \imm
+.endm
+
+.macro srai_ver dst, v, imm
+ mov a2, \dst
+ .if (\imm)
+ movi a3, (((\v) >> (\imm)) & 0xffffffff) | \
+ ~((((\v) & 0x80000000) >> ((\imm) - 1)) - 1)
+ .else
+ movi a3, \v
+ .endif
+ assert eq, a2, a3
+.endm
+
+test srai
+ tests_imm_shift srai, 0x49a3c512
+ tests_imm_shift srai, 0xa3c51249
+test_end
+
+
+.macro srli_set dst, src, v, imm
+ movi \src, \v
+ srli \dst, \src, \imm
+.endm
+
+.macro srli_ver dst, v, imm
+ mov a2, \dst
+ movi a3, (((\v) >> (\imm)) & 0xffffffff)
+ assert eq, a2, a3
+.endm
+
+test srli
+ tests_imm_shift srli, 0x49a3c512
+ tests_imm_shift srli, 0xa3c51249
+test_end
+
+
+.macro sll_set dst, src, v, imm
+ movi a2, \imm
+ ssl a2
+ movi \src, \v
+ sll \dst, \src
+.endm
+
+.macro sll_sar_set dst, src, v, imm
+ movi a2, 32 - \imm
+ wsr a2, sar
+ movi \src, \v
+ sll \dst, \src
+.endm
+
+.macro sll_ver dst, v, imm
+ slli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sll_sar_ver dst, v, imm
+ slli_ver \dst, \v, \imm
+.endm
+
+test sll
+ tests_shift sll, 0xa3c51249
+ tests_shift sll_sar, 0xa3c51249
+test_end
+
+
+.macro srl_set dst, src, v, imm
+ movi a2, \imm
+ ssr a2
+ movi \src, \v
+ srl \dst, \src
+.endm
+
+.macro srl_sar_set dst, src, v, imm
+ movi a2, \imm
+ wsr a2, sar
+ movi \src, \v
+ srl \dst, \src
+.endm
+
+.macro srl_ver dst, v, imm
+ srli_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro srl_sar_ver dst, v, imm
+ srli_ver \dst, \v, \imm
+.endm
+
+test srl
+ tests_shift srl, 0xa3c51249
+ tests_shift srl_sar, 0xa3c51249
+ tests_shift srl, 0x49a3c512
+ tests_shift srl_sar, 0x49a3c512
+test_end
+
+
+.macro sra_set dst, src, v, imm
+ movi a2, \imm
+ ssr a2
+ movi \src, \v
+ sra \dst, \src
+.endm
+
+.macro sra_sar_set dst, src, v, imm
+ movi a2, \imm
+ wsr a2, sar
+ movi \src, \v
+ sra \dst, \src
+.endm
+
+.macro sra_ver dst, v, imm
+ srai_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro sra_sar_ver dst, v, imm
+ srai_ver \dst, \v, \imm
+.endm
+
+test sra
+ tests_shift sra, 0xa3c51249
+ tests_shift sra_sar, 0xa3c51249
+ tests_shift sra, 0x49a3c512
+ tests_shift sra_sar, 0x49a3c512
+test_end
+
+
+.macro src_set dst, src, v, imm
+ movi a2, \imm
+ ssr a2
+ movi \src, (\v) & 0xffffffff
+ movi a4, (\v) >> 32
+ src \dst, a4, \src
+.endm
+
+.macro src_sar_set dst, src, v, imm
+ movi a2, \imm
+ wsr a2, sar
+ movi \src, (\v) & 0xffffffff
+ movi a4, (\v) >> 32
+ src \dst, a4, \src
+.endm
+
+.macro src_ver dst, v, imm
+ src_sar_ver \dst, \v, (\imm) & 0x1f
+.endm
+
+.macro src_sar_ver dst, v, imm
+ mov a2, \dst
+ movi a3, ((\v) >> (\imm)) & 0xffffffff
+ assert eq, a2, a3
+.endm
+
+test src
+ tests_shift src, 0xa3c51249215c3a94
+ tests_shift src_sar, 0xa3c51249215c3a94
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_timer.S b/tests/tcg/xtensa/test_timer.S
new file mode 100644
index 0000000000..1041cc6658
--- /dev/null
+++ b/tests/tcg/xtensa/test_timer.S
@@ -0,0 +1,178 @@
+.include "macros.inc"
+
+test_suite timer
+
+test ccount
+ rsr a3, ccount
+ rsr a4, ccount
+ sub a3, a4, a3
+ assert eqi, a3, 1
+test_end
+
+test ccompare
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare1
+ wsr a2, ccompare2
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsr a2, interrupt
+ assert eqi, a2, 0
+ loop a3, 1f
+ rsr a3, interrupt
+ bnez a3, 2f
+1:
+ test_fail
+2:
+test_end
+
+test ccompare0_interrupt
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare1
+ wsr a2, ccompare2
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+
+ movi a2, 0x40
+ wsr a2, intenable
+ rsil a2, 0
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare1_interrupt
+ set_vector level3, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare0
+ wsr a2, ccompare2
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare1
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+ movi a2, 0x400
+ wsr a2, intenable
+ rsil a2, 2
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+test_end
+
+test ccompare2_interrupt
+ set_vector level5, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare0
+ wsr a2, ccompare1
+
+ movi a3, 20
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare2
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+ movi a2, 0x2000
+ wsr a2, intenable
+ rsil a2, 4
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+test_end
+
+test ccompare_interrupt_masked
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare2
+
+ movi a3, 40
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare1
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+
+ movi a2, 0x40
+ wsr a2, intenable
+ rsil a2, 0
+ loop a3, 1f
+ nop
+1:
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test ccompare_interrupt_masked_waiti
+ set_vector kernel, 2f
+ movi a2, 0
+ wsr a2, intenable
+ rsr a2, interrupt
+ wsr a2, intclear
+ movi a2, 0
+ wsr a2, ccompare2
+
+ movi a3, 40
+ rsr a2, ccount
+ addi a2, a2, 20
+ wsr a2, ccompare1
+ addi a2, a2, 20
+ wsr a2, ccompare0
+ rsync
+ rsr a2, interrupt
+ assert eqi, a2, 0
+
+ movi a2, 0x40
+ wsr a2, intenable
+ waiti 0
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 4 /* LEVEL1_INTERRUPT_CAUSE */
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/test_windowed.S b/tests/tcg/xtensa/test_windowed.S
new file mode 100644
index 0000000000..cb2d39e1fd
--- /dev/null
+++ b/tests/tcg/xtensa/test_windowed.S
@@ -0,0 +1,302 @@
+.include "macros.inc"
+
+test_suite windowed
+
+.altmacro
+
+.macro reset_window start
+ movi a2, 0xff
+ wsr a2, windowstart
+ rsync
+ movi a2, 0
+ wsr a2, windowbase
+ rsync
+ movi a2, \start
+ wsr a2, windowstart
+ rsync
+.endm
+
+.macro overflow_test shift, window, probe_ok, probe_ex
+ set_vector window_overflow_4, 0
+ set_vector window_overflow_8, 0
+ set_vector window_overflow_12, 0
+
+ movi a2, 1 | (((1 << ((\window) / 4)) | 1) << ((\shift) / 4))
+ wsr a2, windowstart
+ reset_ps
+
+ mov a2, a\probe_ok
+ set_vector window_overflow_\window, 10f
+1:
+ mov a2, a\probe_ex
+ test_fail
+10:
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ movi a2, 2f
+ wsr a2, epc1
+
+ rsr a2, windowbase
+ movi a3, (\shift) / 4
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4001f
+ assert eq, a2, a3
+ rfwo
+ test_fail
+2:
+ rsr a2, windowbase
+ assert eqi, a2, 0
+ rsr a2, windowstart
+ movi a3, 1 | ((1 << ((\window) / 4)) << ((\shift) / 4))
+ assert eq, a2, a3
+ rsr a2, ps
+ movi a3, 0x4000f
+ assert eq, a2, a3
+.endm
+
+.macro overflow_tests shift, window, probe
+ .if \probe < 15
+ overflow_test \shift, \window, %((\shift) - 1), \probe
+ overflow_tests \shift, \window, %((\probe) + 1)
+ .endif
+.endm
+
+.macro all_overflow_tests
+ .irp shift, 4, 8, 12
+ .irp window, 4, 8, 12
+ overflow_tests \shift, \window, \shift
+ .endr
+ .endr
+.endm
+
+test overflow
+ all_overflow_tests
+test_end
+
+
+.macro underflow_test window
+ set_vector window_underflow_4, 0
+ set_vector window_underflow_8, 0
+ set_vector window_underflow_12, 0
+
+ set_vector window_underflow_\window, 10f
+
+ reset_window 1
+ reset_ps
+
+ ssai 2
+ movi a2, 2f
+ slli a2, a2, 2
+ movi a3, (\window) / 4
+ src a0, a3, a2
+1:
+ retw
+ test_fail
+10:
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+ movi a2, 2f
+ wsr a2, epc1
+
+ rsr a2, ps
+ movi a3, 0x4001f
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, 8 - ((\window) / 4)
+ rsr a2, windowstart
+ assert eqi, a2, 1
+ rfwu
+2:
+ rsr a2, ps
+ movi a3, 0x4000f
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, 0
+ rsr a2, windowstart
+ assert bsi, a2, 0
+ assert bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test underflow
+ set_vector window_overflow_4, 0
+ set_vector window_overflow_8, 0
+ set_vector window_overflow_12, 0
+
+ underflow_test 4
+ underflow_test 8
+ underflow_test 12
+test_end
+
+
+.macro retw_test window
+ reset_window %(1 | (1 << (8 - (\window) / 4)))
+ reset_ps
+
+ ssai 2
+ movi a2, 1f
+ slli a2, a2, 2
+ movi a3, (\window) / 4
+ src a0, a3, a2
+ retw
+ test_fail
+1:
+ rsr a2, ps
+ movi a3, 0x4000f
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, 8 - ((\window) / 4)
+ rsr a2, windowstart
+ assert bci, a2, 0
+ assert bsi, a2, 8 - ((\window) / 4)
+.endm
+
+test retw
+ set_vector window_underflow_4, 0
+ set_vector window_underflow_8, 0
+ set_vector window_underflow_12, 0
+
+ retw_test 4
+ retw_test 8
+ retw_test 12
+test_end
+
+test movsp
+ set_vector kernel, 2f
+
+ reset_window 1
+ reset_ps
+1:
+ movsp a2, a3
+ test_fail
+2:
+ rsr a2, exccause
+ assert eqi, a2, 5
+ rsr a2, epc1
+ movi a3, 1b
+ assert eq, a2, a3
+
+ set_vector kernel, 0
+
+ reset_window 0x81
+ reset_ps
+
+ movsp a2, a3
+test_end
+
+test rotw
+ reset_window 0x4b
+ reset_ps
+
+ movi a3, 0x10
+
+ rotw 1
+ rsr a2, windowbase
+ assert eqi, a2, 1
+ movi a3, 0x11
+ movi a7, 0x12
+
+ rotw 2
+ rsr a2, windowbase
+ assert eqi, a2, 3
+ movi a3, 0x13
+ movi a7, 0x14
+ movi a11, 0x15
+
+ rotw 3
+ rsr a2, windowbase
+ assert eqi, a2, 6
+ movi a3, 0x16
+ movi a7, 0x17
+
+ movi a2, 0x44
+ wsr a2, windowstart
+ rsync
+
+ movi a2, 0x10
+ assert eq, a2, a11
+ movi a11, 0x18
+ movi a2, 0x11
+ assert eq, a2, a15
+ movi a15, 0x19
+
+ rotw 4
+ movi a2, 0x12
+ assert eq, a2, a3
+ movi a2, 0x13
+ assert eq, a2, a7
+ movi a2, 0x14
+ assert eq, a2, a11
+ movi a2, 0x15
+ assert eq, a2, a15
+
+ movi a2, 0x5
+ wsr a2, windowstart
+ rsync
+
+ rotw -2
+ movi a2, 0x18
+ assert eq, a2, a3
+ movi a2, 0x19
+ assert eq, a2, a7
+test_end
+
+.macro callw_test window
+ call\window 2f
+1:
+ test_fail
+ .align 4
+2:
+ rsr a2, windowbase
+ assert eqi, a2, 0
+ rsr a2, ps
+ movi a3, 0x4000f | ((\window) << 14)
+ assert eq, a2, a3
+ movi a2, 1b
+ slli a2, a2, 2
+ ssai 2
+ movi a3, (\window) / 4
+ src a2, a3, a2
+ assert eq, a2, a\window
+.endm
+
+test callw
+ reset_window 0x1
+ reset_ps
+
+ callw_test 4
+ callw_test 8
+ callw_test 12
+test_end
+
+
+.macro entry_test window
+ reset_window 0x1
+ reset_ps
+ movi a2, 0x4000f | ((\window) << 14)
+ wsr a2, ps
+ isync
+ movi a3, 0x12345678
+ j 1f
+ .align 4
+1:
+ entry a3, 0x5678
+ movi a2, 0x12340000
+ assert eq, a2, a3
+ rsr a2, windowbase
+ assert eqi, a2, (\window) / 4
+ rsr a2, windowstart
+ movi a3, 1 | (1 << ((\window) / 4))
+ assert eq, a2, a3
+ rotw -(\window) / 4
+.endm
+
+test entry
+ entry_test 4
+ entry_test 8
+ entry_test 12
+test_end
+
+test_suite_end
diff --git a/tests/tcg/xtensa/vectors.S b/tests/tcg/xtensa/vectors.S
new file mode 100644
index 0000000000..265a181239
--- /dev/null
+++ b/tests/tcg/xtensa/vectors.S
@@ -0,0 +1,39 @@
+.macro vector name
+
+.section .vector.\name
+ j 1f
+.section .vector.\name\().text
+1:
+ wsr a2, excsave1
+ movi a2, handler_\name
+ l32i a2, a2, 0
+ beqz a2, 1f
+ jx a2
+1:
+ movi a3, 1b
+ movi a2, 1
+ simcall
+
+.align 4
+.global handler_\name
+handler_\name\(): .word 0
+
+.endm
+
+vector window_overflow_4
+vector window_overflow_8
+vector window_overflow_12
+vector window_underflow_4
+vector window_underflow_8
+vector window_underflow_12
+
+vector level2
+vector level3
+vector level4
+vector level5
+vector level6
+vector level7
+
+vector kernel
+vector user
+vector double