| # 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 |