Beispiel #1
0
PcDesc* nmethod::containingPcDescOrNULL(char* pc) {
  // returns PcDesc that is closest one before or == to pc, or NULL if
  // no stored pcDesc exists 
  // called a lot, so watch out for performance bugs
  assert(contains(pc), "nmethod must contain pc into frame");
  int32 offset = pc - insts();
  PcDesc* start = pcs();
  PcDesc* end = pcsEnd() - 1;

  // Skim the cream if only one pcDesc is present.
  if (start == end) return start; 
  assert(start < end, "no PcDescs to search");
  if (start->pc > offset)
    // in prologue; caller has to deal with this
    return NULL;

  // binary search to find approx. location
  PcDesc* middle;
  int32 l = 0, h = end - start;
  do {
    // avoid pointer arithmetic -- gcc uses a division for PcDesc* - PcDesc*
    int32 m = l + (h - l) / 2;
    middle = &start[m];
    if (middle->pc < offset) {
      l = m + 1;
    } else {
      h = m - 1;
    }
  } while (middle->pc != offset && l < h);

  // may not have found exact offset, so search for closest match
  while (middle->pc <= offset && middle < end  ) middle++;
  while (middle->pc >  offset && middle > start) middle--;
  
  assert(start <= middle && middle <= end, "should have found a pcDesc");
# if GENERATE_DEBUGGING_AIDS
    if (CheckAssertions) {
      PcDesc* d = pcs();
      PcDesc* closest = d;
      for (; d <= end; d ++) {
        if (d->pc <= offset && (closest == NULL || closest->pc <= d->pc)) {
          closest = d;
        }
      }
      assert(closest == middle, "found different pcDesc");
    }
# endif

  return middle;
}
Beispiel #2
0
TEST(NumLib, DISABLED_Extrapolation)
#endif
{
    /* In this test a random vector x of nodal values is created.
     * This vector is interpolated to the integration points using each
     * element's the shape functions.
     * Afterwards the integration point values y are extrapolated to the mesh
     * nodes again.
     * Since y have been obtained from x via interpolation, it is expected, that
     * the interpolation result nearly exactly matches the original nodal values
     * x.
     */

    const double mesh_length = 1.0;
    const std::size_t mesh_elements_in_each_direction = 5;

    // generate mesh
    std::unique_ptr<MeshLib::Mesh> mesh(
        MeshLib::MeshGenerator::generateRegularHexMesh(
            mesh_length, mesh_elements_in_each_direction));

    for (unsigned integration_order : {2, 3, 4})
    {
        namespace LinAlg = MathLib::LinAlg;

        auto const nnodes = mesh->getNumberOfNodes();
        auto const nelements = mesh->getNumberOfElements();
        DBUG("number of nodes: %lu, number of elements: %lu", nnodes,
             nelements);

        ExtrapolationTest::ExtrapolationTestProcess pcs(*mesh,
                                                        integration_order);

        // generate random nodal values
        MathLib::MatrixSpecifications spec{nnodes, nnodes, nullptr, nullptr};
        auto x = MathLib::MatrixVectorTraits<GlobalVector>::newInstance(spec);

        fillVectorRandomly(*x);

        pcs.interpolateNodalValuesToIntegrationPoints(*x);

        // test extrapolation of a quantity that is stored in the local
        // assembler
        ExtrapolationTest::extrapolate(
            pcs,
            &ExtrapolationTest::LocalAssemblerDataInterface::getStoredQuantity,
            *x, nnodes, nelements);

        // expect 2*x as extraplation result for derived quantity
        auto two_x = MathLib::MatrixVectorTraits<GlobalVector>::newInstance(*x);
        LinAlg::axpy(*two_x, 1.0, *x);  // two_x = x + x

        // test extrapolation of a quantity that is derived from some
        // integration point values
        ExtrapolationTest::extrapolate(
            pcs,
            &ExtrapolationTest::LocalAssemblerDataInterface::getDerivedQuantity,
            *two_x, nnodes, nelements);
    }
}
Beispiel #3
0
pcstack* new_pcstack()
{
  pcstack* pcs((pcstack*)malloc(sizeof(pcstack)));
  memset((void*)pcs,0,sizeof(pcstack));
  pcs->size=0;
  pcs->first=0;
  return pcs;
}
Beispiel #4
0
bool nmethod::encompasses(void* p) {
  return includes(p, this, this + 1) ||
         includes(p, deps(), depsEnd()) ||
         includes(p, insts(), instsEnd()) ||
         includes(p, locs(), locsEnd()) ||
         scopes->includes((ScopeDesc*) p) ||
         includes(p, pcs(), pcsEnd());
}
Beispiel #5
0
void __attribute__ ((noinline)) i2c_write_bit(uint8_t val) 
{
  if ( val )
    pcs(pcs_i2c_write_1);
  else
    pcs(pcs_i2c_write_0);
  /*
  if (val)
    i2c_read_sda();
  else
    i2c_clear_sda();
  
  i2c_delay();
  i2c_read_scl_and_delay();
  i2c_clear_scl();
  */
}
Beispiel #6
0
void nmethod::printPcs() {
  ResourceMark m;       // in case methods get printed from gdb
  printIndent();
  lprintf("pc-bytecode offsets:\n");
  Indent ++;
  for (PcDesc* p = pcs(); p < pcsEnd(); p ++) p->print(this);
  Indent --;
}
Data_Splitter<INTERVALCONTAINER,IDXTYPE>::Data_Splitter(const Data_Splitter& dsp)
{
	notify("Data_Splitter strong copy constructor begin.");
	csplit.clear();
	for(typename std::vector<PClassSplitter>::const_iterator c=dsp.csplit.begin();c!=dsp.csplit.end();c++) 
		{PClassSplitter pcs(new TClassSplitter(*(*c))); this->csplit.push_back(pcs);}
	notify("Data_Splitter strong copy constructor end.");
}
void PluginsManager::addInMenuFromPMIndex(int i)
{
    std::vector<PluginCmdShortcut> & pluginCmdSCList = (NppParameters::getInstance())->getPluginCommandList();
	::InsertMenu(_hPluginsMenu, i, MF_BYPOSITION | MF_POPUP, (UINT_PTR)_pluginInfos[i]->_pluginMenu, _pluginInfos[i]->_pFuncGetName());

    unsigned short j = 0;
	for ( ; j < _pluginInfos[i]->_nbFuncItem ; j++)
	{
		if (_pluginInfos[i]->_funcItems[j]._pFunc == NULL)
		{
			::InsertMenu(_pluginInfos[i]->_pluginMenu, j, MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
			continue;
		}

        _pluginsCommands.push_back(PluginCommand(_pluginInfos[i]->_moduleName.c_str(), j, _pluginInfos[i]->_funcItems[j]._pFunc));

		int cmdID = ID_PLUGINS_CMD + (_pluginsCommands.size() - 1);
		_pluginInfos[i]->_funcItems[j]._cmdID = cmdID;
		generic_string itemName = _pluginInfos[i]->_funcItems[j]._itemName;

		if (_pluginInfos[i]->_funcItems[j]._pShKey)
		{
			ShortcutKey & sKey = *(_pluginInfos[i]->_funcItems[j]._pShKey);
            PluginCmdShortcut pcs(Shortcut(itemName.c_str(), sKey._isCtrl, sKey._isAlt, sKey._isShift, sKey._key), cmdID, _pluginInfos[i]->_moduleName.c_str(), j);
			pluginCmdSCList.push_back(pcs);
			itemName += TEXT("\t");
			itemName += pcs.toString();
		}
		else
		{	//no ShortcutKey is provided, add an disabled shortcut (so it can still be mapped, Paramaters class can still index any changes and the toolbar wont funk out
            Shortcut sc(itemName.c_str(), false, false, false, 0x00);
            PluginCmdShortcut pcs(sc, cmdID, _pluginInfos[i]->_moduleName.c_str(), j);	//VK_NULL and everything disabled, the menu name is left alone
			pluginCmdSCList.push_back(pcs);
		}
		::InsertMenu(_pluginInfos[i]->_pluginMenu, j, MF_BYPOSITION, cmdID, itemName.c_str());

		if (_pluginInfos[i]->_funcItems[j]._init2Check)
			::CheckMenuItem(_hPluginsMenu, cmdID, MF_BYCOMMAND | MF_CHECKED);
	}
	/*UNLOAD
    ::InsertMenu(_pluginInfos[i]->_pluginMenu, j++, MF_BYPOSITION | MF_SEPARATOR, 0, TEXT(""));
    ::InsertMenu(_pluginInfos[i]->_pluginMenu, j, MF_BYPOSITION, ID_PLUGINS_REMOVING + i, TEXT("Remove this plugin"));
	*/
}
Beispiel #9
0
ExLockSync::ExLockSync()
{
#ifdef DEBUG
    m_lockOwner = 0;
#endif

    CASSERT( sizeof( m_data ) == sizeof( CRITICAL_SECTION ) );
    CASSERT( __alignof( Data ) == __alignof( CRITICAL_SECTION ) );
    InitializeCriticalSection( pcs( &m_data ) );
}
Beispiel #10
0
void i2c_start(void) 
{
  if ( i2c_started != 0 ) 
  { 
    /* if already started: do restart */
    //i2c_read_sda();	/* SDA = 1 */
    //i2c_delay();
    //i2c_read_scl_and_delay();
    pcs(pcs_i2c_restart);
  }
  //i2c_read_sda();
  /* send the start condition, both lines go from 1 to 0 */
  //i2c_clear_sda();
  //i2c_delay();
  //i2c_clear_scl();
  
  pcs(pcs_i2c_start);
  i2c_started = 1;
}
Beispiel #11
0
void
ExLockSync::claimLock()  // nofail
{
    EnterCriticalSection( pcs( &m_data ) );

#ifdef DEBUG
    dbgAssert( !m_lockOwner );
    m_lockOwner = GetCurrentThreadId(); 
#endif
}
Beispiel #12
0
void
ExLockSync::releaseLock()  // nofail
{
#ifdef DEBUG
    dbgAssert( m_lockOwner == GetCurrentThreadId() );
    m_lockOwner = 0; 
#endif

    LeaveCriticalSection( pcs( &m_data ) );
}
void Data_Splitter<INTERVALCONTAINER,IDXTYPE>::set_n(const unsigned int _clsidx, const IDXTYPE _n)
{
	assert(_n>0); 
	assert(_clsidx>=0);
	try {	
		while(csplit.size()<=_clsidx) {PClassSplitter pcs(new TClassSplitter); csplit.push_back(pcs);}
		csplit[_clsidx]->n=_n;
	} catch(...) {
		throw fst_error("Data_Splitter::assign() out-of-index? error.");
	}
}
void Data_Splitter<INTERVALCONTAINER,IDXTYPE>::assign(const unsigned int _clsidx, const PIntervaller _train, const PIntervaller _test)
{
	assert(_clsidx>=0);
	assert(_train); 
	assert(_test);
	try {	
		while(csplit.size()<=_clsidx) {PClassSplitter pcs(new TClassSplitter); csplit.push_back(pcs);}
		csplit[_clsidx]->train=_train; 
		csplit[_clsidx]->test=_test;
	} catch(...) {
		throw fst_error("Data_Splitter::assign() out-of-index? error.");
	}
}
Beispiel #15
0
void UnionScan::executePlanOperation() {
  const auto& tables = input.getTables();
  std::vector<std::shared_ptr<const storage::PointerCalculator>> pcs(tables.size());
  std::transform(begin(tables), end(tables), begin(pcs), [](decltype(*begin(tables)) table) {
    return std::dynamic_pointer_cast<const storage::PointerCalculator>(table);
  });
  if (std::all_of(begin(pcs), end(pcs), [](decltype(*begin(tables)) pc) { return pc != nullptr; })) {
    addResult(storage::PointerCalculator::unite_many(begin(pcs), end(pcs)));
  } else {
    throw std::runtime_error(_planOperationName + " is only supported for PointerCalculators (UnionScan.cpp)");
    // We need to implement duplicate elimination here to make this a true union
    // If you tripped over this error, you probably meant to use UnionAll.
    // addResult(std::make_shared<const HorizontalTable>(tables));
  }
}
Beispiel #16
0
unsigned __attribute__ ((noinline)) i2c_read_bit(void) 
{
  return pcs(pcs_i2c_read_bit);
  //uint8_t val;
  /* do not drive SDA */
  /*
  i2c_read_sda();
  i2c_delay();
  i2c_read_scl_and_delay();
  val = i2c_read_sda();
  i2c_delay();
  i2c_clear_scl();
  return val;
  */
}
Beispiel #17
0
void i2c_stop(void)
{
  /* set SDA to 0 */
  //i2c_clear_sda();  
  //i2c_delay();
  
  /* now release all lines */
  //i2c_read_scl_and_delay();
  
  /* set SDA to 1 */
  //i2c_read_sda();
  //i2c_delay();
  pcs(pcs_i2c_stop);
  i2c_started = 0;
}
Beispiel #18
0
Datei: eval.cpp Projekt: hyln9/nV
bool SearchCProcs(var &result, var head, var body)
{
	stdext::hash_map<Var,CProc>::const_iterator
		iter = CProcs.find(head);
	if(iter != CProcs.end())
	{
		PushCProcSymbol pcs(head);
		if (Verbose >= 3) {
			wcerr << _W("Enter cproc for ");
			Println(Ex(head, body), wcerr);
		}
		try {
			result = iter->second(body);
		}
		catch (UserException&) {
			throw;
		}
// 		catch (std::exception& e) {
// 			wcerr << L"std::exception thrown: " << mbs2wcs(e.what()) << std::endl;
// 			wcerr << "CProc error while eval ";
// 			Println(Ex(head, body), wcerr);
// 			return false;
// 		}
		catch (...) {
			wcerr << "CProc error while eval ";
			Println(Ex(head, body), wcerr);
			throw;
		}
		if (result)
		{
			if (TraceRuleSymbols.count(head) != 0)
			{
				// FIXME: rewrite this after we implement the kernel message infrastructure
				Print(head);
				wcout << _W("::tracer : ");
				Print(Ex(head, body));
				wcout << _W(" :> ");
				Println(result);
			}
			if (Verbose >= 3) {
				wcerr << _W("Result is ");
				Println(result, wcerr);
			}
			return true;
		}
	}
	return false;
}
Beispiel #19
0
// Cutting point of three planes
Foam::point Foam::plane::planePlaneIntersect
(
    const plane& plane2,
    const plane& plane3
) const
{
    List<scalarList> pcs(3);
    pcs[0]= planeCoeffs();
    pcs[1]= plane2.planeCoeffs();
    pcs[2]= plane3.planeCoeffs();

    tensor a
    (
        pcs[0][0],pcs[0][1],pcs[0][2],
        pcs[1][0],pcs[1][1],pcs[1][2],
        pcs[2][0],pcs[2][1],pcs[2][2]
    );

    vector b(pcs[0][3],pcs[1][3],pcs[2][3]);

    return (inv(a) & (-b));
}
Beispiel #20
0
	Android_PushEvent();
}

