295 lines
5.1 KiB
C++
295 lines
5.1 KiB
C++
# 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
|