aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/opencores/aemb/sw/c
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-01-23 16:10:22 -0800
committerMartin Braun <martin.braun@ettus.com>2020-01-28 09:35:36 -0800
commitbafa9d95453387814ef25e6b6256ba8db2df612f (patch)
tree39ba24b5b67072d354775272e687796bb511848d /fpga/usrp2/opencores/aemb/sw/c
parent3075b981503002df3115d5f1d0b97d2619ba30f2 (diff)
downloaduhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce the size of the repository. However, over the last half-decade, the split between the repositories has proven more burdensome than it has been helpful. By merging the FPGA code back, it will be possible to create atomic commits that touch both FPGA and UHD codebases. Continuous integration testing is also simplified by merging the repositories, because it was previously difficult to automatically derive the correct UHD branch when testing a feature branch on the FPGA repository. This commit also updates the license files and paths therein. We are therefore merging the repositories again. Future development for FPGA code will happen in the same repository as the UHD host code and MPM code. == Original Codebase and Rebasing == The original FPGA repository will be hosted for the foreseeable future at its original local location: https://github.com/EttusResearch/fpga/ It can be used for bisecting, reference, and a more detailed history. The final commit from said repository to be merged here is 05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as v4.0.0.0-pre-uhd-merge. If you have changes in the FPGA repository that you want to rebase onto the UHD repository, simply run the following commands: - Create a directory to store patches (this should be an empty directory): mkdir ~/patches - Now make sure that your FPGA codebase is based on the same state as the code that was merged: cd src/fpga # Or wherever your FPGA code is stored git rebase v4.0.0.0-pre-uhd-merge Note: The rebase command may look slightly different depending on what exactly you're trying to rebase. - Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge: git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches Note: Make sure that only patches are stored in your output directory. It should otherwise be empty. Make sure that you picked the correct range of commits, and only commits you wanted to rebase were exported as patch files. - Go to the UHD repository and apply the patches: cd src/uhd # Or wherever your UHD repository is stored git am --directory fpga ~/patches/* rm -rf ~/patches # This is for cleanup == Contributors == The following people have contributed mainly to these files (this list is not complete): Co-authored-by: Alex Williams <alex.williams@ni.com> Co-authored-by: Andrej Rode <andrej.rode@ettus.com> Co-authored-by: Ashish Chaudhari <ashish@ettus.com> Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Derek Kozel <derek.kozel@ettus.com> Co-authored-by: EJ Kreinar <ej@he360.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Ian Buckley <ian.buckley@gmail.com> Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Jon Kiser <jon.kiser@ni.com> Co-authored-by: Josh Blum <josh@joshknows.com> Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Matt Ettus <matt@ettus.com> Co-authored-by: Michael West <michael.west@ettus.com> Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com> Co-authored-by: Nick Foster <nick@ettus.com> Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Paul David <paul.david@ettus.com> Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com> Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com> Co-authored-by: Sylvain Munaut <tnt@246tNt.com> Co-authored-by: Trung Tran <trung.tran@ettus.com> Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com> Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp2/opencores/aemb/sw/c')
-rw-r--r--fpga/usrp2/opencores/aemb/sw/c/aeMB_testbench.c385
-rw-r--r--fpga/usrp2/opencores/aemb/sw/c/endian-test.c86
-rw-r--r--fpga/usrp2/opencores/aemb/sw/c/libaemb.h218
3 files changed, 689 insertions, 0 deletions
diff --git a/fpga/usrp2/opencores/aemb/sw/c/aeMB_testbench.c b/fpga/usrp2/opencores/aemb/sw/c/aeMB_testbench.c
new file mode 100644
index 000000000..c3402e0ef
--- /dev/null
+++ b/fpga/usrp2/opencores/aemb/sw/c/aeMB_testbench.c
@@ -0,0 +1,385 @@
+/* $Id: aeMB_testbench.c,v 1.14 2007/12/28 21:44:04 sybreon Exp $
+**
+** AEMB Function Verification C Testbench
+** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
+**
+** This file is part of AEMB.
+**
+** AEMB 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 3 of the License, or
+** (at your option) any later version.
+**
+** AEMB 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 AEMB. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <malloc.h>
+#include <errno.h>
+#include <reent.h>
+
+#include "libaemb.h"
+
+/**
+ INTERRUPT TEST
+
+ This tests for the following:
+ - Pointer addressing
+ - Interrupt handling
+ */
+
+void __attribute__ ((interrupt_handler)) int_handler();
+volatile int service = 0xDEADDEAD;
+
+void int_service()
+{
+ int* pio = (int*)0xFFFFFFFC;
+ *pio = 0x52544E49; // "INTR"
+ service = 0;
+}
+
+void int_handler()
+{
+ int_service();
+}
+
+/**
+ INTERRUPT TEST ROUTINE
+*/
+int int_test ()
+{
+ // Delay loop until hardware interrupt triggers
+ volatile int i;
+ for (i=0; i < 999; i++) {
+ if (service == 0) return 0;
+ };
+
+ return -1;
+}
+
+/**
+ FIBONACCI TEST
+ http://en.literateprograms.org/Fibonacci_numbers_(C)
+
+ This tests for the following:
+ - Recursion & Iteration
+ - 32/16/8-bit data handling
+*/
+
+unsigned int fib_slow(unsigned int n)
+{
+ return n < 2 ? n : fib_slow(n-1) + fib_slow(n-2);
+}
+
+unsigned int fib_fast(unsigned int n)
+{
+ unsigned int a[3];
+ unsigned int *p=a;
+ unsigned int i;
+
+ for(i=0; i<=n; ++i) {
+ if(i<2) *p=i;
+ else {
+ if(p==a) *p=*(a+1)+*(a+2);
+ else if(p==a+1) *p=*a+*(a+2);
+ else *p=*a+*(a+1);
+ }
+ if(++p>a+2) p=a;
+ }
+
+ return p==a?*(p+2):*(p-1);
+}
+
+int fib_test(int max) {
+ unsigned int n;
+ unsigned int fast, slow;
+ // 32-bit LUT
+ unsigned int fib_lut32[] = {
+ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233
+ };
+ // 16-bit LUT
+ unsigned short fib_lut16[] = {
+ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233
+ };
+ // 8-bit LUT
+ unsigned char fib_lut8[] = {
+ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233
+ };
+
+ for (n=0;n<max;n++) {
+ slow = fib_slow(n);
+ fast = fib_fast(n);
+ if ((slow != fast) ||
+ (fast != fib_lut32[n]) ||
+ (fast != fib_lut16[n]) ||
+ (fast != fib_lut8[n])) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ EUCLIDEAN TEST
+ http://en.literateprograms.org/Euclidean_algorithm_(C)
+
+ This tests for the following:
+ - Modulo arithmetic
+ - Goto
+*/
+
+int euclid_gcd(int a, int b) {
+ if (b > a) goto b_larger;
+ while (1) {
+ a = a % b;
+ if (a == 0) return b;
+ b_larger:
+ b = b % a;
+ if (b == 0) return a;
+ }
+}
+
+int euclid_test(int max)
+{
+ int n;
+ int euclid;
+ // Random Numbers
+ int euclid_a[] = {
+ 1804289383, 1681692777, 1957747793, 719885386, 596516649,
+ 1025202362, 783368690, 2044897763, 1365180540, 304089172,
+ 35005211, 294702567, 336465782, 278722862
+ };
+ int euclid_b[] = {
+ 846930886, 1714636915, 424238335, 1649760492, 1189641421,
+ 1350490027, 1102520059, 1967513926, 1540383426, 1303455736,
+ 521595368, 1726956429, 861021530, 233665123
+ };
+
+ // GCD
+ int euclid_lut[] = {
+ 1, 1, 1, 2, 1, 1, 1, 1, 6, 4, 1, 3, 2, 1
+ };
+
+ for (n=0;n<max;n++) {
+ euclid = euclid_gcd(euclid_a[n],euclid_b[n]);
+ if (euclid != euclid_lut[n]) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ NEWTON-RHAPSON
+ http://en.literateprograms.org/Newton-Raphson's_method_for_root_finding_(C)
+
+ This tests for the following:
+ - Multiplication & Division
+ - Floating point arithmetic
+ - Integer to Float conversion
+*/
+
+float newton_sqrt(float n)
+{
+ float x = 0.0;
+ float xn = 0.0;
+ int iters = 0;
+ int i;
+ for (i = 0; i <= (int)n; ++i)
+ {
+ float val = i*i-n;
+ if (val == 0.0)
+ return i;
+ if (val > 0.0)
+ {
+ xn = (i+(i-1))/2.0;
+ break;
+ }
+ }
+ while (!(iters++ >= 100
+ || x == xn))
+ {
+ x = xn;
+ xn = x - (x * x - n) / (2 * x);
+ }
+ return xn;
+}
+
+int newton_test (int max) {
+ int n;
+ float newt;
+ // 32-bit LUT
+ float newt_lut[] = {
+ 0.000000000000000000000000,
+ 1.000000000000000000000000,
+ 1.414213538169860839843750,
+ 1.732050776481628417968750,
+ 2.000000000000000000000000,
+ 2.236068010330200195312500,
+ 2.449489831924438476562500,
+ 2.645751237869262695312500,
+ 2.828427076339721679687500,
+ 3.000000000000000000000000,
+ 3.162277698516845703125000,
+ 3.316624879837036132812500,
+ 3.464101552963256835937500,
+ 3.605551242828369140625000,
+ 3.741657495498657226562500
+ };
+
+ for (n=0;n<max;n++) {
+ newt = newton_sqrt(n);
+ if (newt != newt_lut[n]) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ FSL TEST ROUTINE
+*/
+
+int fsl_test ()
+{
+ // TEST FSL1 ONLY
+ int FSL = 0xCAFEF00D;
+
+ asm ("PUT %0, RFSL1" :: "r"(FSL));
+ asm ("GET %0, RFSL1" : "=r"(FSL));
+
+ if (FSL != 0x01) return -1;
+
+ asm ("PUT %0, RFSL31" :: "r"(FSL));
+ asm ("GET %0, RFSL31" : "=r"(FSL));
+
+ if (FSL != 0x1F) return -1;
+
+ return 0;
+}
+
+// static int errnum;
+/*
+int *__errno ()
+{
+ return &_REENT->_errno;
+ // return &errnum;
+}
+*/
+
+int malloc_test()
+{
+ void *alloc;
+
+ alloc = (void *)malloc(256); // allocate 32 bytes
+
+ if (alloc == NULL)
+ return -1;
+ else
+ return (int) alloc;
+}
+
+/**
+ MAIN TEST PROGRAMME
+
+ This is the main test procedure. It will output signals onto the
+ MPI port that is checked by the testbench.
+ */
+
+int main ()
+{
+ // Message Passing Port
+ int* mpi = (int*)0xFFFFFFFF;
+
+ // Number of each test to run
+ int max = 10;
+
+ // lock T0 if it's multi-threaded
+ /*
+ if ((aemb_isthreaded() == 0) && (aemb_isthread1() != 0)) {
+ while (1) {
+ asm volatile ("nop;");
+ }
+ }
+ */
+
+ // Enable Global Interrupts
+ aemb_enable_interrupt();
+
+ // INT TEST
+ //if (int_test() == -1) { *mpi = 0x4641494C; }
+
+ // TEST MALLOC
+ if (malloc_test() == -1) { *mpi = 0x4641494C; }
+
+ // FSL TEST
+ //if (fsl_test() == -1) { *mpi = 0x4641494C; }
+
+ // Fibonacci Test
+ if (fib_test(max) == -1) { *mpi = 0x4641494C; }
+
+ // Euclid Test
+ if (euclid_test(max) == -1) { *mpi = 0x4641494C; }
+
+ // Newton-Rhapson Test
+ if (newton_test(max) == -1) { *mpi = 0x4641494C; }
+
+ // Disable Global Interrupts
+ aemb_disable_interrupt();
+
+ // ALL PASSED
+ return 0;
+}
+
+/*
+ HISTORY
+ $Log: aeMB_testbench.c,v $
+ Revision 1.14 2007/12/28 21:44:04 sybreon
+ Added malloc() test
+
+ Revision 1.13 2007/12/11 00:44:31 sybreon
+ Modified for AEMB2
+
+ Revision 1.12 2007/11/18 19:41:45 sybreon
+ Minor simulation fixes.
+
+ Revision 1.11 2007/11/14 23:41:06 sybreon
+ Fixed minor interrupt test typo.
+
+ Revision 1.10 2007/11/14 22:12:02 sybreon
+ Added interrupt test routine.
+
+ Revision 1.9 2007/11/09 20:51:53 sybreon
+ Added GET/PUT support through a FSL bus.
+
+ Revision 1.8 2007/11/03 08:40:18 sybreon
+ Minor code cleanup.
+
+ Revision 1.7 2007/11/02 18:32:19 sybreon
+ Enable MSR_IE with software.
+
+ Revision 1.6 2007/04/30 15:57:10 sybreon
+ Removed byte acrobatics.
+
+ Revision 1.5 2007/04/27 15:17:59 sybreon
+ Added code documentation.
+ Added new tests that test floating point, modulo arithmetic and multiplication/division.
+
+ Revision 1.4 2007/04/25 22:15:05 sybreon
+ Added support for 8-bit and 16-bit data types.
+
+ Revision 1.3 2007/04/04 14:09:04 sybreon
+ Added initial interrupt/exception support.
+
+ Revision 1.2 2007/04/04 06:07:45 sybreon
+ Fixed C code bug which passes the test
+
+ Revision 1.1 2007/03/09 17:41:57 sybreon
+ initial import
+*/
diff --git a/fpga/usrp2/opencores/aemb/sw/c/endian-test.c b/fpga/usrp2/opencores/aemb/sw/c/endian-test.c
new file mode 100644
index 000000000..b585f7a30
--- /dev/null
+++ b/fpga/usrp2/opencores/aemb/sw/c/endian-test.c
@@ -0,0 +1,86 @@
+
+#include "memory_map.h"
+
+int main() {
+ char *p = (char *)0x4000;
+ short *q = (short *)0x5000;
+ int *r= (int *)0x6000;
+
+ int *output = (int *)0x7000;
+
+ char s;
+ short t;
+ int u;
+
+ // Write
+ // Bytes
+ *p = (char)1;
+ p++;
+ *p = (char)2;
+ p++;
+ *p = (char)3;
+ p++;
+ *p = (char)4;
+ p++;
+ *p = (char)5;
+
+ // Words
+ *q = (short) 0x1112;
+ q++;
+ *q = (short) 0x1314;
+ q++;
+ *q = (short) 0x1516;
+
+ // Double Words
+ *r = 0x21222324;
+ r++;
+ *r = 0x25262728;
+ r++;
+ *r = 0x292a2b2c;
+
+
+ // Read
+ p = (char *)0x6000;
+ s = *p;
+ if(s == 0x21)
+ *output = 0x53534150; // PASS
+ else
+ *output = 0x4C494146; // FAIL
+
+ p = (char *)0x6001;
+ s = *p;
+ if(s == 0x22)
+ *output = 0x53534150; // PASS
+ else
+ *output = 0x4C494146; // FAIL
+
+ p = (char *)0x6002;
+ s = *p;
+ if(s == 0x23)
+ *output = 0x53534150; // PASS
+ else
+ *output = 0x4C494146; // FAIL
+
+
+ p = (char *)0x6003;
+ s = *p;
+ if(s == 0x24)
+ *output = 0x53534150; // PASS
+ else
+ *output = 0x4C494146; // FAIL
+
+ q = (short *)0x4000;
+ t = *q;
+ if(t == 0x0102)
+ *output = 0x53534150; // PASS
+ else
+ *output = 0x4C494146; // FAIL
+
+ r = (int *)0x4000;
+ u = *r;
+ if(u == 0x01020304)
+ *output = 0x53534150; // PASS
+ else
+ *output = 0x4C494146; // FAIL
+
+}
diff --git a/fpga/usrp2/opencores/aemb/sw/c/libaemb.h b/fpga/usrp2/opencores/aemb/sw/c/libaemb.h
new file mode 100644
index 000000000..329a327a1
--- /dev/null
+++ b/fpga/usrp2/opencores/aemb/sw/c/libaemb.h
@@ -0,0 +1,218 @@
+/* $Id: libaemb.h,v 1.3 2007/12/16 03:26:37 sybreon Exp $
+**
+** AEMB2 CUSTOM LIBRARY
+**
+** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
+**
+** This file is part of AEMB.
+**
+** AEMB is free software: you can redistribute it and/or modify it
+** under the terms of the GNU Lesser General Public License as
+** published by the Free Software Foundation, either version 3 of the
+** License, or (at your option) any later version.
+**
+** AEMB 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 Lesser General
+** Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public
+** License along with AEMB. If not, see <http:**www.gnu.org/licenses/>.
+*/
+
+#ifndef LIBAEMB_H
+#define LIBAEMB_H
+
+#define AEMB_TXE 0x0100
+#define AEMB_TXP 0x0400
+#define AEMB_TX0 0x0300
+#define AEMB_TX1 0x0700
+#define AEMB_MSK 0x0F00
+
+#define AEMB_BIP 0x0008
+#define AEMB_CCC 0x0004
+#define AEMB_ITE 0x0002
+#define AEMB_BLE 0x0001
+
+
+// Linker symbols
+extern void* _STACK_SIZE;
+extern void* _stack_end;
+
+
+void aemb_hook_init () asm ("_program_init");
+void aemb_hook_clean () asm ("_program_clean");
+
+inline void aemb_enable_interrupt ();
+inline void aemb_disable_interrupt ();
+inline int aemb_isthread1();
+inline int aemb_isthread0();
+inline int aemb_isthreaded();
+
+/*!
+* Assembly macro to enable MSR_IE
+*/
+void aemb_enable_interrupt ()
+{
+ int msr, tmp;
+ asm volatile ("mfs %0, rmsr;"
+ "ori %1, %0, 0x02;"
+ "mts rmsr, %1;"
+ : "=r"(msr)
+ : "r" (tmp)
+ );
+}
+
+/*!
+* Assembly macro to disable MSR_IE
+*/
+void aemb_disable_interrupt ()
+{
+ int msr, tmp;
+ asm volatile ("mfs %0, rmsr;"
+ "andi %1, %0, 0xFD;"
+ "mts rmsr, %1;"
+ : "=r"(msr)
+ : "r" (tmp)
+ );
+}
+
+/*!
+* Bootstrap Hook Override
+*/
+
+void aemb_hook_init ()
+{
+ int msr, tmp;
+ int stk_end, stk_siz;
+
+ /*
+ // Check to see if hardware threads are enabled
+ if (((msr & AEMB_TXE) != AEMB_TXE) ||
+ // Check to see if second thread is started
+ ((msr & AEMB_TX1) == AEMB_TX1)) return;
+ */
+ //return;
+ asm volatile ("mfs %0, rmsr;"
+ // Check for BIP
+ "andi %1, %0, %5;"
+ "xori %1, %1, %5;"
+ "beqi %1, 44;"
+
+ // Check for TXE
+ "andi %1, %0, %2;"
+ "xori %1, %1, %2;"
+ "bnei %1, 36;"
+
+ // Check for TX1
+ "andi %1, %0, %3;"
+ "xori %1, %1, %3;"
+ "beqi %1, 20;"
+
+ // reallocate stack pointer for T0
+ "ori %1, r0, %4;"
+ "sra %1, %1;"
+ "rsubk r1, %1, r1;"
+
+ // reboot the machine
+ //"brki r0, _crtinit;"
+ "brid 0;"
+ "nop;"
+
+ // clear BIP
+ "andni %1, %0, %5;"
+ "mts rmsr, %1;"
+
+ :"=r"(msr), "=r"(tmp)
+ :"i"(AEMB_TXE), "i"(AEMB_TX1), "i"(&_STACK_SIZE), "i"(AEMB_BIP)
+ );
+
+}
+
+/*!
+ Undo the changes made by programme init
+*/
+
+void aemb_hook_clean ()
+{
+ int msr, tmp;
+ int stk_end, stk_siz;
+
+ /*
+ // Check to see if hardware threads are enabled
+ if (((msr & AEMB_TXE) != AEMB_TXE) ||
+ // Check to see if second thread is started
+ ((msr & AEMB_TX1) == AEMB_TX1)) return;
+ */
+ return;
+ asm volatile ("mfs %0, rmsr;"
+ "andi %1, %0, %2;"
+ "xori %1, %1, %2;"
+ "bnei %1, 28;"
+ "andi %1, %0, %3;"
+ "xori %1, %1, %3;"
+ "beqi %1, 16;"
+
+ // reallocate stack pointer for T0
+ "ori %1, r0, %4;"
+ "sra %1, %1;"
+ "addk r1, %1, r1;"
+
+ :"=r"(msr), "=r"(tmp)
+ :"i"(AEMB_TXE), "i"(AEMB_TX1), "i"(&_STACK_SIZE)
+ );
+
+
+}
+
+/* Checks if it's T1, and returns 0 if true */
+
+int aemb_isthread1 ()
+{
+ int msr, tmp, res;
+ asm volatile ("mfs %0, rmsr;"
+ "andi %1, %0, %3;"
+ "xori %1, %1, %3;"
+ :"=r"(msr), "=r"(tmp)
+ :"i"(AEMB_TXE), "i"(AEMB_TXP)
+ );
+ return tmp;
+}
+
+/* Checks if it's T0, and returns 0 if true */
+
+int aemb_isthread0 ()
+{
+ int msr, tmp, res;
+ asm volatile ("mfs %0, rmsr;"
+ "andi %1, %0, %3;"
+ "xori %1, %1, %2;"
+ :"=r"(msr), "=r"(tmp)
+ :"i"(AEMB_TXP), "i"(AEMB_MSK)
+ );
+ return tmp;
+}
+
+/* Checks if TXE is available, and returns 0 if true */
+
+int aemb_isthreaded ()
+{
+ int msr, tmp, res;
+ asm volatile ("mfs %0, rmsr;"
+ "andi %1, %0, %2;"
+ "xori %1, %1, %2;"
+ :"=r"(msr), "=r"(tmp)
+ :"i"(AEMB_TXE), "i"(AEMB_MSK)
+ );
+ return tmp;
+}
+
+#endif
+
+/* $Log: libaemb.h,v $
+/* Revision 1.3 2007/12/16 03:26:37 sybreon
+/* Made T0 loop.
+/*
+/* Revision 1.1 2007/12/11 00:44:04 sybreon
+/* initial import
+/* */