void Java_in_celest_xash3d_XashActivity_nativeString(JNIEnv* env, jclass cls, jobject string)
{
	char* str = (char *) (*env)->GetStringUTFChars(env, string, NULL);

	Android_Lock();
	strncat( events.inputtext, str, 256 );
	Android_Unlock();

	(*env)->ReleaseStringUTFChars(env, string, str);
}

#ifdef SOFTFP_LINK
void Java_in_celest_xash3d_XashActivity_nativeTouch(JNIEnv* env, jclass cls, jint finger, jint action, jfloat x, jfloat y ) __attribute__((pcs("aapcs")));
#endif
void Java_in_celest_xash3d_XashActivity_nativeTouch(JNIEnv* env, jclass cls, jint finger, jint action, jfloat x, jfloat y )
{
	float dx, dy;
	event_t *event;

	// if something wrong with android event
	if( finger > MAX_FINGERS )
		return;

	// not touch action?
	if( !( action >=0 && action <= 2 ) )
		return;

	// 0.0f .. 1.0f
Beispiel #21
0
// REQUIRES: arm-registered-target
// RUN: %clang_cc1 -triple arm-none-linux-gnueabi -emit-llvm -w -o - < %s | FileCheck %s
typedef int __attribute__((pcs("aapcs"))) (*aapcs_fn)(void);
typedef int __attribute__((pcs("aapcs-vfp"))) (*aapcs_vfp_fn)(void);

aapcs_fn bar;

int foo(aapcs_vfp_fn baz) {
// CHECK-LABEL: define i32 @foo
// CHECK: call arm_aapcscc
// CHECK: call arm_aapcs_vfpcc
  return bar() + baz();
}
Beispiel #22
0
/* maybe this can be optimized */
void i2c_init(void)
{
  pcs(pcs_i2c_init);
}
Beispiel #23
0
void simple_load_balancer::run_lb(app_info& info, partition_configuration& pc, bool is_stateful)
{
    if (_state->freezed() && is_stateful)
        return;

    configuration_update_request proposal;
    proposal.config = pc;
    proposal.info = info;

    if (is_stateful)
    {
        if (pc.primary.is_invalid())
        {
            if (pc.secondaries.size() > 0)
            {
                if (s_lb_for_test)
                {
                    std::vector< ::dsn::rpc_address> tmp(pc.secondaries);
                    std::sort(tmp.begin(), tmp.end());
                    proposal.node = tmp[0];
                }
                else
                {
                    proposal.node = pc.secondaries[dsn_random32(0, static_cast<int>(pc.secondaries.size()) - 1)];
                }
                proposal.type = config_type::CT_UPGRADE_TO_PRIMARY;
            }

            else if (pc.last_drops.size() == 0)
            {
                proposal.node = find_minimal_load_machine(true);
                proposal.type = config_type::CT_ASSIGN_PRIMARY;
            }

            // DDD
            else
            {
                proposal.node = *pc.last_drops.rbegin();
                proposal.type = config_type::CT_ASSIGN_PRIMARY;

                derror("%s.%d.%d enters DDD state, we are waiting for its last primary node %s to come back ...",
                    info.app_type.c_str(),
                    pc.pid.get_app_id(),
                    pc.pid.get_partition_index(),
                    proposal.node.to_string()
                    );
            }

            if (proposal.node.is_invalid() == false)
            {
                send_proposal(proposal.node, proposal);
            }
        }

        else if (static_cast<int>(pc.secondaries.size()) + 1 < pc.max_replica_count)
        {
            proposal.type = config_type::CT_ADD_SECONDARY;
            proposal.node = find_minimal_load_machine(false);
            if (proposal.node.is_invalid() == false &&
                proposal.node != pc.primary &&
                std::find(pc.secondaries.begin(), pc.secondaries.end(), proposal.node) == pc.secondaries.end())
            {
                send_proposal(pc.primary, proposal);
            }
        }
        else
        {
            // it is healthy, nothing to do
        }
    }
    
    // stateless
    else
    {
        partition_configuration_stateless pcs(pc);

        if (static_cast<int>(pcs.worker_replicas().size()) < pc.max_replica_count)
        {
            proposal.type = config_type::CT_ADD_SECONDARY;
            proposal.node = find_minimal_load_machine(false);
            if (proposal.node.is_invalid() == false)
            {
                bool send = true;

                for (auto& s : pc.secondaries)
                {
                    // not on the same machine
                    if (s == proposal.node)
                    {
                        send = false;
                        break;
                    }
                }

                if (send)
                {
                    send_proposal(proposal.node, proposal);
                }
            }
        }
        else
        {
            // it is healthy, nothing to do
        }
    }
}
Beispiel #24
0
void __attribute__ ((noinline)) i2c_clear_scl(void)
{
  /* set open collector and drive low */
  pcs(pcs_i2c_clear_scl);
}
Beispiel #25
0
/* actually, the scl line is not observed, so this procedure does not return a value */
void i2c_read_scl_and_delay(void)
{
  pcs(pcs_i2c_read_scl_and_delay);
}
Beispiel #26
0
uint8_t __attribute__ ((noinline)) i2c_read_sda(void)
{
  //Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, 0, 0);
  return pcs(pcs_i2c_read_sda);
  //return Chip_GPIO_ReadPortBit(LPC_GPIO_PORT, 0, 0);  
}
Beispiel #27
0
bool nmethod::verify() {
  bool r = true;
  ResourceMark rm;

  r &= OopNCode::verify2("nmethod");
  
  if (insts() != (char*)(this + 1)) {
    error1("nmethod at 0x%lx has incorrect insts pointer", this);
    r = false;
  }
  if (!Memory->code->contains(this)) {
    error1("nmethod at 0x%lx not in zone", this);
    r = false;
  }
  if (!zoneLink.verify_list_integrity()) {
    lprintf("\tof zoneLink of nmethod 0x%lx\n", this);
    r = false;
  }
  { FOR_MY_CODETABLE_ENTRIES(e)
      if (e->nm != this) {
        error1("bad code table link for nmethod %#lx\n", this);
        r = false;
      }
  }
  bool isAligned = (frame_size & (frame_word_alignment-1)) == 0;
  if (!isAligned) {
    lprintf("nmethod at %#lx: frame size is not multiple of %d words\n",
           (long unsigned)this,
           frame_word_alignment);
    r = false;
  }
  if (codeTableLink != NULL) {
    nmethod *tableResult =
      isDebug() ? Memory->code->debugTable->lookup(key) :
                  Memory->code->table     ->lookup(key);
    if (tableResult != this) {
      error1("nmethod at %#lx: code table lookup failed", this);
      r = false;
    }
  }
  if (!key.verify()) {
    lprintf("\tof key of nmethod 0x%lx\n", this);
    r = false;
  }
  { FOR_MY_CODETABLE_ENTRIES(e)
      if (!e->key.verify()) {
        lprintf("\tof code table key %#lx of nmethod 0x%lx\n",
               (long unsigned)&e->key, (long unsigned)this);
        r = false;
      }
  }
  if (!linkedSends.verify_list_integrity()) {
    lprintf("\tof linkedSends of nmethod 0x%lx\n", this);
    r = false;
  }
  if (!diLink.verify_list_integrity()) {
    lprintf("\tof diLink of nmethod 0x%lx\n", this);
    r = false;
  }
  r &= scopes->verify();

  for (PcDesc* p = pcs(); p < pcsEnd(); p++) {
    if (! p->verify(this)) {
      lprintf("\t\tin nmethod at %#lx (pcs)\n", this);
      r = false;
    }
  }
  
  // more checks in ncode::verify called above
  bool shouldBeDI = diLink.notEmpty();
  for (addrDesc* l = locs(); l < locsEnd(); l++) {
    if (l->isDIDesc()) {
      shouldBeDI = true;
    }
  }
  
  if (shouldBeDI && !isDI()) {
    error1("nmethod %#lx should be marked isDI", this);
    r = false;
  } else if (!shouldBeDI && isDI()) {
    error1("nmethod %#lx should not be marked isDI", this);
    r = false;
  }

  if (! key.receiverMap()->is_block() ) {
    for (nmln* d = deps(); d < depsEnd(); d++) {
      if (! d->verify_list_integrity()) {
        lprintf("\tin nmethod at %#lx (deps)\n", this);
        r = false;
      }
    }
  }
  
  if (frame_chain != NoFrameChain) {
    error1("nmethod %#lx has non-zero frame chain value", this);
    r = false;
  }
  
  if (findNMethod( instsEnd() - oopSize) != this) {
    error1("findNMethod did not find this nmethod (%#lx)", this);
    r = false;
  }
  return r;
}
Beispiel #28
0
void __attribute__ ((noinline)) i2c_clear_sda(void)
{
  /* set open collector and drive low */
  pcs(pcs_i2c_clear_sda);
  // Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 0);
}
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file tests __aeabi_drsub for the compiler_rt library.
//
//===----------------------------------------------------------------------===//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#if __arm__
extern __attribute__((pcs("aapcs"))) double __aeabi_drsub(double a, double b);

int test__aeabi_drsub(double a, double b, double expected)
{
    double actual = __aeabi_drsub(a, b);
    if (actual != expected)
        printf("error in __aeabi_drsub(%f, %f) = %f, expected %f\n",
               a, b, actual, expected);
    return actual != expected;
}
#endif

int main()
{
#if __arm__
    if (test__aeabi_drsub(1.0, 1.0, 0.0))
Beispiel #30
0
//
//===----------------------------------------------------------------------===//
//
// This file tests __aeabi_cfcmpeq for the compiler_rt library.
//
//===----------------------------------------------------------------------===//

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#if __arm__
#include "call_apsr.h"

extern __attribute__((pcs("aapcs"))) void __aeabi_cfcmpeq(float a, float b);

int test__aeabi_cfcmpeq(float a, float b, int expected)
{
    uint32_t cpsr_value = call_apsr_f(a, b, __aeabi_cfcmpeq);
    union cpsr cpsr = { .value = cpsr_value };
    if (expected != cpsr.flags.z) {
        printf("error in __aeabi_cfcmpeq(%f, %f) => Z = %d, expected %d\n",
               a, b, cpsr.flags.z, expected);
        return 1;
    }
    return 0;
}
#endif

int main()