blob: 991d1679b302a1f9281907e902bf1478145390ce [file] [log] [blame]
# 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