summaryrefslogtreecommitdiff
path: root/sim/testsuite/bfin/testutils.inc
diff options
context:
space:
mode:
Diffstat (limited to 'sim/testsuite/bfin/testutils.inc')
-rw-r--r--sim/testsuite/bfin/testutils.inc295
1 files changed, 295 insertions, 0 deletions
diff --git a/sim/testsuite/bfin/testutils.inc b/sim/testsuite/bfin/testutils.inc
new file mode 100644
index 00000000000..991d1679b30
--- /dev/null
+++ b/sim/testsuite/bfin/testutils.inc
@@ -0,0 +1,295 @@
+# R0 and P0 are used as tmps, consider them call clobbered by these macros.
+
+# To build for hardware, use:
+# bfin-linux-uclibc-gcc -nostdlib -g -Wa,--defsym,BFIN_HOST=1 foo.s
+
+# MACRO: start
+# All assembler tests should start with a call to "start"
+ .macro start
+ .text
+ # Pad with EMUEXCPT to make sure "jump to 0" always fails
+__panic:
+ .rep 0xf
+ .word 0x0025
+ .endr
+ abort;
+ jump __panic;
+
+ .global __pass
+__pass:
+ write 1, _passmsg, 5
+ exit 0
+.ifdef BFIN_JTAG
+__emu_out:
+ /* DBGSTAT */
+ imm32 P0 0xFFE05008;
+
+1: R7 = [P0];
+ CC = BITTST (R7,0);
+ IF CC JUMP 1b;
+
+ EMUDAT = R0;
+ RTS;
+.endif
+ .global __fail
+__fail:
+.ifndef BFIN_HOST
+ P0.H = _rets;
+ P0.L = _rets;
+ R0 = RETS;
+ R0 += -4;
+ P1 = 8;
+ R2 = '9';
+ LSETUP (1f, 3f) LC0 = P1;
+1:
+ R1 = R0;
+ R1 >>= 28;
+ R1 += 0x30;
+ CC = R2 < R1;
+ IF !CC jump 2f;
+ R1 += 7;
+2:
+ B[P0++] = R1;
+3:
+ R0 <<= 4;
+
+ write 1, _failmsg, 22
+.else
+ write 1, _failmsg, 5
+.endif
+ exit 1
+
+.ifndef BFIN_HOST
+ .data
+_failmsg:
+ .ascii "fail at PC=0x"
+_rets:
+ .ascii "12345678\n"
+_passmsg:
+ .ascii "pass\n"
+ .align 4
+_params:
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+
+ .text
+ .global __start
+__start:
+.else
+.global ___uClibc_main;
+___uClibc_main:
+.global _main;
+_main:
+.endif
+ .endm
+
+# MACRO: system_call
+# Make a libgloss/Linux system call
+ .macro system_call nr:req
+ P0 = \nr (X);
+ EXCPT 0;
+ .endm
+
+# MACRO: exit
+# Quit the current test
+ .macro exit rc:req
+ R0 = \rc (X);
+.ifndef BFIN_HOST
+ P0.H = _params;
+ P0.L = _params;
+ [P0] = R0;
+ R0 = P0;
+.endif
+ system_call 1
+ .endm
+
+# MACRO: pass
+# Write 'pass' to stdout via syscalls and quit;
+# meant for non-OS operating environments
+ .macro pass
+ CALL __pass;
+ .endm
+
+# MACRO: fail
+# Write 'fail' to stdout via syscalls and quit;
+# meant for non-OS operating environments
+ .macro fail
+ CALL __fail;
+ .endm
+
+# MACRO: write
+# Just like the write() C function; uses system calls
+ .macro write fd:req, buf:req, count:req
+.ifndef BFIN_HOST
+ P0.H = _params;
+ P0.L = _params;
+ R0 = \fd (X);
+ [P0] = R0;
+ R0.H = \buf;
+ R0.L = \buf;
+ [P0 + 4] = R0;
+ R0 = \count (X);
+ [P0 + 8] = R0;
+ R0 = P0;
+ system_call 5
+.endif
+ .endm
+
+# MACRO: outc_str
+# Output a string using the debug OUTC insn
+ .macro outc_str ch:req, more:vararg
+ OUTC \ch;
+ .ifnb \more
+ outc_str \more
+ .endif
+ .endm
+
+# MACRO: dbg_pass
+# Write 'pass' to stdout and quit (all via debug insns);
+# meant for OS operating environments
+ .macro dbg_pass
+.ifdef BFIN_JTAG
+ R0 = 6;
+ CALL __emu_out;
+ R0.L = 0x6170; /* 'p'=0x70 'a'=0x70 */
+ R0.H = 0x7373; /* 's'=0x73 */
+ CALL __emu_out;
+
+ R0.L = 0x0A; /* newline */
+ R0.H = 0x0000;
+ CALL __emu_out;
+1:
+ EMUEXCPT;
+ JUMP 1b;
+.else
+ outc_str 'p', 'a', 's', 's', '\n'
+ HLT;
+.endif
+ .endm
+
+# MACRO: dbg_fail
+# Write 'fail' to stdout and quit (all via debug insns);
+# meant for OS operating environments
+ .macro dbg_fail
+.ifdef BFIN_JTAG
+ R0 = 6;
+ CALL __emu_out;
+ R0.L = 0x6166; /* 'f'=0x66 'a'=0x61 */
+ R0.H = 0x6c69; /* 'i'=0x69 'l'=0x6c */
+ CALL __emu_out;
+
+ R0.L = 0x0A; /* newline */
+ R0.H = 0x0000;
+ CALL __emu_out;
+1:
+ EMUEXCPT;
+ JUMP 1b;
+.else
+ outc_str 'f', 'a', 'i', 'l', '\n'
+.endif
+ ABORT;
+ .endm
+
+# MACRO: imm32
+# Load a 32bit immediate directly into a register
+ .macro imm32 reg:req, val:req
+ .if (\val) & ~0x7fff
+ \reg\().L = ((\val) & 0xffff);
+ \reg\().H = (((\val) >> 16) & 0xffff);
+ .else
+ \reg = \val;
+ .endif
+ .endm
+
+# MACRO: dmm32
+# Load a 32bit immediate indirectly into a register
+ .macro dmm32 reg:req, val:req
+ [--SP] = R0;
+ imm32 R0, \val
+ \reg = R0;
+ R0 = [SP++];
+ .endm
+
+# MACRO: loadsym
+# Load a symbol directly into a register
+.ifndef BFIN_HOST
+ .macro loadsym reg:req, sym:req, offset=0
+ \reg\().L = (\sym\() + \offset\());
+ \reg\().H = (\sym\() + \offset\());
+ .endm
+.else
+ .macro loadsym reg:req, sym:req, offset=0
+ [--SP] = R0;
+ R0 = [P3 + \sym\()@GOT17M4];
+ .if \offset
+ [--SP] = R1;
+ R1 = \offset\() (Z);
+ R0 = R0 + R1;
+ R1 = [SP++];
+ .endif
+ \reg = R0;
+ R0 = [SP++];
+ .endm
+.endif
+
+# MACRO: CHECKREG
+# Use debug insns to verify the value of a register matches
+ .macro CHECKREG reg:req, val:req
+ DBGAL (\reg, ((\val) & 0xffff));
+ DBGAH (\reg, (((\val) >> 16) & 0xffff));
+ .endm
+
+# internal helper macros; ignore them
+ .macro __init_regs reg:req, max:req, x:req, val:req
+ .ifle (\x - \max)
+ imm32 \reg\()\x, \val
+ .endif
+ .endm
+ .macro _init_regs reg:req, max:req, val:req
+ __init_regs \reg, \max, 0, \val
+ __init_regs \reg, \max, 1, \val
+ __init_regs \reg, \max, 2, \val
+ __init_regs \reg, \max, 3, \val
+ __init_regs \reg, \max, 4, \val
+ __init_regs \reg, \max, 5, \val
+ __init_regs \reg, \max, 6, \val
+ __init_regs \reg, \max, 7, \val
+ .endm
+
+# MACRO: init_r_regs
+# MACRO: init_p_regs
+# MACRO: init_b_regs
+# MACRO: init_i_regs
+# MACRO: init_l_regs
+# MACRO: init_m_regs
+# Set the specified group of regs to the specified value
+ .macro init_r_regs val:req
+ _init_regs R, 7, \val
+ .endm
+ .macro init_p_regs val:req
+ _init_regs P, 5, \val
+ .endm
+ .macro init_b_regs val:req
+ _init_regs B, 3, \val
+ .endm
+ .macro init_i_regs val:req
+ _init_regs I, 3, \val
+ .endm
+ .macro init_l_regs val:req
+ _init_regs L, 3, \val
+ .endm
+ .macro init_m_regs val:req
+ _init_regs M, 3, \val
+ .endm
+
+ // the test framework needs things to be quiet, so don't
+ // print things out by default.
+ .macro _DBG reg:req
+ //DBG \reg;
+ .endm
+
+ .macro _DBGCMPLX reg:req
+ //
+ .endm