Commit cab37234 by Roman

Add libs bsp,builtins,m,softfloat,testfloat

Signed-off-by: Roman Bartosinski <roman@daiteq.com>
1 parent f604accf
Showing with 4865 additions and 0 deletions
# Makefile for building BSP library
# Allowed defined symbols which are used in the library:
# - BSP_BOARD
$(info >>> L-BSP <<< T=$(TOP) D=$(DSTPATH) I=$(INCPATH) B=$(BLDPATH) CF=$(CFLAGS) F=$(FPUCFG) )
# ramsize = 4MB
#CFLAGS+=-DRAMSIZE=4194304 -Xassembler '--defsym RAMSIZE=4194304'
PWD:=$(shell pwd)
SOURCE_DIR?=$(PWD)
EXPHDRS=my_printf.h leon-myuart.h sysregs.h lconf.h leon.h stub.h
SOURCES=$(wildcard *.c)
ASMS=$(wildcard *.S)
COBJS=$(SOURCES:%.c=$(BLDPATH)/%.o)
AOBJS=$(ASMS:%.S=$(BLDPATH)/%.o)
DISS=$(SOURCES:%.c=$(BLDPATH)/%.dis)
LIBRARY=libbsp
ifeq ($(TOOL),llvm)
CC=clang
TOOLCHAIN=sparc-daiteq-elf
#CFLAGS=-msoft-float -O3
CFLAGS+=-target $(TOOLCHAIN) -mcpu=leon2
# TODO: asm options according to selected type of FPU
CFLAGS+=-Xassembler --has-fhalf -Xassembler --has-fpack -Xassembler -Aleon
FPUTYPE=-daiteq-fpu-type=$(FPUCFG)
endif
ifeq ($(TOOL),gcc)
TOOLCHAIN=sparc-gaisler-elf
CC=$(TOOLCHAIN)-gcc
CFLAGS+=-mcpu=leon -qbsp=leon2 -mfix-at697f -std=c99
FPUTYPE=-DFPUCFG=$(FPUCFG)
endif
CFLAGS+=-ffunction-sections -fdata-sections
CFLAGS+=-I. -I$(SFDIR)/source/include
AR=$(TOOLCHAIN)-ar
.PHONY: all clean export
all: export
@echo "Library is created"
$(BLDPATH):
@mkdir -p $(BLDPATH)
$(BLDPATH)/$(LIBRARY).a: $(AOBJS) $(COBJS)
@$(AR) crs $@ $^
$(BLDPATH)/%.o:%.c
@$(CC) $(FPUTYPE) $(CFLAGS) -c $< -o $@
$(BLDPATH)/%.o:%.S
@$(CC) $(FPUTYPE) $(CFLAGS) -c $< -o $@
$(BLDPATH)/%.dis:$(BLDPATH)/%.o
@$(TOOLCHAIN)-objdump -S $< > $@
clean:
rm -rf $(BLDPATH)
export: $(DSTPATH)/$(LIBRARY).a $(DISS) $(EXPHDRS:%=$(INCPATH)/%)
@echo "Library is exported"
$(DSTPATH)/$(LIBRARY).a: $(BLDPATH) $(BLDPATH)/$(LIBRARY).a
@cp $(BLDPATH)/$(LIBRARY).a $(DSTPATH)
$(INCPATH)/%: $(SOURCE_DIR)/%
ln -sf $< $@
/* -----------------------------------------------------------------------------
* Copyright (C) 2020 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : asi.h
* Authors : Martin Danek
* Description : address space identifier assignments
* Release :
* Version : 1.0
* Date : 4.1.2020
* -----------------------------------------------------------------------------
*/
#ifndef ASI_H
#define ASI_H
#define FIFO_DATA_ASR %%asr7
#define FIFO_CTL_ASR %%asr17
#define CODE_DATA_ASR %%asr1
#define CODE_CTL_ASR %%asr3
#define SWAR_CTL_ASR %%asr22
#define SWAR_ACC_ASR %%asr23
#define SYSREGS_CTL_ASR %%asr2
#endif
/* -----------------------------------------------------------------------------
* Copyright (C) 2019 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : asm.h
* Authors : Martin Danek
* Description : inline assembly routines
* Release :
* Version : 1.0
* Date : 9.4.2019
* -----------------------------------------------------------------------------
*/
#ifndef ASM_H
#define ASM_H
#define str(s) #s
#define rd_asr(A,R) \
__asm__ volatile ( \
"\t rd " str(A) ", %0\n" \
: "=r" (R) \
) \
#define wr_asr(A,O) \
__asm__ volatile ( \
"\t nop\n" \
"\t wr %0, 0, " str(A) " \n" \
"\t nop\n" \
: \
: "r" (O) \
) \
\
#define swar(A, B, RES) \
__asm__ volatile ( \
"\t swar %1, %2, %0 \n" \
: "=r" (RES) \
: "Ir" (A), "Ir" (B) \
) \
\
#define swarcc(A, B, RES) \
__asm__ volatile ( \
"\t swarcc %1, %2, %0 \n" \
: "=r" (RES) \
: "Ir" (A), "Ir" (B) \
: "cc" \
) \
\
#endif
#include "leon.h"
/* #define RAMSIZE 0x1000000 */
#ifndef RAMSIZE
#define RAMSIZE 128*1024
#endif
/* #define RAMSIZE 0x1000 */
#define RAMEND (CRAM + RAMSIZE)
.seg "text"
.proc 0
.align 4
! .global _hardreset
!_hardreset:
.global boot
boot:
por:
flush
set 0x10c0, %g1 ! init IU
! set 0x00c0, %g1 ! init IU
mov %g1, %psr
mov %g0, %wim
mov %g0, %tbr
mov %g0, %y
nop
set _text_start,%g1
mov %g1, %tbr
set PREGS, %g7 ! on-chip register base address
set 0x1000f, %g1
st %g1, [%g7 + CCTRL]
ld [%g7 + ECTRL], %g1
and %g1, 0x100, %g1
sll %g1, 1, %g2
or %g1, %g2, %g1
set 0x0f0000, %g2
or %g1, %g2, %g1
st %g1, [%g7 + ECTRL]
ld [%g7 + MCFG1], %g1
and %g1, 0x3ff, %g1
st %g1, [%g7 + MCFG1]
and %g1, 0x300, %g1
ld [%g7 + IOREG], %g2
srl %g2, 4, %g3
and %g3, 3, %g3
or %g1, %g3, %g1
set 0x04080000, %g3 ! initialise memory config registers
or %g3, %g1, %g1
st %g1, [%g7 + MCFG1]
sll %g2, 4, %g3
and %g3, 0x70, %g1
and %g2, 0x0c0, %g3
srl %g3, 4, %g3
or %g3, %g1, %g1
srl %g3, 2, %g3
or %g3, %g1, %g1
set 0x800, %g3
or %g3, %g1, %g1
andcc %g2, 3, %g0
bne 1f
nop
add %g1, 0x200, %g1
1:
! set 0xd5384000, %g3
! or %g3, %g1, %g1
! st %g1, [%g7 + MCFG2]
set -1, %g3
st %g0, [%g7 + FADDR]
st %g0, [%g7 + MSTAT]
st %g0, [%g7 + WPROT1]
st %g0, [%g7 + WPROT2]
st %g3, [%g7 + SRLD]
st %g3, [%g7 + SCNT]
st %g0, [%g7 + TCTRL0]
st %g3, [%g7 + TRLD0]
st %g3, [%g7 + TCNT0]
st %g0, [%g7 + TCTRL1]
st %g3, [%g7 + TRLD1]
st %g3, [%g7 + TCNT1]
st %g3, [%g7 + USCAL0]
st %g3, [%g7 + UCTRL0]
st %g0, [%g7 + USTAT0]
st %g3, [%g7 + USCAL1]
st %g3, [%g7 + UCTRL1]
st %g0, [%g7 + USTAT1]
st %g0, [%g7 + WPROT1]
st %g0, [%g7 + WPROT2]
st %g0, [%g7 + IOREG]
st %g0, [%g7 + IOICONF]
st %g0, [%g7 + IFORCE]
st %g0, [%g7 + IMASK]
st %g0, [%g7 + IPEND]
st %g3, [%g7 + ICLEAR]
st %g0, [%g7 + IMASK2]
st %g0, [%g7 + IPEND2]
st %g3, [%g7 + ICLEAR2]
st %g0, [%g7 + ISTAT2]
ba 2f ! ld [%g7 + ECTRL], %g2 ! if LEON-FT, then clear %asr16
nop ! srl %g2, RFE_CONF_BIT, %g3
andcc %g3, RFE_CONF_MASK, %g3
be 2f
nop
mov %g0, %asr16
2:
ld [%g7 + LCONF], %g2 ! load LEON configuration register
srl %g2, 20, %g3
and %g3, 0x1f, %g3
mov %g0, %g4
mov %g0, %g5
mov %g0, %g6
1:
mov %g0, %l0
mov %g0, %l1
mov %g0, %l2
mov %g0, %l3
mov %g0, %l4
mov %g0, %l5
mov %g0, %l6
mov %g0, %l7
mov %g0, %o0
mov %g0, %o1
mov %g0, %o2
mov %g0, %o3
mov %g0, %o4
mov %g0, %o5
mov %g0, %o6
mov %g0, %o7
subcc %g3, 1, %g3
bge 1b
save
srl %g2, FPU_CONF_BIT, %g3
andcc %g3, FPU_CONF_MASK, %g0
be 3f
set zerodword, %g4
st %g0, [%g4]
st %g0, [%g4+4]
nop
ld [%g4], %fsr
ldd [%g4], %f0
ldd [%g4], %f2
ldd [%g4], %f4
ldd [%g4], %f6
ldd [%g4], %f8
ldd [%g4], %f10
ldd [%g4], %f12
ldd [%g4], %f14
ldd [%g4], %f16
ldd [%g4], %f18
ldd [%g4], %f20
ldd [%g4], %f22
ldd [%g4], %f24
ldd [%g4], %f26
ldd [%g4], %f28
ldd [%g4], %f30
ba 3f
mov %g0,%g4
3:
set 0x40000000, %o1
set 0x80000000, %o2
set 0x80f003a7, %o3
st %o3, [%o2+0x28]
/*
set 1, %o3
st %o3, [%o2+4]
set 2, %o3
st %o3, [%o2+4]
st %o3, [%o2+4]
set 0x80100000, %o3
st %o3, [%o2+4]
nop
nop
nop
nop
ldda [%o1] 0, %o4
set 0x76543210, %o3
st %o3, [%o1+0]
st %o3, [%o1+4]
st %o3, [%o1+8]
std %o2, [%o1+0]
ld [%o1+0], %o4
ld [%o1+4], %o4
1:
ldda [%o1] 0, %o4
ldda [%o1] 0, %o4
call 0x40000000
nop
ba 1b
st %g0, [%o1+0x10]
sth %o3, [%o1+0x10]
ld [%o1+0x10], %o4
st %g0, [%o1+0x14]
sth %o3, [%o1+0x16]
ld [%o1+0x14], %o4
st %g0, [%o1+0x18]
stub %o3, [%o1+0x18]
stub %o3, [%o1+0x19]
stub %o3, [%o1+0x1a]
stub %o3, [%o1+0x1b]
ld [%o1+0x18], %o4
*/
/*
set 0x20000000, %o1
set 0x01234567, %o3
st %o3, [%o1+96]
sth %o3, [%o1+98]
stb %o3, [%o1+99]
ld [%o1+96], %o2
st %o2, [%o1+96]
lduh [%o1+96], %o3
sth %o3, [%o1+96]
lduh [%o1+98], %o3
sth %o3, [%o1+98]
ldub [%o1+96], %o4
stb %o4, [%o1+96]
ldub [%o1+97], %o4
stb %o4, [%o1+97]
ldub [%o1+98], %o4
stb %o4, [%o1+98]
ldub [%o1+99], %o4
stb %o4, [%o1+99]
*/
mov 2, %g1
mov %g1, %wim
! set 0x10e0, %g1 ! enable traps
! set 0x00c0, %g1 ! enable traps
set 0x10e0, %g1 ! enable traps
mov %g1, %psr
nop; nop; nop;
set CRAM + RAMSIZE - 16, %g3
! set CRAM + (4*1024) - 16, %g3
! set CRAM + (192*1024) - 16, %g3
! set SDRAM + (256*1024) - 16, %g3
mov %g3, %fp
sub %g3, 96, %sp
set main, %g1
jmp %g1
nop
.seg "data"
zerodword:
.word 0
.word 0
.align 32
/* -----------------------------------------------------------------------------
* Copyright (C) 2020 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : sysregs.c
* Authors : Martin Danek
* Description : system register definitions
* Release :
* Version : 1.0
* Date : 14.6.2020
* -----------------------------------------------------------------------------
*/
#include <stdint.h>
#include "leon-myuart.h"
#include "lconf.h"
void get_lconf(lconf_type *lconf) {
unsigned config;
config = (unsigned)cpu_reg_read(LCONF_BASE);
lconf->ahbstaten = (config&LCONF_AHBSTATEN);
lconf->wdogen = (config&LCONF_WDOGEN);
lconf->multiplier = (config&LCONF_MULTIPLIER);
lconf->divider = (config&LCONF_DIVIDER);
lconf->macen = (config&LCONF_MACEN);
lconf->sdramen = (config&LCONF_SDRAMEN);
lconf->dsu = (config&LCONF_DSU);
lconf->men = (config&LCONF_MEN);
//
lconf->dline_bits = (config&LCONF_DLINE_BITS) >> 10;
lconf->dset_bits = (config&LCONF_DSIZE) >> 12;
lconf->iline_bits = (config&LCONF_ILINE_BITS) >> 15;
lconf->iset_bits = (config&LCONF_ISIZE) >> 17;
lconf->nwindows = (config&LCONF_NWINDOWS) >> 20;
lconf->watchpoints = (config&LCONF_WATCHPOINTS) >> 26;
lconf->fpu = (config&LCONF_FPU_MSK) >> 4;
lconf->pci = (config&LCONF_PCI_MSK) >> 2;
lconf->wproten = (config&LCONF_WPROTEN_MSK);
}
void get_lconf_fpu(lconf_fpu_type *lconf_fpu) {
unsigned config;
config = (unsigned)cpu_reg_read(LCONF_FPU_BASE);
lconf_fpu->fdiv = (config&LCONF_FPU_DIV);
lconf_fpu->fsqrt = (config&LCONF_FPU_SQRT);
lconf_fpu->packed = (config&LCONF_FPU_PACKED);
lconf_fpu->dual = (config&LCONF_FPU_DUAL);
//
lconf_fpu->exp_hi = (config&LCONF_FPU_EXPH_BITS) >> 4;
lconf_fpu->trsig_hi = (config&LCONF_FPU_TRSIGH_BITS) >> 8;
lconf_fpu->exp_lo = (config&LCONF_FPU_EXPL_BITS) >> 14;
lconf_fpu->trsig_lo = (config&LCONF_FPU_TRSIGL_BITS) >> 18;
}
void get_lconf_swar(lconf_swar_type *lconf_swar) {
unsigned config;
config = (unsigned)cpu_reg_read(LCONF_SWAR_BASE);
lconf_swar->correl = (config&LCONF_SWAR_CORREL);
lconf_swar->demod = (config&LCONF_SWAR_DEMOD);
lconf_swar->sincos = (config&LCONF_SWAR_SINCOS);
lconf_swar->audio = (config&LCONF_SWAR_AUDIO);
lconf_swar->video = (config&LCONF_SWAR_VIDEO);
lconf_swar->alu = (config&LCONF_SWAR_ALU);
lconf_swar->acc = (config&LCONF_SWAR_ACC);
//
lconf_swar->lanes = (config&LCONF_SWAR_LANES) >> 16;
lconf_swar->swidth = (config&LCONF_SWAR_SWIDTH) >> 21;
lconf_swar->awidth = (config&LCONF_SWAR_AWIDTH) >> 26;
}
void report_lconf(lconf_type *lconf) {
NL;
m_print("LEON CONFIGURATION");NL;
m_print("------------------");NL;
if (lconf->ahbstaten) { m_print(" AHBSTATEN");NL; }
if (lconf->wdogen) { m_print(" WDOGEN");NL; }
if (lconf->multiplier) { m_print(" MULTIPLIER");NL; }
if (lconf->divider) { m_print(" DIVIDER");NL; }
if (lconf->macen) { m_print(" MACEN");NL; }
if (lconf->sdramen) { m_print(" SDRAMEN");NL; }
if (lconf->dsu) { m_print(" DSU");NL; }
if (lconf->men) { m_print(" MEN");NL; }
m_print(" DLINE BITS: ");i_print(lconf->dline_bits);NL;
m_print(" DSET SIZE [KB]: ");i_print(1<<lconf->dset_bits);NL;
m_print(" ILINE BITS: ");i_print(lconf->iline_bits);NL;
m_print(" ISET SIZE [KB]: ");i_print(1<<lconf->iset_bits);NL;
m_print(" NWINDOWS: ");i_print(lconf->nwindows+1);NL;
m_print(" WATCHPOINTS: ");i_print(lconf->watchpoints);NL;
m_print(" FPU: ");
switch (lconf->fpu) {
case 0: m_print("NONE"); break;
case 1: m_print("MEIKO/DAIFPU"); break;
case 2: m_print("GRFPU"); break;
default: m_print("DAIFPU");break;
}
NL;
m_print(" PCI: ");
switch (lconf->pci) {
case 0: m_print("NONE"); break;
case 1: m_print("INSILICON"); break;
case 2: m_print("ESA"); break;
default: m_print("OTHER");break;
}
NL;
m_print(" WPROTEN: ");i_print(lconf->wproten);NL;
m_print("");NL;NL;
}
void report_lconf_fpu(lconf_fpu_type *lconf_fpu) {
m_print("DAIFPU");NL;
m_print("------");NL;
if (lconf_fpu->fdiv) { m_print(" FDIV");NL; }
if (lconf_fpu->fsqrt) { m_print(" FSQRT");NL; }
if (lconf_fpu->packed) { m_print(" PACKED");NL; }
if (lconf_fpu->dual) { m_print(" DUAL");NL; }
m_print(" PREC1 EXP BITS: ");i_print(lconf_fpu->exp_hi);NL;
m_print(" PREC1 TRSIG BITS: ");i_print(lconf_fpu->trsig_hi);NL;
if (lconf_fpu->dual) {
m_print(" PREC2 EXP BITS: ");i_print(lconf_fpu->exp_lo);NL;
m_print(" PREC2 TRSIG BITS: ");i_print(lconf_fpu->trsig_lo);NL;
}
m_print("");NL;
}
void report_lconf_swar(lconf_swar_type *lconf_swar) {
if ((lconf_swar->correl)||
(lconf_swar->demod)||
(lconf_swar->audio)||
(lconf_swar->video)||
(lconf_swar->alu)) {
m_print("SWAR UNIT");NL;
m_print("---------");NL;
if (lconf_swar->correl) { m_print(" CORREL");NL; }
if (lconf_swar->demod) { m_print(" DEMOD");NL; }
if (lconf_swar->sincos) { m_print(" SINCOS");NL; }
if (lconf_swar->audio) { m_print(" AUDIO");NL; }
if (lconf_swar->video) { m_print(" VIDEO");NL; }
if (lconf_swar->alu) { m_print(" ALU");NL; }
if (lconf_swar->acc) { m_print(" ACC");NL; }
m_print(" LANES: ");i_print(lconf_swar->lanes);NL;
m_print(" SWIDTH: ");i_print(lconf_swar->swidth);NL;
m_print(" AWIDTH: ");i_print(lconf_swar->awidth);NL;
}
else {
m_print("SWAR UNIT DISABLED");NL;
m_print("------------------");NL;
}
m_print("");NL;
}
/* -----------------------------------------------------------------------------
* Copyright (C) 2020 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : lconf.h
* Authors : Martin Danek
* Description : system register definitions
* Release :
* Version : 1.0
* Date : 18.6.2020
* -----------------------------------------------------------------------------
*/
#ifndef LCONF_H
#define LCONF_H
// LEON2FT configuration register definitions
#define LCONF_BASE 0x80000024
#define LCONF_FPU_BASE LCONF_BASE+4
#define LCONF_SWAR_BASE LCONF_BASE+8
// LCONF CONFIGURATION BITS
#define LCONF_WPROTEN_MSK 0x00000003
#define LCONF_WPROTEN 0x00000001
//
#define LCONF_PCI_MSK 0x0000000C
#define LCONF_PCI_INSILICON 0x00000004
#define LCONF_PCI_ESA 0x00000008
#define LCONF_PCI_OTHER 0x0000000C
//
#define LCONF_FPU_MSK 0x00000030
#define LCONF_FPU_MEIKO 0x00000010
#define LCONF_FPU_GRFPU 0x00000020
#define LCONF_FPU_DAIFPU 0x00000030
//
#define LCONF_AHBSTATEN 0x00000040
#define LCONF_WDOGEN 0x00000080
#define LCONF_MULTIPLIER 0x00000100
#define LCONF_DIVIDER 0x00000200
//
#define LCONF_DLINE_BITS 0x00000C00
#define LCONF_DSIZE 0x00007000
#define LCONF_ILINE_BITS 0x00018000
#define LCONF_ISIZE 0x000E0000
//
#define LCONF_NWINDOWS 0x01F00000
#define LCONF_MACEN 0x02000000
#define LCONF_WATCHPOINTS 0x1C000000
#define LCONF_SDRAMEN 0x20000000
#define LCONF_DSU 0x40000000
#define LCONF_MEN 0x80000000
// LCONF_FPU CONFIGURATION BITS
#define LCONF_FPU_DIV 0x000001
#define LCONF_FPU_SQRT 0x000002
//
#define LCONF_FPU_PACKED 0x000004
#define LCONF_FPU_DUAL 0x000008
//
#define LCONF_FPU_EXPH_BITS 0x0000F0
#define LCONF_FPU_TRSIGH_BITS 0x003F00
#define LCONF_FPU_EXPL_BITS 0x03C000
#define LCONF_FPU_TRSIGL_BITS 0xFC0000
// LCONF_SWAR CONFIGURATION BITS
#define LCONF_SWAR_CORREL 0x00000001
#define LCONF_SWAR_DEMOD 0x00000002
#define LCONF_SWAR_SINCOS 0x00000004
//
#define LCONF_SWAR_AUDIO 0x00000008
#define LCONF_SWAR_VIDEO 0x00000010
#define LCONF_SWAR_ALU 0x00000020
//
#define LCONF_SWAR_ACC 0x00000040
//
#define LCONF_SWAR_LANES 0x001F0000
#define LCONF_SWAR_SWIDTH 0x03E00000
#define LCONF_SWAR_AWIDTH 0xFC000000
// FPU TYPES
#define FPU_NONE 0
#define FPU_MEIKO 1
#define FPU_GRFPU 2
#define FPU_DAIFPU 3
// PCI TYPES
#define PCI_NONE 0
#define PCI_INSILICON 1
#define PCI_ESA 2
#define PCI_OTHER 3
typedef struct lconf_type {
unsigned ahbstaten;
unsigned wdogen;
unsigned multiplier;
unsigned divider;
unsigned macen;
unsigned sdramen;
unsigned dsu;
unsigned men;
unsigned dline_bits;
unsigned dset_bits;
unsigned iline_bits;
unsigned iset_bits;
unsigned nwindows;
unsigned watchpoints;
unsigned fpu;
unsigned pci;
unsigned wproten;
} lconf_type;
typedef struct lconf_fpu_type {
unsigned fdiv;
unsigned fsqrt;
unsigned packed;
unsigned dual;
unsigned exp_hi;
unsigned trsig_hi;
unsigned exp_lo;
unsigned trsig_lo;
} lconf_fpu_type;
typedef struct lconf_swar_type {
unsigned correl;
unsigned demod;
unsigned sincos;
unsigned audio;
unsigned video;
unsigned alu;
unsigned acc;
unsigned lanes;
unsigned swidth;
unsigned awidth;
} lconf_swar_type;
void get_lconf(lconf_type *lconf);
void get_lconf_fpu(lconf_fpu_type *lconf_fpu);
void get_lconf_swar(lconf_swar_type *lconf_swar);
void report_lconf(lconf_type *lconf);
void report_lconf_fpu(lconf_fpu_type *lconf_fpu);
void report_lconf_swar(lconf_swar_type *lconf_swar);
#endif
/* -----------------------------------------------------------------------------
* Copyright (C) 2015-2018 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : leon-myuart.c
* Authors : Martin Danek
* Description : leon2 uart I/O routines
* Release :
* Version : 1.0
* Date : 10.05.2018
* -----------------------------------------------------------------------------
*/
#include "leon-myuart.h"
void delay(int i)
{
#ifndef SIM
int k = 0, j = 0;
for(k = 0; k < i; k++)
{
for(j = 0; j < 40; j++);
__asm__ volatile ("\t nop\n");
}
#endif
}
/* ***************** */
/* UART ROUTINES */
/* */
void init_uart(void) {
cpu_reg_write(APBPIO_DIRECTION,DIRECTION_UARTS);
cpu_reg_write(APBUART1_PRESCALER,SCALER_RELOAD_VALUE);
cpu_reg_write(APBUART1_CONTROL,ENABLE_RX|ENABLE_TX);
}
void m_putchar(unsigned char s) {
int status = 0;
while ((status=(cpu_reg_read(APBUART1_STATUS))&STAT_TH)==0) {
delay(10);
;
}
cpu_reg_write(APBUART1_DATA,s);
while ((status=(cpu_reg_read(APBUART1_STATUS))&STAT_TH)==0) {
delay(10);
;
}
}
unsigned char m_getchar(void) {
int status = 0;
while ((status=(cpu_reg_read(APBUART1_STATUS))&STAT_DR)==0) {
delay(10);
;
}
return cpu_reg_read(APBUART1_DATA);
}
void m_print(unsigned char* s) {
unsigned cnt=200;
unsigned char *l;
l=s;
while ((cnt>0)&&(*l!='\0')) {
if (*l=='\n') {
// m_putchar(0x0D);
m_putchar(0x0A);
}
else {
m_putchar(*l);
}
l++;
cnt--;
}
}
void i_print(int i) {
unsigned char buf[22];
unsigned idx=20;
unsigned neg=0;
buf[21]='\0';
// buf[20]='\n';
if (i==0) {
buf[idx--]='0';
}
else {
if (i<0) {
neg=1;
i=-i;
}
while ((i>0)&&(idx>0)) {
buf[idx--]='0'+(i%10);
i=i/10;
}
if (neg)
buf[idx--]='-';
}
buf[idx]=' ';
m_print(&buf[idx+1]);
}
void i_hexprint(unsigned i) {
unsigned char buf[22];
unsigned idx=20;
unsigned char dgt;
buf[21]='\0';
// buf[20]='\n';
if (i==0) {
buf[idx--]='0';
}
else {
while ((i>0)&&(idx>0)) {
dgt=(i%16);
if (dgt>9)
buf[idx--]='A'+dgt-10;
else
buf[idx--]='0'+dgt;
i=i/16;
}
}
if (idx==19)
buf[idx--]='0';
buf[idx]=' ';
m_print(&buf[idx]);
}
unsigned i_conv(char *s) {
unsigned val=0;
unsigned i=0;
while (*(s+i)!='\0') {
val*=10;
val+=*(s+i)-'0';
i++;
}
return val;
}
unsigned i_hexconv(char *s) {
unsigned val=0;
unsigned i=0;
while (*(s+i)!='\0') {
val*=16;
if ((*(s+i)>='0')&&(*(s+i)<='9'))
val+=*(s+i)-'0';
else if ((*(s+i)>='A')&&(*(s+i)<='F'))
val+=*(s+i)-'A'+10;
else if ((*(s+i)>='a')&&(*(s+i)<='f'))
val+=*(s+i)-'a'+10;
i++;
}
return val;
}
unsigned getval(unsigned char* s, unsigned base) {
char str[25];
char *p_s;
unsigned i=0;
unsigned val=0;
p_s=str;
m_print(s);
do {
str[i++]=m_getchar();
} while ((str[i-1]!=0x0D)&&(str[i-1]!=0x0A)&&(i<25));
str[i-1]='\0';
if (base==16) {
val=i_hexconv(p_s);
i_hexprint(val);
}
else {
val=i_conv(p_s);
i_print(val);
}
m_print("\n");
return val;
}
void dumpMem(unsigned count, void *address, unsigned len) {
unsigned i,j;
for (i=0;i<len;i++) {
if (i%16==0) {
m_print("\nDUMP");
i_print(count);
m_print(": ");
i_hexprint((unsigned)address+i);
}
i_hexprint(*((unsigned char*)address+i));
}
m_print("\nDUMP DONE\n");
}
void dataError(void* a, unsigned sz, unsigned i, unsigned expected) {
m_print("ADDR: ");i_hexprint((unsigned)(a+i*sz));
m_print(" EXPECTED ");i_hexprint(expected);
m_print(" ACTUAL ");i_hexprint(*((unsigned*)a+i));
m_print("\n");
}
/* ***************** */
/* TIMER ROUTINES */
/* */
void init_timer(void) {
cpu_reg_write(APBPRESCALER_RELOAD, TMR_PRESCALER_VALUE);
cpu_reg_write(APBTIMER1_COUNTER, 0);
cpu_reg_write(APBTIMER1_RELOAD, TMR_RELOAD_VALUE); //TIMER_RELOAD_VALUE);
#ifdef USE_BSP_INTERRUPTS
cpu_reg_write(APBINTCTRL_CLEAR, 1<<8);
cpu_reg_write(APBINTCTRL_MASK, 1<<8);
#endif
cpu_reg_write(APBTIMER1_CONTROL, TMR_RUN);
}
void timer_start(void)
{
cpu_reg_write(APBTIMER1_CONTROL, TMR_ENABLE | TMR_LOAD);
}
void timer_stop(void)
{
cpu_reg_write(APBTIMER1_CONTROL, TMR_DISABLE);
}
unsigned int clock(void) {
unsigned int val;
val=cpu_reg_read(APBTIMER1_COUNTER);
return TMR_RELOAD_VALUE-val;
}
#ifdef USE_BSP_INTERRUPTS
extern unsigned int _tmrcnt;
#endif
unsigned int get_time(unsigned int *sec)
{
unsigned int val;
unsigned int tctrl = cpu_reg_read(APBTIMER1_CONTROL);
#ifdef USE_BSP_INTERRUPTS
// disable timer to avoid inconsistency
if (sec && (tctrl & TMR_ENABLE)) cpu_reg_write(APBTIMER1_CONTROL, (tctrl & ~TMR_ENABLE));
#endif
val=cpu_reg_read(APBTIMER1_COUNTER);
val = TMR_RELOAD_VALUE-val;
#ifdef USE_BSP_INTERRUPTS
if (sec) {
*sec = _tmrcnt;
if (tctrl & TMR_ENABLE) cpu_reg_write(APBTIMER1_CONTROL, tctrl);
}
#endif
return val;
}
/* control structure */
#ifndef __ASSEMBLER__
struct lregs {
volatile unsigned int memcfg1; /* 0x00 */
volatile unsigned int memcfg2;
volatile unsigned int ectrl;
volatile unsigned int failaddr;
volatile unsigned int memstatus; /* 0x10 */
volatile unsigned int cachectrl;
volatile unsigned int powerdown;
volatile unsigned int writeprot1;
volatile unsigned int writeprot2; /* 0x20 */
volatile unsigned int leonconf;
volatile unsigned int dummy2;
volatile unsigned int dummy3;
volatile unsigned int dummy4; /* 0x30 */
volatile unsigned int dummy5;
volatile unsigned int dummy6;
volatile unsigned int dummy7;
volatile unsigned int timercnt1; /* 0x40 */
volatile unsigned int timerload1;
volatile unsigned int timerctrl1;
volatile unsigned int wdog;
volatile unsigned int timercnt2;
volatile unsigned int timerload2;
volatile unsigned int timerctrl2;
volatile unsigned int dummy8;
volatile unsigned int scalercnt;
volatile unsigned int scalerload;
volatile unsigned int dummy9;
volatile unsigned int dummy10;
volatile unsigned int uartdata1;
volatile unsigned int uartstatus1;
volatile unsigned int uartctrl1;
volatile unsigned int uartscaler1;
volatile unsigned int uartdata2;
volatile unsigned int uartstatus2;
volatile unsigned int uartctrl2;
volatile unsigned int uartscaler2;
volatile unsigned int irqmask;
volatile unsigned int irqpend;
volatile unsigned int irqforce;
volatile unsigned int irqclear;
volatile unsigned int piodata;
volatile unsigned int piodir;
volatile unsigned int pioirq[2];
volatile unsigned int imask2;
volatile unsigned int ipend2;
volatile unsigned int istat2;
volatile unsigned int dummy12;
volatile unsigned int dcomdata;
volatile unsigned int dcomstatus;
volatile unsigned int dcomctrl;
volatile unsigned int dcomscaler;
volatile unsigned int wprot1a;
volatile unsigned int wprot1e;
volatile unsigned int wprot2a;
volatile unsigned int wprot2e;
};
#endif
/* control registers */
#define PREGS 0x80000000
#define MCFG1 0x00
#define MCFG2 0x04
#define MCFG3 0x08
#define ECTRL 0x08
#define FADDR 0x0c
#define MSTAT 0x10
#define CCTRL 0x14
#define PWDOWN 0x18
#define WPROT1 0x1C
#define WPROT2 0x20
#define LCONF 0x24
#define TCNT0 0x40
#define TRLD0 0x44
#define TCTRL0 0x48
#define TCNT1 0x50
#define TRLD1 0x54
#define TCTRL1 0x58
#define SCNT 0x60
#define SRLD 0x64
#define UDATA0 0x70
#define USTAT0 0x74
#define UCTRL0 0x78
#define USCAL0 0x7c
#define UDATA1 0x80
#define USTAT1 0x84
#define UCTRL1 0x88
#define USCAL1 0x8c
#define IMASK 0x90
#define IPEND 0x94
#define IFORCE 0x98
#define ICLEAR 0x9c
#define IOREG 0xA0
#define IODIR 0xA4
#define IOICONF 0xA8
#define IMASK2 0xB0
#define IPEND2 0xB4
#define ISTAT2 0xB8
#define ICLEAR2 0xB8
/* ASI codes */
#define ASI_PCI 0x4
#define ASI_ITAG 0xC
#define ASI_IDATA 0xD
#define ASI_DTAG 0xE
#define ASI_DDATA 0xF
/* memory areas */
#ifndef CRAM
#define CRAM 0x40040000
#endif
#define SDRAM 0x60000000
#define IOAREA 0x20000000
/* Some bit field masks */
#define CCTRL_FLUSHING_MASK 0x0c000
#define RFE_CONF_BIT 30
#define RFE_CONF_MASK 3
#define CPP_CONF_BIT 19
#define CPP_CONF_MASK 3
#define FPU_CONF_BIT 4
#define FPU_CONF_MASK 3
#define CPTE_MASK (3 << 17)
#define MUL_CONF_BIT 8
#define MAC_CONF_BIT 25
#define DIV_CONF_BIT 9
#define REDAC_CONF_BIT 9
#define PEDAC_CONF_BIT 8
#define MEDAC_CONF_BIT 27
#define MMU_CONF_BIT 31
#define ITE_BIT 12
#define IDE_BIT 10
#define DTE_BIT 8
#define DDE_BIT 6
#define CE_CLEAR 0x3fc0;
/* FSR bit field masks */
#define FSR_RD_BIT 30
#define FSR_RD_MASK 0x03
#define FSR_TEM_BIT 23
#define FSR_TEM_MASK 0x1F
#define FSR_NS_BIT 22
#define FSR_NS_MASK 0x01
#define FSR_VER_BIT 17
#define FSR_VER_MASK 0x07
#define FSR_FTT_BIT 14
#define FSR_FTT_MASK 0x07
#define FSR_QNE_BIT 13
#define FSR_QNE_MASK 0x01
#define FSR_U_BIT 12
#define FSR_U_MASK 0x01
#define FSR_FCC_BIT 10
#define FSR_FCC_MASK 0x03
#define FSR_AEXC_BIT 5
#define FSR_AEXC_MASK 0x1F
#define FSR_CEXC_BIT 0
#define FSR_CEXC_MASK 0x1F
/* simple replacement of memcpy */
#include <stdlib.h>
void *memcpy(void *dest, const void *src, size_t n)
{
char *ps = (char*)src;
char *pd = (char*)dest;
while (n--) {
*pd++ = *ps++;
}
return dest;
}
/* Public domain. */
#include <stddef.h>
void *
memset (void *dest, int val, size_t len)
{
unsigned char *ptr = dest;
while (len-- > 0)
*ptr++ = val;
return dest;
}
This diff is collapsed. Click to expand it.
#include "leon.h"
/* #include "test.h" */
#include "mmu.h"
.seg "text"
/* SRMMU_TFAULT() SRMMU_DFAULT()
* %l0 : %psr
* %l1 = pc :set by trap
* %l2 = npc :set by trap
* %l7 : 1 on inst, 0 on data
*/
.global srmmu_fault, _mmu_switch
_mmu_switch:
srmmu_fault:
jmp %l1 ! reexecute command
rett %l2
.align 8
.global pth_addr, pth_addr1
pth_addr: .word 0
.align 8
pth_addr1: .word 0,0,0,0,0,0,0,0,0
\ No newline at end of file
#ifndef MY_PRINTF_H
#define MY_PRINTF_H
#include <stdarg.h>
#include <stddef.h>
#define FILE void
//#define stdout 0
extern FILE *stderr;
extern FILE *stdout;
#define printf printf_
int printf_(char const *fmt, ...);
#define fprintf fprintf_
int fprintf_(FILE *file, char const *fmt, ...);
#endif
/* from glibs/stdlib/rand.c random.c */
//#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
extern int errno;
/* Linear congruential. */
#define TYPE_0 0
#define BREAK_0 8
#define DEG_0 0
#define SEP_0 0
/* x**7 + x**3 + 1. */
#define TYPE_1 1
#define BREAK_1 32
#define DEG_1 7
#define SEP_1 3
/* x**15 + x + 1. */
#define TYPE_2 2
#define BREAK_2 64
#define DEG_2 15
#define SEP_2 1
/* x**31 + x**3 + 1. */
#define TYPE_3 3
#define BREAK_3 128
#define DEG_3 31
#define SEP_3 3
/* x**63 + x + 1. */
#define TYPE_4 4
#define BREAK_4 256
#define DEG_4 63
#define SEP_4 1
/* Array versions of the above information to make code run faster.
Relies on fact that TYPE_i == i. */
#define MAX_TYPES 5 /* Max number of types above. */
static int32_t randtbl[DEG_3 + 1] =
{
TYPE_3,
-1726662223, 379960547, 1735697613, 1040273694, 1313901226,
1627687941, -179304937, -2073333483, 1780058412, -1989503057,
-615974602, 344556628, 939512070, -1249116260, 1507946756,
-812545463, 154635395, 1388815473, -1926676823, 525320961,
-1009028674, 968117788, -123449607, 1284210865, 435012392,
-2017506339, -911064859, -370259173, 1132637927, 1398500161,
-205601318,
};
static struct random_data unsafe_state =
{
.fptr = &randtbl[SEP_3 + 1],
.rptr = &randtbl[1],
.state = &randtbl[1],
.rand_type = TYPE_3,
.rand_deg = DEG_3,
.rand_sep = SEP_3,
.end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])]
};
int
__random_r (struct random_data *buf, int32_t *result)
{
int32_t *state;
if (buf == NULL || result == NULL)
goto fail;
state = buf->state;
if (buf->rand_type == TYPE_0)
{
int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
}
else
{
int32_t *fptr = buf->fptr;
int32_t *rptr = buf->rptr;
int32_t *end_ptr = buf->end_ptr;
uint32_t val;
val = *fptr += (uint32_t) *rptr;
/* Chucking least random bit. */
*result = val >> 1;
++fptr;
if (fptr >= end_ptr)
{
fptr = state;
++rptr;
}
else
{
++rptr;
if (rptr >= end_ptr)
rptr = state;
}
buf->fptr = fptr;
buf->rptr = rptr;
}
return 0;
fail:
errno = -100; // EINVAL;
return -1;
}
int
__srandom_r (unsigned int seed, struct random_data *buf)
{
int type;
int32_t *state;
long int i;
int32_t word;
int32_t *dst;
int kc;
if (buf == NULL)
goto fail;
type = buf->rand_type;
if ((unsigned int) type >= MAX_TYPES)
goto fail;
state = buf->state;
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
if (seed == 0)
seed = 1;
state[0] = seed;
if (type == TYPE_0)
goto done;
dst = state;
word = seed;
kc = buf->rand_deg;
for (i = 1; i < kc; ++i)
{
/* This does:
state[i] = (16807 * state[i - 1]) % 2147483647;
but avoids overflowing 31 bits. */
long int hi = word / 127773;
long int lo = word % 127773;
word = 16807 * lo - 2836 * hi;
if (word < 0)
word += 2147483647;
*++dst = word;
}
buf->fptr = &state[buf->rand_sep];
buf->rptr = &state[0];
kc *= 10;
while (--kc >= 0)
{
int32_t discard;
(void) __random_r (buf, &discard);
}
done:
return 0;
fail:
return -1;
}
void srand(unsigned int seed)
{
__srandom_r (seed, &unsafe_state);
}
int rand(void)
{
int32_t retval;
(void) __random_r (&unsafe_state, &retval);
return retval;
}
/* from glibs/stdlib/rand.c random.c */
/* there are some changes to allow the second independent generator */
//#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
extern int errno;
/* Linear congruential. */
#define TYPE_0 0
#define BREAK_0 8
#define DEG_0 0
#define SEP_0 0
/* x**7 + x**3 + 1. */
#define TYPE_1 1
#define BREAK_1 32
#define DEG_1 7
#define SEP_1 3
/* x**15 + x + 1. */
#define TYPE_2 2
#define BREAK_2 64
#define DEG_2 15
#define SEP_2 1
/* x**31 + x**3 + 1. */
#define TYPE_3 3
#define BREAK_3 128
#define DEG_3 31
#define SEP_3 3
/* x**63 + x + 1. */
#define TYPE_4 4
#define BREAK_4 256
#define DEG_4 63
#define SEP_4 1
/* Array versions of the above information to make code run faster.
Relies on fact that TYPE_i == i. */
#define MAX_TYPES 5 /* Max number of types above. */
static int32_t randtbl[DEG_3 + 1] =
{
TYPE_3,
-1726662223, 379960547, 1735697613, 1040273694, 1313901226,
1627687941, -179304937, -2073333483, 1780058412, -1989503057,
-615974602, 344556628, 939512070, -1249116260, 1507946756,
-812545463, 154635395, 1388815473, -1926676823, 525320961,
-1009028674, 968117788, -123449607, 1284210865, 435012392,
-2017506339, -911064859, -370259173, 1132637927, 1398500161,
-205601318,
};
static struct random_data unsafe_state =
{
.fptr = &randtbl[SEP_3 + 1],
.rptr = &randtbl[1],
.state = &randtbl[1],
.rand_type = TYPE_3,
.rand_deg = DEG_3,
.rand_sep = SEP_3,
.end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])]
};
int
__random_r2 (struct random_data *buf, int32_t *result)
{
int32_t *state;
if (buf == NULL || result == NULL)
goto fail;
state = buf->state;
if (buf->rand_type == TYPE_0)
{
int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
state[0] = val;
*result = val;
}
else
{
int32_t *fptr = buf->fptr;
int32_t *rptr = buf->rptr;
int32_t *end_ptr = buf->end_ptr;
uint32_t val;
val = *fptr += (uint32_t) *rptr;
/* Chucking least random bit. */
*result = val >> 1;
++fptr;
if (fptr >= end_ptr)
{
fptr = state;
++rptr;
}
else
{
++rptr;
if (rptr >= end_ptr)
rptr = state;
}
buf->fptr = fptr;
buf->rptr = rptr;
}
return 0;
fail:
errno = -100; // EINVAL;
return -1;
}
int
__srandom_r2 (unsigned int seed, struct random_data *buf)
{
int type;
int32_t *state;
long int i;
int32_t word;
int32_t *dst;
int kc;
if (buf == NULL)
goto fail;
type = buf->rand_type;
if ((unsigned int) type >= MAX_TYPES)
goto fail;
state = buf->state;
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
if (seed == 0)
seed = 1;
state[0] = seed;
if (type == TYPE_0)
goto done;
dst = state;
word = seed;
kc = buf->rand_deg;
for (i = 1; i < kc; ++i)
{
/* This does:
state[i] = (16807 * state[i - 1]) % 2147483647;
but avoids overflowing 31 bits. */
long int hi = word / 127773;
long int lo = word % 127773;
word = 16807 * lo - 2836 * hi;
if (word < 0)
word += 2147483647;
*++dst = word;
}
buf->fptr = &state[buf->rand_sep];
buf->rptr = &state[0];
kc *= 10;
while (--kc >= 0)
{
int32_t discard;
(void) __random_r2 (buf, &discard);
}
done:
return 0;
fail:
return -1;
}
void srand2(unsigned int seed)
{
__srandom_r2 (seed, &unsafe_state);
}
int rand2(void)
{
int32_t retval;
(void) __random_r2 (&unsafe_state, &retval);
return retval;
}
/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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 2.1 of the License, or (at your option) any later version.
The GNU C Library 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 the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <string.h>
#undef strcmp
#ifndef STRCMP
# define STRCMP strcmp
#endif
/* Compare S1 and S2, returning less than, equal to or
greater than zero if S1 is lexicographically less than,
equal to or greater than S2. */
int
STRCMP (const char *p1, const char *p2)
{
const unsigned char *s1 = (const unsigned char *) p1;
const unsigned char *s2 = (const unsigned char *) p2;
unsigned char c1, c2;
do
{
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0')
return c1 - c2;
}
while (c1 == c2);
return c1 - c2;
}
//libc_hidden_builtin_def (strcmp)
/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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 2.1 of the License, or (at your option) any later version.
The GNU C Library 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 the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <string.h>
#undef strcpy
#ifndef STRCPY
# define STRCPY strcpy
#endif
/* Copy SRC to DEST. */
char *
STRCPY (char *dest, const char *src)
{
return memcpy (dest, src, strlen (src) + 1);
}
//libc_hidden_builtin_def (strcpy)
/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Torbjorn Granlund (tege@sics.se),
with help from Dan Sahlin (dan@sics.se);
commentary by Jim Blandy (jimb@ai.mit.edu).
The GNU C Library 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 2.1 of the License, or (at your option) any later version.
The GNU C Library 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 the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <string.h>
#include <stdlib.h>
#undef strlen
#ifndef STRLEN
# define STRLEN strlen
#endif
size_t strlen(const char *str)
{
size_t i=0;
if (!str) return 0;
while (str[i])
i++;
return i;
}
///* Return the length of the null-terminated string STR. Scan for
// the null terminator quickly by testing four bytes at a time. */
//size_t
//STRLEN (const char *str)
//{
// const char *char_ptr;
// const unsigned long int *longword_ptr;
// unsigned long int longword, himagic, lomagic;
// /* Handle the first few characters by reading one character at a time.
// Do this until CHAR_PTR is aligned on a longword boundary. */
// for (char_ptr = str; ((unsigned long int) char_ptr
// & (sizeof (longword) - 1)) != 0;
// ++char_ptr)
// if (*char_ptr == '\0')
// return char_ptr - str;
// /* All these elucidatory comments refer to 4-byte longwords,
// but the theory applies equally well to 8-byte longwords. */
// longword_ptr = (unsigned long int *) char_ptr;
// /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
// the "holes." Note that there is a hole just to the left of
// each byte, with an extra at the end:
// bits: 01111110 11111110 11111110 11111111
// bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
// The 1-bits make sure that carries propagate to the next 0-bit.
// The 0-bits provide holes for carries to fall into. */
// himagic = 0x80808080L;
// lomagic = 0x01010101L;
// if (sizeof (longword) > 4)
// {
// /* 64-bit version of the magic. */
// /* Do the shift in two steps to avoid a warning if long has 32 bits. */
// himagic = ((himagic << 16) << 16) | himagic;
// lomagic = ((lomagic << 16) << 16) | lomagic;
// }
// if (sizeof (longword) > 8)
// abort ();
// /* Instead of the traditional loop which tests each character,
// we will test a longword at a time. The tricky part is testing
// if *any of the four* bytes in the longword in question are zero. */
// for (;;)
// {
// longword = *longword_ptr++;
// if (((longword - lomagic) & ~longword & himagic) != 0)
// {
// /* Which of the bytes was the zero? If none of them were, it was
// a misfire; continue the search. */
// const char *cp = (const char *) (longword_ptr - 1);
// if (cp[0] == 0)
// return cp - str;
// if (cp[1] == 0)
// return cp - str + 1;
// if (cp[2] == 0)
// return cp - str + 2;
// if (cp[3] == 0)
// return cp - str + 3;
// if (sizeof (longword) > 4)
// {
// if (cp[4] == 0)
// return cp - str + 4;
// if (cp[5] == 0)
// return cp - str + 5;
// if (cp[6] == 0)
// return cp - str + 6;
// if (cp[7] == 0)
// return cp - str + 7;
// }
// }
// }
//}
////libc_hidden_builtin_def (strlen)
/* simple replacement of strtol */
#include <stdlib.h>
#include <limits.h>
long long int internal_strtol(const char *nptr, char **endptr, int base)
{
long long int res = 0;
long int dig;
int sign = 0;
do {
/* skip spaces (isspace) */
while (*nptr==' ' || *nptr=='\t' || *nptr=='\n' ||
*nptr=='\v' || *nptr=='\f' || *nptr=='\r') {
nptr++;
}
if (*nptr==0) break;
/* test sign */
if (*nptr=='-' || *nptr=='+') {
if (*nptr=='-') sign = 1;
nptr++;
}
if (*nptr==0) break;
/* select base if base was 0 */
if (base==0 && *nptr=='0') {
nptr++;
if (*nptr==0) break;
if (*nptr=='b') base = 2;
else if (*nptr=='x') base = 16;
else base = 8;
}
if (base==0) base = 10;
/* read digits in the loop */
do {
if (*nptr==0) break;
if (*nptr>='0' && *nptr<='9')
dig = *nptr-'0';
else if (*nptr>='A' && *nptr<='Z')
dig = *nptr - 'A' + 10;
else if (*nptr>='a' && *nptr<='z')
dig = *nptr - 'a' + 10;
else
break;
if (dig<0 || dig>=base) break;
res = res*base + dig;
nptr++;
} while(1);
} while(0);
if (endptr) *endptr = (char *)nptr;
if (sign) res = -res;
return res;
}
long int strtol(const char *nptr, char **endptr, int base)
{
long long ir = internal_strtol(nptr, endptr, base);
if (ir<LONG_MIN) return LONG_MIN;
if (ir>LONG_MAX) return LONG_MAX;
return (long)ir;
}
unsigned long int strtoul(const char *nptr, char **endptr, int base)
{
long long ir = internal_strtol(nptr, endptr, base);
if (ir<0) return 0;
if (ir>ULONG_MAX) return ULONG_MAX;
return (unsigned long) ir;
}
/* stub with functions replacing some system calling */
//#include <stdio.h>
#include "my_printf.h"
//struct _IO_FILE {
// int dumb;
//};
FILE *stderr = NULL;
FILE *stdout = NULL;
int errno = 0;
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler)
{
return handler;
}
void exit(int status)
{
(void) status;
asm("mov %psr,%g1");
asm("sub %g0,33,%g2");
asm("and %g1,%g2,%g1");
asm("mov %g1,%psr");
asm("nop");
asm("ta 0");
asm("nop");
asm("nop");
asm("nop");
while(1) ;
}
int fputs(const char *s, FILE *stream)
{
printf_(s);
return 0;
}
int puts(const char *s)
{
printf_(s);
return 0;
}
int fputc(int c, FILE *stream)
{
printf_("%c",c);
return c;
}
int putc(int c, FILE *stream)
{
printf_("%c",c);
return c;
}
int fflush(FILE *stream)
{
return 0;
}
int my_vfprintf(FILE *stream, const char *format, ...);
#undef fprintf
int fprintf(FILE *stream, const char *format, ...)
{
va_list arg;
int length;
va_start(arg, format);
length = my_vfprintf(stream, format, arg);
va_end(arg);
return length;
}
#undef printf
int printf(const char *format, ...)
{
va_list arg;
int length;
va_start(arg, format);
length = my_vfprintf(stdout, format, arg);
va_end(arg);
return length;
}
int vfprintf(FILE *stream, const char *format, va_list ap)
{
return my_vfprintf(stream, format, ap);
}
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
// TODO ... for -O3 fputs is sometimes replaced by fwrite
}
#ifndef __SYSTEM_STUB_HEADER_FILE__
#define __SYSTEM_STUB_HEADER_FILE__
void *memset(void *s, int c, size_t n);
/* random.c */
void srand(unsigned int seed);
int rand(void);
void srand2(unsigned int seed);
int rand2(void);
#endif /* __SYSTEM_STUB_HEADER_FILE__ */
/* -----------------------------------------------------------------------------
* Copyright (C) 2020 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : sysregs.c
* Authors : Martin Danek
* Description : system register definitions
* Release :
* Version : 1.0
* Date : 14.6.2020
* -----------------------------------------------------------------------------
*/
#include "asi.h"
#include "asm.h"
#include "sysregs.h"
void sysregs_init() {
wr_asr(SYSREGS_CTL_ASR, SYSREGS_RST);
wr_asr(SYSREGS_CTL_ASR, SYSREGS_START);
}
void sysregs_start() {
wr_asr(SYSREGS_CTL_ASR, SYSREGS_START);
}
void sysregs_stop() {
wr_asr(SYSREGS_CTL_ASR, SYSREGS_STOP);
}
void sysregs_read(unsigned *ticks_lo, unsigned *ticks_hi, unsigned *insns) {
wr_asr(SYSREGS_CTL_ASR, SYSREGS_TICKS_LO);
rd_asr(SYSREGS_CTL_ASR, *ticks_lo);
wr_asr(SYSREGS_CTL_ASR, SYSREGS_TICKS_HI);
rd_asr(SYSREGS_CTL_ASR, *ticks_hi);
wr_asr(SYSREGS_CTL_ASR, SYSREGS_INSNS);
rd_asr(SYSREGS_CTL_ASR, *insns);
}
/* -----------------------------------------------------------------------------
* Copyright (C) 2020 daiteq s.r.o. http://www.daiteq.com
*
* This program is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
* -----------------------------------------------------------------------------
* Filename : sysregs.h
* Authors : Martin Danek
* Description : system register definitions
* Release :
* Version : 1.0
* Date : 14.6.2020
* -----------------------------------------------------------------------------
*/
#ifndef SYSREGS_H
#define SYSREGS_H
// SYSREGS configuration register definitions
#define SYSREGS_TICKS_LO 0x0
#define SYSREGS_TICKS_HI 0x1
#define SYSREGS_INSNS 0x2
#define SYSREGS_RST 0x8
#define SYSREGS_START 0x4
#define SYSREGS_STOP 0x0
void sysregs_init();
void sysregs_start();
void sysregs_stop();
void sysregs_read(unsigned *ticks_lo, unsigned *ticks_hi, unsigned *insns);
#endif
#define MSGAREA IOAREA
#define PRINT(X) set MSGAREA, %o0; ld [%o0 + X*4], %g0
#define FAIL(X) set MSGAREA, %o0; st %g0, [%o0 + X*4]
#define SYS_TEST 0
#define CACHE_TEST 1
#define REG_TEST 2
#define MUL_TEST 3
#define DIV_TEST 4
#define WATCH_TEST 5
#define SNOOP_TEST 6
#define FPU_TEST 7
#define PCI_TEST 8
#define RAM_INIT 9
#define IRQ_TEST 10
#define TIMER_TEST 11
#define UART_TEST 12
#define PIO_TEST 13
#define EDAC_TEST 14
#define DMA_TEST 15
#define DPRAM_TEST 16
#define CRAM_TEST 17
#define MEM_TEST 18
#define TEST_END 19
#define WP_TEST 20
#define DSU_TEST 21
#define MMU_TEST 23
#define ITAG_VALID_MASK ((1 << ILINESZ) -1)
#define ITAG_MAX_ADDRESS ((1 << ITAG_BITS) -1) << (ILINEBITS + 2)
#define DTAG_VALID_MASK ((1 << DLINESZ) -1)
#define DTAG_MAX_ADDRESS ((1 << DTAG_BITS) -1) << (DLINEBITS + 2)
#ifndef __ASSEMBLER__
extern struct lregs *lr;
extern int test;
#endif
# Makefile for building builtins library
$(info >>> L-builtins <<< T=$(TOP) D=$(DSTPATH) I=$(INCPATH) B=$(BLDPATH) CF=$(APPCFLAGS) F=$(FPUCFG) )
EXPHDRS=
SOURCES=$(wildcard *.c)
OBJS=$(SOURCES:%.c=$(BLDPATH)/%.o)
DISS=$(SOURCES:%.c=$(BLDPATH)/%.dis)
LIBRARY=libins
ifeq ($(TOOL),llvm)
CC=clang
TOOLCHAIN=sparc-daiteq-elf
#CFLAGS=-msoft-float -O3
CFLAGS+=-target $(TOOLCHAIN) -mcpu=leon2
# TODO: asm options according to selected type of FPU
CFLAGS+=-Xassembler --has-fhalf -Xassembler --has-fpack -Xassembler -Aleon
endif
ifeq ($(TOOL),gcc)
TOOLCHAIN=sparc-gaisler-elf
CC=$(TOOLCHAIN)-gcc
CFLAGS+=-mcpu=leon -qbsp=leon2 -mfix-at697f
endif
CFLAGS+=-ffunction-sections -fdata-sections
CFLAGS+=-I. -I$(SFDIR)/source/include
FPUTYPE=-daiteq-fpu-type=$(FPUCFG)
AR=$(TOOLCHAIN)-ar
.PHONY: all clean export
all: export
@echo "Library is created"
$(BLDPATH):
@mkdir -p $(BLDPATH)
$(BLDPATH)/$(LIBRARY).a: $(OBJS)
@$(AR) crs $@ $^
$(BLDPATH)/%.o:%.c
@$(CC) $(FPUTYPE) $(CFLAGS) -c $< -o $@
$(BLDPATH)/%.dis:$(BLDPATH)/%.o
@$(TOOLCHAIN)-objdump -S $< > $@
clean:
rm -rf $(BLDPATH)
export: $(DSTPATH)/$(LIBRARY).a $(DISS) $(EXPHDRS:%=$(INCPATH)/%)
@echo "Library is exported"
$(DSTPATH)/$(LIBRARY).a: $(BLDPATH) $(BLDPATH)/$(LIBRARY).a
@cp $(BLDPATH)/$(LIBRARY).a $(DSTPATH)
$(INCPATH)/%: $(SOURCE_DIR)/%
ln -sf $< $@
//===-- lib/absdf2.c - Double-precision subtraction ---------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
#define DOUBLE_PRECISION
#include "fp_lib.h"
// Subtraction; flip the sign bit of b and add.
COMPILER_RT_ABI fp_t
__absdf2(fp_t a) {
// const unsigned int ai = toRep(a) & ~signBit;
return fromRep(toRep(a) & absMask);
}
//===-- lib/abssf2.c - Single-precision subtraction ---------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
#define SINGLE_PRECISION
#include "fp_lib.h"
// Subtraction; flip the sign bit of b and add.
COMPILER_RT_ABI fp_t
__abssf2(fp_t a) {
// const unsigned int ai = toRep(a) & ~signBit;
return fromRep(toRep(a) & absMask);
}
/* ====-- ashldi3.c - Implement __ashldi3 -----------------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __ashldi3 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
/* Returns: a << b */
/* Precondition: 0 <= b < bits_in_dword */
COMPILER_RT_ABI di_int
__ashldi3(di_int a, si_int b)
{
const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
dwords input;
dwords result;
input.all = a;
if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */
{
result.s.low = 0;
result.s.high = input.s.low << (b - bits_in_word);
}
else /* 0 <= b < bits_in_word */
{
if (b == 0)
return a;
result.s.low = input.s.low << b;
result.s.high = (input.s.high << b) | (input.s.low >> (bits_in_word - b));
}
return result.all;
}
#if defined(__ARM_EABI__)
AEABI_RTABI di_int __aeabi_llsl(di_int a, si_int b) COMPILER_RT_ALIAS(__ashldi3);
#endif
//===-- ashrdi3.c - Implement __ashrdi3 -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __ashrdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: arithmetic a >> b
// Precondition: 0 <= b < bits_in_dword
COMPILER_RT_ABI di_int __ashrdi3(di_int a, si_int b) {
const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
dwords input;
dwords result;
input.all = a;
if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ {
// result.s.high = input.s.high < 0 ? -1 : 0
result.s.high = input.s.high >> (bits_in_word - 1);
result.s.low = input.s.high >> (b - bits_in_word);
} else /* 0 <= b < bits_in_word */ {
if (b == 0)
return a;
result.s.high = input.s.high >> b;
result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b);
}
return result.all;
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__ashrdi3, __aeabi_lasr)
#endif
//===-- bswapdi2.c - Implement __bswapdi2 ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __bswapdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
COMPILER_RT_ABI uint64_t __bswapdi2(uint64_t u) {
return (
(((u)&0xff00000000000000ULL) >> 56) |
(((u)&0x00ff000000000000ULL) >> 40) |
(((u)&0x0000ff0000000000ULL) >> 24) |
(((u)&0x000000ff00000000ULL) >> 8) |
(((u)&0x00000000ff000000ULL) << 8) |
(((u)&0x0000000000ff0000ULL) << 24) |
(((u)&0x000000000000ff00ULL) << 40) |
(((u)&0x00000000000000ffULL) << 56));
}
//===-- bswapsi2.c - Implement __bswapsi2 ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __bswapsi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
COMPILER_RT_ABI uint32_t __bswapsi2(uint32_t u) {
return ((((u)&0xff000000) >> 24) |
(((u)&0x00ff0000) >> 8) |
(((u)&0x0000ff00) << 8) |
(((u)&0x000000ff) << 24));
}
//===-- clzdi2.c - Implement __clzdi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __clzdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: the number of leading 0-bits
#if !defined(__clang__) && \
((defined(__sparc__) && defined(__arch64__)) || defined(__mips64) || \
(defined(__riscv) && __SIZEOF_POINTER__ >= 8))
// On 64-bit architectures with neither a native clz instruction nor a native
// ctz instruction, gcc resolves __builtin_clz to __clzdi2 rather than
// __clzsi2, leading to infinite recursion.
#define __builtin_clz(a) __clzsi2(a)
extern si_int __clzsi2(si_int);
#endif
// Precondition: a != 0
COMPILER_RT_ABI si_int __clzdi2(di_int a) {
dwords x;
x.all = a;
const si_int f = -(x.s.high == 0);
return __builtin_clz((x.s.high & ~f) | (x.s.low & f)) +
(f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
}
//===-- clzsi2.c - Implement __clzsi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __clzsi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: the number of leading 0-bits
// Precondition: a != 0
COMPILER_RT_ABI si_int __clzsi2(si_int a) {
su_int x = (su_int)a;
si_int t = ((x & 0xFFFF0000) == 0) << 4; // if (x is small) t = 16 else 0
x >>= 16 - t; // x = [0 - 0xFFFF]
su_int r = t; // r = [0, 16]
// return r + clz(x)
t = ((x & 0xFF00) == 0) << 3;
x >>= 8 - t; // x = [0 - 0xFF]
r += t; // r = [0, 8, 16, 24]
// return r + clz(x)
t = ((x & 0xF0) == 0) << 2;
x >>= 4 - t; // x = [0 - 0xF]
r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28]
// return r + clz(x)
t = ((x & 0xC) == 0) << 1;
x >>= 2 - t; // x = [0 - 3]
r += t; // r = [0 - 30] and is even
// return r + clz(x)
// switch (x)
// {
// case 0:
// return r + 2;
// case 1:
// return r + 1;
// case 2:
// case 3:
// return r;
// }
return r + ((2 - x) & -((x & 2) == 0));
}
//===-- cmpdi2.c - Implement __cmpdi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __cmpdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: if (a < b) returns 0
// if (a == b) returns 1
// if (a > b) returns 2
COMPILER_RT_ABI si_int __cmpdi2(di_int a, di_int b) {
dwords x;
x.all = a;
dwords y;
y.all = b;
if (x.s.high < y.s.high)
return 0;
if (x.s.high > y.s.high)
return 2;
if (x.s.low < y.s.low)
return 0;
if (x.s.low > y.s.low)
return 2;
return 1;
}
#ifdef __ARM_EABI__
// Returns: if (a < b) returns -1
// if (a == b) returns 0
// if (a > b) returns 1
COMPILER_RT_ABI si_int __aeabi_lcmp(di_int a, di_int b) {
return __cmpdi2(a, b) - 1;
}
#endif
//===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// // This file implements the following soft-float comparison routines:
//
// __eqdf2 __gedf2 __unorddf2
// __ledf2 __gtdf2
// __ltdf2
// __nedf2
//
// The semantics of the routines grouped in each column are identical, so there
// is a single implementation for each, and wrappers to provide the other names.
//
// The main routines behave as follows:
//
// __ledf2(a,b) returns -1 if a < b
// 0 if a == b
// 1 if a > b
// 1 if either a or b is NaN
//
// __gedf2(a,b) returns -1 if a < b
// 0 if a == b
// 1 if a > b
// -1 if either a or b is NaN
//
// __unorddf2(a,b) returns 0 if both a and b are numbers
// 1 if either a or b is NaN
//
// Note that __ledf2( ) and __gedf2( ) are identical except in their handling of
// NaN values.
//
//===----------------------------------------------------------------------===//
#define DOUBLE_PRECISION
#include "fp_lib.h"
enum LE_RESULT {
LE_LESS = -1,
LE_EQUAL = 0,
LE_GREATER = 1,
LE_UNORDERED = 1
};
COMPILER_RT_ABI enum LE_RESULT
__ledf2(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
// If either a or b is NaN, they are unordered.
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
// If a and b are both zeros, they are equal.
if ((aAbs | bAbs) == 0) return LE_EQUAL;
// If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a floating-point compare.
if ((aInt & bInt) >= 0) {
if (aInt < bInt) return LE_LESS;
else if (aInt == bInt) return LE_EQUAL;
else return LE_GREATER;
}
// Otherwise, both are negative, so we need to flip the sense of the
// comparison to get the correct result. (This assumes a twos- or ones-
// complement integer representation; if integers are represented in a
// sign-magnitude representation, then this flip is incorrect).
else {
if (aInt > bInt) return LE_LESS;
else if (aInt == bInt) return LE_EQUAL;
else return LE_GREATER;
}
}
#if defined(__ELF__)
// Alias for libgcc compatibility
FNALIAS(__cmpdf2, __ledf2);
#endif
enum GE_RESULT {
GE_LESS = -1,
GE_EQUAL = 0,
GE_GREATER = 1,
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
};
COMPILER_RT_ABI enum GE_RESULT
__gedf2(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
if ((aAbs | bAbs) == 0) return GE_EQUAL;
if ((aInt & bInt) >= 0) {
if (aInt < bInt) return GE_LESS;
else if (aInt == bInt) return GE_EQUAL;
else return GE_GREATER;
} else {
if (aInt > bInt) return GE_LESS;
else if (aInt == bInt) return GE_EQUAL;
else return GE_GREATER;
}
}
COMPILER_RT_ABI int
__unorddf2(fp_t a, fp_t b) {
const rep_t aAbs = toRep(a) & absMask;
const rep_t bAbs = toRep(b) & absMask;
return aAbs > infRep || bAbs > infRep;
}
// The following are alternative names for the preceding routines.
COMPILER_RT_ABI enum LE_RESULT
__eqdf2(fp_t a, fp_t b) {
return __ledf2(a, b);
}
COMPILER_RT_ABI enum LE_RESULT
__ltdf2(fp_t a, fp_t b) {
return __ledf2(a, b);
}
COMPILER_RT_ABI enum LE_RESULT
__nedf2(fp_t a, fp_t b) {
return __ledf2(a, b);
}
COMPILER_RT_ABI enum GE_RESULT
__gtdf2(fp_t a, fp_t b) {
return __gedf2(a, b);
}
#if defined(__ARM_EABI__)
#if defined(COMPILER_RT_ARMHF_TARGET)
AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) {
return __unorddf2(a, b);
}
#else
AEABI_RTABI int __aeabi_dcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unorddf2);
#endif
#endif
/* -------------------------------------------------------------------------- */
enum CMP_RESULT {
CMP_LESS = -1,
CMP_EQUAL = 0,
CMP_GREATER = 1,
CMP_UNORDERED = 3 // Note: different from LE_UNORDERED, GE_UNORDERED
};
#define _DOUBLE_IS_SIGNAN(x) \
( \
(x##Exponent==2047) ? \
( (!x##Fract==0 && !(x##Fract & ((rep_t)1<<(53-2) % typeWidth))) ? \
(1) ? \
(0) \
) : \
(0) \
)
COMPILER_RT_ABI enum CMP_RESULT _D_cmp(fp_t a, fp_t b)
{
rep_t A = toRep(a);
rep_t B = toRep(b);
enum CMP_RESULT ret;
const rep_t aExponent = A >> significandBits & maxExponent;
const rep_t bExponent = B >> significandBits & maxExponent;
const rep_t aFract = A & significandMask;
const rep_t bFract = B & significandMask;
const rep_t aSign = A & signBit;
const rep_t bSign = B & signBit;
/* NANs are unordered. */
if ((bExponent == 2047 && !(bFract==0) )
|| (aExponent == 2047 && !(aFract==0))) {
ret = CMP_UNORDERED;
// check NAN
// if (_HALF_IS_SIGNAN(b) || _HALF_IS_SIGNAN(a) FP_SET_EXCEPTION (FP_EX_INVALID);
} else {
int aIsZero, bIsZero;
bIsZero = (!bExponent && (bFract == 0)) ? 1 : 0;
aIsZero = (!aExponent && (aFract == 0)) ? 1 : 0;
if (bIsZero && aIsZero)
ret = 0;
else if (bIsZero)
ret = aSign ? 1 : -1;
else if (aIsZero)
ret = bSign ? -1 : 1;
else if (bSign != aSign)
ret = bSign ? -1 : 1;
else if (bExponent > aExponent)
ret = bSign ? -1 : 1;
else if (bExponent < aExponent)
ret = bSign ? 1 : -1;
else if (bFract > aFract)
ret = bSign ? -1 : 1;
else if (aFract > bFract)
ret = bSign ? 1 : -1;
else
ret = 0;
}
// if (ret == -1) ret = 2;
return ret;
}
//===-- lib/comparehf2.c - Half-precision comparisons -----------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the following soft-fp_t comparison routines:
//
// __eqhf2 __gehf2 __unordhf2
// __lehf2 __gthf2
// __lthf2
// __nehf2
//
// The semantics of the routines grouped in each column are identical, so there
// is a single implementation for each, and wrappers to provide the other names.
//
// The main routines behave as follows:
//
// __lehf2(a,b) returns -1 if a < b
// 0 if a == b
// 1 if a > b
// 1 if either a or b is NaN
//
// __gehf2(a,b) returns -1 if a < b
// 0 if a == b
// 1 if a > b
// -1 if either a or b is NaN
//
// __unordhf2(a,b) returns 0 if both a and b are numbers
// 1 if either a or b is NaN
//
// Note that __lehf2( ) and __gehf2( ) are identical except in their handling of
// NaN values.
//
//===----------------------------------------------------------------------===//
#define HALF_PRECISION
#include "fp_lib.h"
enum LE_RESULT {
LE_LESS = -1,
LE_EQUAL = 0,
LE_GREATER = 1,
LE_UNORDERED = 1
};
COMPILER_RT_ABI enum LE_RESULT
__lehf2(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
// If either a or b is NaN, they are unordered.
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
// If a and b are both zeros, they are equal.
if ((aAbs | bAbs) == 0) return LE_EQUAL;
// If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a fp_ting-point compare.
if ((aInt & bInt) >= 0) {
if (aInt < bInt) return LE_LESS;
else if (aInt == bInt) return LE_EQUAL;
else return LE_GREATER;
}
// Otherwise, both are negative, so we need to flip the sense of the
// comparison to get the correct result. (This assumes a twos- or ones-
// complement integer representation; if integers are represented in a
// sign-magnitude representation, then this flip is incorrect).
else {
if (aInt > bInt) return LE_LESS;
else if (aInt == bInt) return LE_EQUAL;
else return LE_GREATER;
}
}
#if defined(__ELF__)
// Alias for libgcc compatibility
FNALIAS(__cmphf2, __lehf2);
#endif
enum GE_RESULT {
GE_LESS = -1,
GE_EQUAL = 0,
GE_GREATER = 1,
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
};
COMPILER_RT_ABI enum GE_RESULT
__gehf2(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
if ((aAbs | bAbs) == 0) return GE_EQUAL;
if ((aInt & bInt) >= 0) {
if (aInt < bInt) return GE_LESS;
else if (aInt == bInt) return GE_EQUAL;
else return GE_GREATER;
} else {
if (aInt > bInt) return GE_LESS;
else if (aInt == bInt) return GE_EQUAL;
else return GE_GREATER;
}
}
COMPILER_RT_ABI int
__unordhf2(fp_t a, fp_t b) {
const rep_t aAbs = toRep(a) & absMask;
const rep_t bAbs = toRep(b) & absMask;
return aAbs > infRep || bAbs > infRep;
}
// The following are alternative names for the preceding routines.
COMPILER_RT_ABI enum LE_RESULT
__eqhf2(fp_t a, fp_t b) {
return __lehf2(a, b);
}
COMPILER_RT_ABI enum LE_RESULT
__lthf2(fp_t a, fp_t b) {
return __lehf2(a, b);
}
COMPILER_RT_ABI enum LE_RESULT
__nehf2(fp_t a, fp_t b) {
return __lehf2(a, b);
}
COMPILER_RT_ABI enum GE_RESULT
__gthf2(fp_t a, fp_t b) {
return __gehf2(a, b);
}
#if defined(__ARM_EABI__)
#if defined(COMPILER_RT_ARMHF_TARGET)
AEABI_RTABI int __aeabi_hcmpun(fp_t a, fp_t b) {
return __unordhf2(a, b);
}
#else
AEABI_RTABI int __aeabi_hcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unordhf2);
#endif
#endif
/* -------------------------------------------------------------------------- */
enum CMP_RESULT {
CMP_LESS = -1,
CMP_EQUAL = 0,
CMP_GREATER = 1,
CMP_UNORDERED = 3 // Note: different from LE_UNORDERED, GE_UNORDERED
};
#define _HALF_IS_SIGNAN(x) \
( \
(x##Exponent==31) ? \
( (!x##Fract==0 && !(x##Fract & (1<<(11-2)))) ? \
(1) ? \
(0) \
) : \
(0) \
)
COMPILER_RT_ABI enum CMP_RESULT _H_cmp(fp_t a, fp_t b)
{
rep_t A = toRep(a);
rep_t B = toRep(b);
enum CMP_RESULT ret;
const rep_t aExponent = (A >> significandBits) & maxExponent;
const rep_t bExponent = (B >> significandBits) & maxExponent;
const rep_t aFract = A & significandMask;
const rep_t bFract = B & significandMask;
const rep_t aSign = A & signBit;
const rep_t bSign = B & signBit;
/* NANs are unordered. */
if ((bExponent == 31 && !(bFract==0) )
|| (aExponent == 31 && !(aFract==0))) {
ret = CMP_UNORDERED;
// check NAN
// if (_HALF_IS_SIGNAN(b) || _HALF_IS_SIGNAN(a) FP_SET_EXCEPTION (FP_EX_INVALID);
} else {
int aIsZero, bIsZero;
bIsZero = (!bExponent && (bFract == 0)) ? 1 : 0;
aIsZero = (!aExponent && (aFract == 0)) ? 1 : 0;
if (bIsZero && aIsZero)
ret = 0;
else if (bIsZero)
ret = aSign ? 1 : -1;
else if (aIsZero)
ret = bSign ? -1 : 1;
else if (bSign != aSign)
ret = bSign ? -1 : 1;
else if (bExponent > aExponent)
ret = bSign ? -1 : 1;
else if (bExponent < aExponent)
ret = bSign ? 1 : -1;
else if (bFract > aFract)
ret = bSign ? -1 : 1;
else if (aFract > bFract)
ret = bSign ? 1 : -1;
else
ret = 0;
}
// if (ret == -1) ret = 2;
return ret;
}
//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the following soft-fp_t comparison routines:
//
// __eqsf2 __gesf2 __unordsf2
// __lesf2 __gtsf2
// __ltsf2
// __nesf2
//
// The semantics of the routines grouped in each column are identical, so there
// is a single implementation for each, and wrappers to provide the other names.
//
// The main routines behave as follows:
//
// __lesf2(a,b) returns -1 if a < b
// 0 if a == b
// 1 if a > b
// 1 if either a or b is NaN
//
// __gesf2(a,b) returns -1 if a < b
// 0 if a == b
// 1 if a > b
// -1 if either a or b is NaN
//
// __unordsf2(a,b) returns 0 if both a and b are numbers
// 1 if either a or b is NaN
//
// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of
// NaN values.
//
//===----------------------------------------------------------------------===//
#define SINGLE_PRECISION
#include "fp_lib.h"
enum LE_RESULT {
LE_LESS = -1,
LE_EQUAL = 0,
LE_GREATER = 1,
LE_UNORDERED = 1
};
COMPILER_RT_ABI enum LE_RESULT
__lesf2(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
// If either a or b is NaN, they are unordered.
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
// If a and b are both zeros, they are equal.
if ((aAbs | bAbs) == 0) return LE_EQUAL;
// If at least one of a and b is positive, we get the same result comparing
// a and b as signed integers as we would with a fp_ting-point compare.
if ((aInt & bInt) >= 0) {
if (aInt < bInt) return LE_LESS;
else if (aInt == bInt) return LE_EQUAL;
else return LE_GREATER;
}
// Otherwise, both are negative, so we need to flip the sense of the
// comparison to get the correct result. (This assumes a twos- or ones-
// complement integer representation; if integers are represented in a
// sign-magnitude representation, then this flip is incorrect).
else {
if (aInt > bInt) return LE_LESS;
else if (aInt == bInt) return LE_EQUAL;
else return LE_GREATER;
}
}
#if defined(__ELF__)
// Alias for libgcc compatibility
FNALIAS(__cmpsf2, __lesf2);
#endif
enum GE_RESULT {
GE_LESS = -1,
GE_EQUAL = 0,
GE_GREATER = 1,
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
};
COMPILER_RT_ABI enum GE_RESULT
__gesf2(fp_t a, fp_t b) {
const srep_t aInt = toRep(a);
const srep_t bInt = toRep(b);
const rep_t aAbs = aInt & absMask;
const rep_t bAbs = bInt & absMask;
if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
if ((aAbs | bAbs) == 0) return GE_EQUAL;
if ((aInt & bInt) >= 0) {
if (aInt < bInt) return GE_LESS;
else if (aInt == bInt) return GE_EQUAL;
else return GE_GREATER;
} else {
if (aInt > bInt) return GE_LESS;
else if (aInt == bInt) return GE_EQUAL;
else return GE_GREATER;
}
}
COMPILER_RT_ABI int
__unordsf2(fp_t a, fp_t b) {
const rep_t aAbs = toRep(a) & absMask;
const rep_t bAbs = toRep(b) & absMask;
return aAbs > infRep || bAbs > infRep;
}
// The following are alternative names for the preceding routines.
COMPILER_RT_ABI enum LE_RESULT
__eqsf2(fp_t a, fp_t b) {
return __lesf2(a, b);
}
COMPILER_RT_ABI enum LE_RESULT
__ltsf2(fp_t a, fp_t b) {
return __lesf2(a, b);
}
COMPILER_RT_ABI enum LE_RESULT
__nesf2(fp_t a, fp_t b) {
return __lesf2(a, b);
}
COMPILER_RT_ABI enum GE_RESULT
__gtsf2(fp_t a, fp_t b) {
return __gesf2(a, b);
}
#if defined(__ARM_EABI__)
#if defined(COMPILER_RT_ARMHF_TARGET)
AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) {
return __unordsf2(a, b);
}
#else
AEABI_RTABI int __aeabi_fcmpun(fp_t a, fp_t b) COMPILER_RT_ALIAS(__unordsf2);
#endif
#endif
/* -------------------------------------------------------------------------- */
enum CMP_RESULT {
CMP_LESS = -1,
CMP_EQUAL = 0,
CMP_GREATER = 1,
CMP_UNORDERED = 3 // Note: different from LE_UNORDERED, GE_UNORDERED
};
#define _SINGLE_IS_SIGNAN(x) \
( \
(x##Exponent==255) ? \
( (!x##Fract==0 && !(x##Fract & (1<<(24-2)))) ? \
(1) ? \
(0) \
) : \
(0) \
)
COMPILER_RT_ABI enum CMP_RESULT _S_cmp(fp_t a, fp_t b)
{
rep_t A = toRep(a);
rep_t B = toRep(b);
enum CMP_RESULT ret;
const rep_t aExponent = A >> significandBits & maxExponent;
const rep_t bExponent = B >> significandBits & maxExponent;
const rep_t aFract = A & significandMask;
const rep_t bFract = B & significandMask;
const rep_t aSign = A & signBit;
const rep_t bSign = B & signBit;
/* NANs are unordered. */
if ((bExponent == 255 && !(bFract==0) )
|| (aExponent == 255 && !(aFract==0))) {
ret = CMP_UNORDERED;
// check NAN
// if (_HALF_IS_SIGNAN(b) || _HALF_IS_SIGNAN(a) FP_SET_EXCEPTION (FP_EX_INVALID);
} else {
int aIsZero, bIsZero;
bIsZero = (!bExponent && (bFract == 0)) ? 1 : 0;
aIsZero = (!aExponent && (aFract == 0)) ? 1 : 0;
if (bIsZero && aIsZero)
ret = 0;
else if (bIsZero)
ret = aSign ? 1 : -1;
else if (aIsZero)
ret = bSign ? -1 : 1;
else if (bSign != aSign)
ret = bSign ? -1 : 1;
else if (bExponent > aExponent)
ret = bSign ? -1 : 1;
else if (bExponent < aExponent)
ret = bSign ? 1 : -1;
else if (bFract > aFract)
ret = bSign ? -1 : 1;
else if (aFract > bFract)
ret = bSign ? 1 : -1;
else
ret = 0;
}
// if (ret == -1) ret = 2;
return ret;
}
//===-- ctzdi2.c - Implement __ctzdi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __ctzdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: the number of trailing 0-bits
#if !defined(__clang__) && \
((defined(__sparc__) && defined(__arch64__)) || defined(__mips64) || \
(defined(__riscv) && __SIZEOF_POINTER__ >= 8))
// On 64-bit architectures with neither a native clz instruction nor a native
// ctz instruction, gcc resolves __builtin_ctz to __ctzdi2 rather than
// __ctzsi2, leading to infinite recursion.
#define __builtin_ctz(a) __ctzsi2(a)
extern si_int __ctzsi2(si_int);
#endif
// Precondition: a != 0
COMPILER_RT_ABI si_int __ctzdi2(di_int a) {
dwords x;
x.all = a;
const si_int f = -(x.s.low == 0);
return __builtin_ctz((x.s.high & f) | (x.s.low & ~f)) +
(f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
}
//===-- ctzsi2.c - Implement __ctzsi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __ctzsi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: the number of trailing 0-bits
// Precondition: a != 0
COMPILER_RT_ABI si_int __ctzsi2(si_int a) {
su_int x = (su_int)a;
si_int t = ((x & 0x0000FFFF) == 0)
<< 4; // if (x has no small bits) t = 16 else 0
x >>= t; // x = [0 - 0xFFFF] + higher garbage bits
su_int r = t; // r = [0, 16]
// return r + ctz(x)
t = ((x & 0x00FF) == 0) << 3;
x >>= t; // x = [0 - 0xFF] + higher garbage bits
r += t; // r = [0, 8, 16, 24]
// return r + ctz(x)
t = ((x & 0x0F) == 0) << 2;
x >>= t; // x = [0 - 0xF] + higher garbage bits
r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28]
// return r + ctz(x)
t = ((x & 0x3) == 0) << 1;
x >>= t;
x &= 3; // x = [0 - 3]
r += t; // r = [0 - 30] and is even
// return r + ctz(x)
// The branch-less return statement below is equivalent
// to the following switch statement:
// switch (x)
// {
// case 0:
// return r + 2;
// case 2:
// return r + 1;
// case 1:
// case 3:
// return r;
// }
return r + ((2 - (x >> 1)) & -((x & 1) == 0));
}
//===-- divdi3.c - Implement __divdi3 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __divdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: a / b
COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b) {
const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
di_int s_a = a >> bits_in_dword_m1; // s_a = a < 0 ? -1 : 0
di_int s_b = b >> bits_in_dword_m1; // s_b = b < 0 ? -1 : 0
a = (a ^ s_a) - s_a; // negate if s_a == -1
b = (b ^ s_b) - s_b; // negate if s_b == -1
s_a ^= s_b; // sign of quotient
return (__udivmoddi4(a, b, (du_int *)0) ^ s_a) - s_a; // negate if s_a == -1
}
//===-- divsi3.c - Implement __divsi3 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __divsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: a / b
COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b) {
const int bits_in_word_m1 = (int)(sizeof(si_int) * CHAR_BIT) - 1;
si_int s_a = a >> bits_in_word_m1; // s_a = a < 0 ? -1 : 0
si_int s_b = b >> bits_in_word_m1; // s_b = b < 0 ? -1 : 0
a = (a ^ s_a) - s_a; // negate if s_a == -1
b = (b ^ s_b) - s_b; // negate if s_b == -1
s_a ^= s_b; // sign of quotient
//
// On CPUs without unsigned hardware division support,
// this calls __udivsi3 (notice the cast to su_int).
// On CPUs with unsigned hardware division support,
// this uses the unsigned division instruction.
//
return ((su_int)a / (su_int)b ^ s_a) - s_a; // negate if s_a == -1
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__divsi3, __aeabi_idiv)
#endif
//===-- ffsdi2.c - Implement __ffsdi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __ffsdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: the index of the least significant 1-bit in a, or
// the value zero if a is zero. The least significant bit is index one.
COMPILER_RT_ABI si_int __ffsdi2(di_int a) {
dwords x;
x.all = a;
if (x.s.low == 0) {
if (x.s.high == 0)
return 0;
return __builtin_ctz(x.s.high) + (1 + sizeof(si_int) * CHAR_BIT);
}
return __builtin_ctz(x.s.low) + 1;
}
//===-- ffssi2.c - Implement __ffssi2 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __ffssi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: the index of the least significant 1-bit in a, or
// the value zero if a is zero. The least significant bit is index one.
COMPILER_RT_ABI si_int __ffssi2(si_int a) {
if (a == 0) {
return 0;
}
return __builtin_ctz(a) + 1;
}
//===-- lib/fp_lib.h - Floating-point utilities -------------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a configuration header for soft-float routines in compiler-rt.
// This file does not provide any part of the compiler-rt interface, but defines
// many useful constants and utility routines that are used in the
// implementation of the soft-float routines in compiler-rt.
//
// Assumes that float, double and long double correspond to the IEEE-754
// binary32, binary64 and binary 128 types, respectively, and that integer
// endianness matches floating point endianness on the target platform.
//
//===----------------------------------------------------------------------===//
#ifndef FP_LIB_HEADER
#define FP_LIB_HEADER
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include "int_lib.h"
// x86_64 FreeBSD prior v9.3 define fixed-width types incorrectly in
// 32-bit mode.
#if defined(__FreeBSD__) && defined(__i386__)
# include <sys/param.h>
# if __FreeBSD_version < 903000 // v9.3
# define uint64_t unsigned long long
# define int64_t long long
# undef UINT64_C
# define UINT64_C(c) (c ## ULL)
# endif
#endif
#if defined(HALF_PRECISION)
typedef uint16_t rep_t;
typedef int16_t srep_t;
typedef half fp_t;
#define REP_C UINT16_C
#define significandBits 10
static __inline int rep_clz(rep_t a) {
return __builtin_clz(a);
}
// 16x16 --> 32 bit multiply
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
const uint32_t product = (uint32_t)a*b;
*hi = product >> 16;
*lo = product;
}
COMPILER_RT_ABI fp_t __addhf3(fp_t a, fp_t b);
#elif defined(SINGLE_PRECISION)
typedef uint32_t rep_t;
typedef int32_t srep_t;
typedef float fp_t;
#define REP_C UINT32_C
#define significandBits 23
static __inline int rep_clz(rep_t a) {
return __builtin_clz(a);
}
// 32x32 --> 64 bit multiply
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
const uint64_t product = (uint64_t)a*b;
*hi = product >> 32;
*lo = product;
}
COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
#elif defined(DOUBLE_PRECISION)
typedef uint64_t rep_t;
typedef int64_t srep_t;
typedef double fp_t;
#define REP_C UINT64_C
#define significandBits 52
static __inline int rep_clz(rep_t a) {
#if defined __LP64__
return __builtin_clzl(a);
#else
if (a & REP_C(0xffffffff00000000))
return __builtin_clz(a >> 32);
else
return 32 + __builtin_clz(a & REP_C(0xffffffff));
#endif
}
#define loWord(a) (a & 0xffffffffU)
#define hiWord(a) (a >> 32)
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
// many 64-bit platforms have this operation, but they tend to have hardware
// floating-point, so we don't bother with a special case for them here.
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
// Each of the component 32x32 -> 64 products
const uint64_t plolo = loWord(a) * loWord(b);
const uint64_t plohi = loWord(a) * hiWord(b);
const uint64_t philo = hiWord(a) * loWord(b);
const uint64_t phihi = hiWord(a) * hiWord(b);
// Sum terms that contribute to lo in a way that allows us to get the carry
const uint64_t r0 = loWord(plolo);
const uint64_t r1 = hiWord(plolo) + loWord(plohi) + loWord(philo);
*lo = r0 + (r1 << 32);
// Sum terms contributing to hi with the carry from lo
*hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi;
}
#undef loWord
#undef hiWord
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
#elif defined(QUAD_PRECISION)
#if __LDBL_MANT_DIG__ == 113
#define CRT_LDBL_128BIT
typedef __uint128_t rep_t;
typedef __int128_t srep_t;
typedef long double fp_t;
#define REP_C (__uint128_t)
// Note: Since there is no explicit way to tell compiler the constant is a
// 128-bit integer, we let the constant be casted to 128-bit integer
#define significandBits 112
static __inline int rep_clz(rep_t a) {
const union
{
__uint128_t ll;
#if _YUGA_BIG_ENDIAN
struct { uint64_t high, low; } s;
#else
struct { uint64_t low, high; } s;
#endif
} uu = { .ll = a };
uint64_t word;
uint64_t add;
if (uu.s.high){
word = uu.s.high;
add = 0;
}
else{
word = uu.s.low;
add = 64;
}
return __builtin_clzll(word) + add;
}
#define Word_LoMask UINT64_C(0x00000000ffffffff)
#define Word_HiMask UINT64_C(0xffffffff00000000)
#define Word_FullMask UINT64_C(0xffffffffffffffff)
#define Word_1(a) (uint64_t)((a >> 96) & Word_LoMask)
#define Word_2(a) (uint64_t)((a >> 64) & Word_LoMask)
#define Word_3(a) (uint64_t)((a >> 32) & Word_LoMask)
#define Word_4(a) (uint64_t)(a & Word_LoMask)
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
// many 64-bit platforms have this operation, but they tend to have hardware
// floating-point, so we don't bother with a special case for them here.
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
const uint64_t product11 = Word_1(a) * Word_1(b);
const uint64_t product12 = Word_1(a) * Word_2(b);
const uint64_t product13 = Word_1(a) * Word_3(b);
const uint64_t product14 = Word_1(a) * Word_4(b);
const uint64_t product21 = Word_2(a) * Word_1(b);
const uint64_t product22 = Word_2(a) * Word_2(b);
const uint64_t product23 = Word_2(a) * Word_3(b);
const uint64_t product24 = Word_2(a) * Word_4(b);
const uint64_t product31 = Word_3(a) * Word_1(b);
const uint64_t product32 = Word_3(a) * Word_2(b);
const uint64_t product33 = Word_3(a) * Word_3(b);
const uint64_t product34 = Word_3(a) * Word_4(b);
const uint64_t product41 = Word_4(a) * Word_1(b);
const uint64_t product42 = Word_4(a) * Word_2(b);
const uint64_t product43 = Word_4(a) * Word_3(b);
const uint64_t product44 = Word_4(a) * Word_4(b);
const __uint128_t sum0 = (__uint128_t)product44;
const __uint128_t sum1 = (__uint128_t)product34 +
(__uint128_t)product43;
const __uint128_t sum2 = (__uint128_t)product24 +
(__uint128_t)product33 +
(__uint128_t)product42;
const __uint128_t sum3 = (__uint128_t)product14 +
(__uint128_t)product23 +
(__uint128_t)product32 +
(__uint128_t)product41;
const __uint128_t sum4 = (__uint128_t)product13 +
(__uint128_t)product22 +
(__uint128_t)product31;
const __uint128_t sum5 = (__uint128_t)product12 +
(__uint128_t)product21;
const __uint128_t sum6 = (__uint128_t)product11;
const __uint128_t r0 = (sum0 & Word_FullMask) +
((sum1 & Word_LoMask) << 32);
const __uint128_t r1 = (sum0 >> 64) +
((sum1 >> 32) & Word_FullMask) +
(sum2 & Word_FullMask) +
((sum3 << 32) & Word_HiMask);
*lo = r0 + (r1 << 64);
*hi = (r1 >> 64) +
(sum1 >> 96) +
(sum2 >> 64) +
(sum3 >> 32) +
sum4 +
(sum5 << 32) +
(sum6 << 64);
}
#undef Word_1
#undef Word_2
#undef Word_3
#undef Word_4
#undef Word_HiMask
#undef Word_LoMask
#undef Word_FullMask
#endif // __LDBL_MANT_DIG__ == 113
#else
#error HALF_PRECISION, SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
#endif
#if defined(HALF_PRECISION) || defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || defined(CRT_LDBL_128BIT)
#define typeWidth (sizeof(rep_t)*CHAR_BIT)
#define exponentBits (typeWidth - significandBits - 1)
#define maxExponent ((1 << exponentBits) - 1)
#define exponentBias (maxExponent >> 1)
#define implicitBit (REP_C(1) << significandBits)
#define significandMask (implicitBit - 1U)
#define signBit (REP_C(1) << (significandBits + exponentBits))
#define absMask (signBit - 1U)
#define exponentMask (absMask ^ significandMask)
#define oneRep ((rep_t)exponentBias << significandBits)
#define infRep exponentMask
#define quietBit (implicitBit >> 1)
#define qnanRep (exponentMask | quietBit)
static __inline rep_t toRep(fp_t x) {
const union { fp_t f; rep_t i; } rep = {.f = x};
return rep.i;
}
static __inline fp_t fromRep(rep_t x) {
const union { fp_t f; rep_t i; } rep = {.i = x};
return rep.f;
}
static __inline int normalize(rep_t *significand) {
const int shift = rep_clz(*significand) - rep_clz(implicitBit);
*significand <<= shift;
return 1 - shift;
}
static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
*hi = *hi << count | *lo >> (typeWidth - count);
*lo = *lo << count;
}
static __inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, unsigned int count) {
if (count < typeWidth) {
const bool sticky = *lo << (typeWidth - count);
*lo = *hi << (typeWidth - count) | *lo >> count | sticky;
*hi = *hi >> count;
}
else if (count < 2*typeWidth) {
const bool sticky = *hi << (2*typeWidth - count) | *lo;
*lo = *hi >> (count - typeWidth) | sticky;
*hi = 0;
} else {
const bool sticky = *hi | *lo;
*lo = sticky;
*hi = 0;
}
}
#endif
#endif // FP_LIB_HEADER
/* ===-- int_endianness.h - configuration header for compiler-rt ------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file is a configuration header for compiler-rt.
* This file is not part of the interface of this library.
*
* ===----------------------------------------------------------------------===
*/
#ifndef INT_ENDIANNESS_H
#define INT_ENDIANNESS_H
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
defined(__ORDER_LITTLE_ENDIAN__)
/* Clang and GCC provide built-in endianness definitions. */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define _YUGA_LITTLE_ENDIAN 0
#define _YUGA_BIG_ENDIAN 1
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#endif /* __BYTE_ORDER__ */
#else /* Compilers other than Clang or GCC. */
#if defined(__SVR4) && defined(__sun)
#include <sys/byteorder.h>
#if defined(_BIG_ENDIAN)
#define _YUGA_LITTLE_ENDIAN 0
#define _YUGA_BIG_ENDIAN 1
#elif defined(_LITTLE_ENDIAN)
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#else /* !_LITTLE_ENDIAN */
#error "unknown endianness"
#endif /* !_LITTLE_ENDIAN */
#endif /* Solaris and AuroraUX. */
/* .. */
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
defined(__minix)
#include <sys/endian.h>
#if _BYTE_ORDER == _BIG_ENDIAN
#define _YUGA_LITTLE_ENDIAN 0
#define _YUGA_BIG_ENDIAN 1
#elif _BYTE_ORDER == _LITTLE_ENDIAN
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#endif /* _BYTE_ORDER */
#endif /* *BSD */
#if defined(__OpenBSD__)
#include <machine/endian.h>
#if _BYTE_ORDER == _BIG_ENDIAN
#define _YUGA_LITTLE_ENDIAN 0
#define _YUGA_BIG_ENDIAN 1
#elif _BYTE_ORDER == _LITTLE_ENDIAN
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#endif /* _BYTE_ORDER */
#endif /* OpenBSD */
/* .. */
/* Mac OSX has __BIG_ENDIAN__ or __LITTLE_ENDIAN__ automatically set by the
* compiler (at least with GCC) */
#if defined(__APPLE__) || defined(__ellcc__ )
#ifdef __BIG_ENDIAN__
#if __BIG_ENDIAN__
#define _YUGA_LITTLE_ENDIAN 0
#define _YUGA_BIG_ENDIAN 1
#endif
#endif /* __BIG_ENDIAN__ */
#ifdef __LITTLE_ENDIAN__
#if __LITTLE_ENDIAN__
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#endif
#endif /* __LITTLE_ENDIAN__ */
#endif /* Mac OSX */
/* .. */
#if defined(_WIN32)
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#endif /* Windows */
#endif /* Clang or GCC. */
/* . */
#if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN)
#error Unable to determine endian
#endif /* Check we found an endianness correctly. */
#endif /* INT_ENDIANNESS_H */
/* ===-- int_lib.h - configuration header for compiler-rt -----------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file is a configuration header for compiler-rt.
* This file is not part of the interface of this library.
*
* ===----------------------------------------------------------------------===
*/
#ifndef INT_LIB_H
#define INT_LIB_H
/* Assumption: Signed integral is 2's complement. */
/* Assumption: Right shift of signed negative is arithmetic shift. */
/* Assumption: Endianness is little or big (not mixed). */
#if defined(__ELF__)
#define FNALIAS(alias_name, original_name) \
void alias_name() __attribute__((__alias__(#original_name)))
#define COMPILER_RT_ALIAS(aliasee) __attribute__((__alias__(#aliasee)))
#else
#define FNALIAS(alias, name) _Pragma("GCC error(\"alias unsupported on this file format\")")
#define COMPILER_RT_ALIAS(aliasee) _Pragma("GCC error(\"alias unsupported on this file format\")")
#endif
/* ABI macro definitions */
#if __ARM_EABI__
# ifdef COMPILER_RT_ARMHF_TARGET
# define COMPILER_RT_ABI
# else
# define COMPILER_RT_ABI __attribute__((__pcs__("aapcs")))
# endif
#else
# define COMPILER_RT_ABI
#endif
#define AEABI_RTABI __attribute__((__pcs__("aapcs")))
#ifdef _MSC_VER
#define ALWAYS_INLINE __forceinline
#define NOINLINE __declspec(noinline)
#define NORETURN __declspec(noreturn)
#define UNUSED
#else
#define ALWAYS_INLINE __attribute__((always_inline))
#define NOINLINE __attribute__((noinline))
#define NORETURN __attribute__((noreturn))
#define UNUSED __attribute__((unused))
#endif
#if defined(__NetBSD__) && (defined(_KERNEL) || defined(_STANDALONE))
/*
* Kernel and boot environment can't use normal headers,
* so use the equivalent system headers.
*/
# include <machine/limits.h>
# include <sys/stdint.h>
# include <sys/types.h>
#else
/* Include the standard compiler builtin headers we use functionality from. */
# include <limits.h>
# include <stdint.h>
# include <stdbool.h>
# include <float.h>
#endif
/* Include the commonly used internal type definitions. */
#include "int_types.h"
/* Include internal utility function declarations. */
#include "int_util.h"
COMPILER_RT_ABI si_int __paritysi2(si_int a);
COMPILER_RT_ABI si_int __paritydi2(di_int a);
COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b);
COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b);
COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d);
COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int* rem);
COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int* rem);
#ifdef CRT_HAS_128BIT
COMPILER_RT_ABI si_int __clzti2(ti_int a);
COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem);
#endif
/* Definitions for builtins unavailable on MSVC */
#if defined(_MSC_VER) && !defined(__clang__)
#include <intrin.h>
uint32_t __inline __builtin_ctz(uint32_t value) {
unsigned long trailing_zero = 0;
if (_BitScanForward(&trailing_zero, value))
return trailing_zero;
return 32;
}
uint32_t __inline __builtin_clz(uint32_t value) {
unsigned long leading_zero = 0;
if (_BitScanReverse(&leading_zero, value))
return 31 - leading_zero;
return 32;
}
#if defined(_M_ARM) || defined(_M_X64)
uint32_t __inline __builtin_clzll(uint64_t value) {
unsigned long leading_zero = 0;
if (_BitScanReverse64(&leading_zero, value))
return 63 - leading_zero;
return 64;
}
#else
uint32_t __inline __builtin_clzll(uint64_t value) {
if (value == 0)
return 64;
uint32_t msh = (uint32_t)(value >> 32);
uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF);
if (msh != 0)
return __builtin_clz(msh);
return 32 + __builtin_clz(lsh);
}
#endif
#define __builtin_clzl __builtin_clzll
#endif /* defined(_MSC_VER) && !defined(__clang__) */
#endif /* INT_LIB_H */
/* ===-- int_lib.h - configuration header for compiler-rt -----------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file is not part of the interface of this library.
*
* This file defines various standard types, most importantly a number of unions
* used to access parts of larger types.
*
* ===----------------------------------------------------------------------===
*/
#ifndef INT_TYPES_H
#define INT_TYPES_H
#include "int_endianness.h"
/* si_int is defined in Linux sysroot's asm-generic/siginfo.h */
#ifdef si_int
#undef si_int
#endif
typedef int si_int;
typedef unsigned su_int;
typedef long long di_int;
typedef unsigned long long du_int;
typedef union
{
di_int all;
struct
{
#if _YUGA_LITTLE_ENDIAN
su_int low;
si_int high;
#else
si_int high;
su_int low;
#endif /* _YUGA_LITTLE_ENDIAN */
}s;
} dwords;
typedef union
{
du_int all;
struct
{
#if _YUGA_LITTLE_ENDIAN
su_int low;
su_int high;
#else
su_int high;
su_int low;
#endif /* _YUGA_LITTLE_ENDIAN */
}s;
} udwords;
#if (defined(__LP64__) || defined(__wasm__) || defined(__mips64)) || defined(__riscv)
#define CRT_HAS_128BIT
#endif
#ifdef CRT_HAS_128BIT
typedef int ti_int __attribute__ ((mode (TI)));
typedef unsigned tu_int __attribute__ ((mode (TI)));
typedef union
{
ti_int all;
struct
{
#if _YUGA_LITTLE_ENDIAN
du_int low;
di_int high;
#else
di_int high;
du_int low;
#endif /* _YUGA_LITTLE_ENDIAN */
}s;
} twords;
typedef union
{
tu_int all;
struct
{
#if _YUGA_LITTLE_ENDIAN
du_int low;
du_int high;
#else
du_int high;
du_int low;
#endif /* _YUGA_LITTLE_ENDIAN */
}s;
} utwords;
static __inline ti_int make_ti(di_int h, di_int l) {
twords r;
r.s.high = h;
r.s.low = l;
return r.all;
}
static __inline tu_int make_tu(du_int h, du_int l) {
utwords r;
r.s.high = h;
r.s.low = l;
return r.all;
}
#endif /* CRT_HAS_128BIT */
typedef union
{
su_int u;
float f;
} float_bits;
typedef union
{
udwords u;
double f;
} double_bits;
typedef struct
{
#if _YUGA_LITTLE_ENDIAN
udwords low;
udwords high;
#else
udwords high;
udwords low;
#endif /* _YUGA_LITTLE_ENDIAN */
} uqwords;
typedef union
{
uqwords u;
long double f;
} long_double_bits;
#if __STDC_VERSION__ >= 199901L
typedef float _Complex Fcomplex;
typedef double _Complex Dcomplex;
typedef long double _Complex Lcomplex;
#define COMPLEX_REAL(x) __real__(x)
#define COMPLEX_IMAGINARY(x) __imag__(x)
#else
typedef struct { float real, imaginary; } Fcomplex;
typedef struct { double real, imaginary; } Dcomplex;
typedef struct { long double real, imaginary; } Lcomplex;
#define COMPLEX_REAL(x) (x).real
#define COMPLEX_IMAGINARY(x) (x).imaginary
#endif
#endif /* INT_TYPES_H */
/* ===-- int_util.h - internal utility functions ----------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===-----------------------------------------------------------------------===
*
* This file is not part of the interface of this library.
*
* This file defines non-inline utilities which are available for use in the
* library. The function definitions themselves are all contained in int_util.c
* which will always be compiled into any compiler-rt library.
*
* ===-----------------------------------------------------------------------===
*/
#ifndef INT_UTIL_H
#define INT_UTIL_H
/** \brief Trigger a program abort (or panic for kernel code). */
#define compilerrt_abort() compilerrt_abort_impl(__FILE__, __LINE__, __func__)
NORETURN void compilerrt_abort_impl(const char *file, int line,
const char *function);
#define COMPILE_TIME_ASSERT(expr) COMPILE_TIME_ASSERT1(expr, __COUNTER__)
#define COMPILE_TIME_ASSERT1(expr, cnt) COMPILE_TIME_ASSERT2(expr, cnt)
#define COMPILE_TIME_ASSERT2(expr, cnt) \
typedef char ct_assert_##cnt[(expr) ? 1 : -1] UNUSED
#endif /* INT_UTIL_H */
/* ===-- lshrdi3.c - Implement __lshrdi3 -----------------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __lshrdi3 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
/* Returns: logical a >> b */
/* Precondition: 0 <= b < bits_in_dword */
COMPILER_RT_ABI di_int
__lshrdi3(di_int a, si_int b)
{
const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
udwords input;
udwords result;
input.all = a;
if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */
{
result.s.high = 0;
result.s.low = input.s.high >> (b - bits_in_word);
}
else /* 0 <= b < bits_in_word */
{
if (b == 0)
return a;
result.s.high = input.s.high >> b;
result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b);
}
return result.all;
}
#if defined(__ARM_EABI__)
AEABI_RTABI di_int __aeabi_llsr(di_int a, si_int b) COMPILER_RT_ALIAS(__lshrdi3);
#endif
//===-- muldi3.c - Implement __muldi3 -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __muldi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: a * b
static di_int __muldsi3(su_int a, su_int b) {
dwords r;
const int bits_in_word_2 = (int)(sizeof(si_int) * CHAR_BIT) / 2;
const su_int lower_mask = (su_int)~0 >> bits_in_word_2;
r.s.low = (a & lower_mask) * (b & lower_mask);
su_int t = r.s.low >> bits_in_word_2;
r.s.low &= lower_mask;
t += (a >> bits_in_word_2) * (b & lower_mask);
r.s.low += (t & lower_mask) << bits_in_word_2;
r.s.high = t >> bits_in_word_2;
t = r.s.low >> bits_in_word_2;
r.s.low &= lower_mask;
t += (b >> bits_in_word_2) * (a & lower_mask);
r.s.low += (t & lower_mask) << bits_in_word_2;
r.s.high += t >> bits_in_word_2;
r.s.high += (a >> bits_in_word_2) * (b >> bits_in_word_2);
return r.all;
}
// Returns: a * b
COMPILER_RT_ABI di_int __muldi3(di_int a, di_int b) {
dwords x;
x.all = a;
dwords y;
y.all = b;
dwords r;
r.all = __muldsi3(x.s.low, y.s.low);
r.s.high += x.s.high * y.s.low + x.s.low * y.s.high;
return r.all;
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__muldi3, __aeabi_lmul)
#endif
//===-- lib/negdf2.c - Double-precision subtraction ---------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
#define DOUBLE_PRECISION
#include "fp_lib.h"
// Subtraction; flip the sign bit of b and add.
COMPILER_RT_ABI fp_t
__negdf2(fp_t a) {
const rep_t ai = toRep(a) ^ signBit;
return fromRep(ai);
}
//===-- lib/neghf2.c - Half-precision subtraction ---------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
#define HALF_PRECISION
#include "fp_lib.h"
// Subtraction; flip the sign bit of b and add.
COMPILER_RT_ABI fp_t
__neghf2(fp_t a) {
const unsigned int ai = toRep(a) ^ signBit;
return fromRep(ai);
}
//===-- lib/negsf2.c - Single-precision subtraction ---------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float subtraction with the
// IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
#define SINGLE_PRECISION 1
#include "fp_lib.h"
fp_t __negsf2(fp_t a)
{
const unsigned int ai = toRep(a) ^ signBit;
return fromRep(ai);
}
//===-- paritydi2.c - Implement __paritydi2 -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __paritydi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: 1 if number of bits is odd else returns 0
COMPILER_RT_ABI si_int __paritydi2(di_int a) {
dwords x;
x.all = a;
return __paritysi2(x.s.high ^ x.s.low);
}
//===-- paritysi2.c - Implement __paritysi2 -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __paritysi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: 1 if number of bits is odd else returns 0
COMPILER_RT_ABI si_int __paritysi2(si_int a) {
su_int x = (su_int)a;
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
return (0x6996 >> (x & 0xF)) & 1;
}
//===-- popcountdi2.c - Implement __popcountdi2 ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __popcountdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: count of 1 bits
COMPILER_RT_ABI si_int __popcountdi2(di_int a) {
du_int x2 = (du_int)a;
x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL);
// Every 2 bits holds the sum of every pair of bits (32)
x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL);
// Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (16)
x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL;
// Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (8)
su_int x = (su_int)(x2 + (x2 >> 32));
// The lower 32 bits hold four 16 bit sums (5 significant bits).
// Upper 32 bits are garbage
x = x + (x >> 16);
// The lower 16 bits hold two 32 bit sums (6 significant bits).
// Upper 16 bits are garbage
return (x + (x >> 8)) & 0x0000007F; // (7 significant bits)
}
//===-- popcountsi2.c - Implement __popcountsi2 ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements __popcountsi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#include "int_lib.h"
// Returns: count of 1 bits
COMPILER_RT_ABI si_int __popcountsi2(si_int a) {
su_int x = (su_int)a;
x = x - ((x >> 1) & 0x55555555);
// Every 2 bits holds the sum of every pair of bits
x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
// Every 4 bits holds the sum of every 4-set of bits (3 significant bits)
x = (x + (x >> 4)) & 0x0F0F0F0F;
// Every 8 bits holds the sum of every 8-set of bits (4 significant bits)
x = (x + (x >> 16));
// The lower 16 bits hold two 8 bit sums (5 significant bits).
// Upper 16 bits are garbage
return (x + (x >> 8)) & 0x0000003F; // (6 significant bits)
}
/* ===-- udivdi3.c - Implement __udivdi3 -----------------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __udivdi3 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
/* Returns: a / b */
COMPILER_RT_ABI du_int
__udivdi3(du_int a, du_int b)
{
return __udivmoddi4(a, b, 0);
}
/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __udivmoddi4 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
/* Effects: if rem != 0, *rem = a % b
* Returns: a / b
*/
/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
COMPILER_RT_ABI du_int
__udivmoddi4(du_int a, du_int b, du_int* rem)
{
const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
udwords n;
n.all = a;
udwords d;
d.all = b;
udwords q;
udwords r;
unsigned sr;
/* special cases, X is unknown, K != 0 */
if (n.s.high == 0)
{
if (d.s.high == 0)
{
/* 0 X
* ---
* 0 X
*/
if (rem)
*rem = n.s.low % d.s.low;
return n.s.low / d.s.low;
}
/* 0 X
* ---
* K X
*/
if (rem)
*rem = n.s.low;
return 0;
}
/* n.s.high != 0 */
if (d.s.low == 0)
{
if (d.s.high == 0)
{
/* K X
* ---
* 0 0
*/
if (rem)
*rem = n.s.high % d.s.low;
return n.s.high / d.s.low;
}
/* d.s.high != 0 */
if (n.s.low == 0)
{
/* K 0
* ---
* K 0
*/
if (rem)
{
r.s.high = n.s.high % d.s.high;
r.s.low = 0;
*rem = r.all;
}
return n.s.high / d.s.high;
}
/* K K
* ---
* K 0
*/
if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */
{
if (rem)
{
r.s.low = n.s.low;
r.s.high = n.s.high & (d.s.high - 1);
*rem = r.all;
}
return n.s.high >> __builtin_ctz(d.s.high);
}
/* K K
* ---
* K 0
*/
sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
/* 0 <= sr <= n_uword_bits - 2 or sr large */
if (sr > n_uword_bits - 2)
{
if (rem)
*rem = n.all;
return 0;
}
++sr;
/* 1 <= sr <= n_uword_bits - 1 */
/* q.all = n.all << (n_udword_bits - sr); */
q.s.low = 0;
q.s.high = n.s.low << (n_uword_bits - sr);
/* r.all = n.all >> sr; */
r.s.high = n.s.high >> sr;
r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
}
else /* d.s.low != 0 */
{
if (d.s.high == 0)
{
/* K X
* ---
* 0 K
*/
if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */
{
if (rem)
*rem = n.s.low & (d.s.low - 1);
if (d.s.low == 1)
return n.all;
sr = __builtin_ctz(d.s.low);
q.s.high = n.s.high >> sr;
q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
return q.all;
}
/* K X
* ---
* 0 K
*/
sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
/* 2 <= sr <= n_udword_bits - 1
* q.all = n.all << (n_udword_bits - sr);
* r.all = n.all >> sr;
*/
if (sr == n_uword_bits)
{
q.s.low = 0;
q.s.high = n.s.low;
r.s.high = 0;
r.s.low = n.s.high;
}
else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1
{
q.s.low = 0;
q.s.high = n.s.low << (n_uword_bits - sr);
r.s.high = n.s.high >> sr;
r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
}
else // n_uword_bits + 1 <= sr <= n_udword_bits - 1
{
q.s.low = n.s.low << (n_udword_bits - sr);
q.s.high = (n.s.high << (n_udword_bits - sr)) |
(n.s.low >> (sr - n_uword_bits));
r.s.high = 0;
r.s.low = n.s.high >> (sr - n_uword_bits);
}
}
else
{
/* K X
* ---
* K K
*/
sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
/* 0 <= sr <= n_uword_bits - 1 or sr large */
if (sr > n_uword_bits - 1)
{
if (rem)
*rem = n.all;
return 0;
}
++sr;
/* 1 <= sr <= n_uword_bits */
/* q.all = n.all << (n_udword_bits - sr); */
q.s.low = 0;
if (sr == n_uword_bits)
{
q.s.high = n.s.low;
r.s.high = 0;
r.s.low = n.s.high;
}
else
{
q.s.high = n.s.low << (n_uword_bits - sr);
r.s.high = n.s.high >> sr;
r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
}
}
}
/* Not a special case
* q and r are initialized with:
* q.all = n.all << (n_udword_bits - sr);
* r.all = n.all >> sr;
* 1 <= sr <= n_udword_bits - 1
*/
su_int carry = 0;
for (; sr > 0; --sr)
{
/* r:q = ((r:q) << 1) | carry */
r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1));
r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1));
q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1));
q.s.low = (q.s.low << 1) | carry;
/* carry = 0;
* if (r.all >= d.all)
* {
* r.all -= d.all;
* carry = 1;
* }
*/
const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
carry = s & 1;
r.all -= d.all & s;
}
q.all = (q.all << 1) | carry;
if (rem)
*rem = r.all;
return q.all;
}
/* ===-- umoddi3.c - Implement __umoddi3 -----------------------------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __umoddi3 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
#include "int_lib.h"
/* Returns: a % b */
COMPILER_RT_ABI du_int
__umoddi3(du_int a, du_int b)
{
du_int r;
__udivmoddi4(a, b, &r);
return r;
}
# Makefile for building libm/openlibm library
$(info >>> L-openlibm <<< T=$(TOP) D=$(DSTPATH) I=$(INCPATH) B=$(BLDPATH) CF=$(CFLAGS) F=$(FPUCFG) )
PWD:=$(shell pwd)
SOURCE_DIR?=$(PWD)
EXPHDRS=openlibm_math.h sfmath.h extmath.h
SOURCES=$(wildcard *.c)
OBJS=$(SOURCES:%.c=$(BLDPATH)/%.o)
DISS=$(SOURCES:%.c=$(BLDPATH)/%.dis)
LIBRARY=libm
SFDIR=../softfloat
ifeq ($(TOOL),llvm)
CC=clang
TOOLCHAIN=sparc-daiteq-elf
#CFLAGS=-msoft-float -O3
CFLAGS+=-target $(TOOLCHAIN) -mcpu=leon2
# TODO: asm options according to selected type of FPU
CFLAGS+=-Xassembler --has-fhalf -Xassembler --has-fpack -Xassembler -Aleon
endif
ifeq ($(TOOL),gcc)
TOOLCHAIN=sparc-gaisler-elf
CC=$(TOOLCHAIN)-gcc
CFLAGS+=-mcpu=leon -qbsp=leon2 -mfix-at697f
endif
CFLAGS+=-ffunction-sections -fdata-sections
CFLAGS+=-I. -I$(SFDIR)/source/include
FPUTYPE=-daiteq-fpu-type=$(FPUCFG)
AR=$(TOOLCHAIN)-ar
.PHONY: all clean export
all: export
@echo "Library is created"
$(BLDPATH):
@mkdir -p $(BLDPATH)
$(BLDPATH)/$(LIBRARY).a: $(OBJS)
@$(AR) crs $@ $^
$(BLDPATH)/%.o:%.c
@$(CC) $(FPUTYPE) $(CFLAGS) -c $< -o $@
$(BLDPATH)/%.dis:$(BLDPATH)/%.o
@$(TOOLCHAIN)-objdump -S $< > $@
clean:
rm -rf $(BLDPATH)
export: $(DSTPATH)/$(LIBRARY).a $(DISS) $(EXPHDRS:%=$(INCPATH)/%)
@echo "Library is exported"
$(DSTPATH)/$(LIBRARY).a: $(BLDPATH) $(BLDPATH)/$(LIBRARY).a
@cp $(BLDPATH)/$(LIBRARY).a $(DSTPATH)
$(INCPATH)/%: $(SOURCE_DIR)/%
ln -sf $< $@
#ifndef _CDEFS_COMPAT_H_
#define _CDEFS_COMPAT_H_
#if !defined(__BEGIN_DECLS)
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#endif /* !defined(__BEGIN_DECLS) */
#ifdef __GNUC__
#ifndef __strong_reference
#ifdef __APPLE__
#define __strong_reference(sym,aliassym) __weak_reference(sym,aliassym)
#else
#define __strong_reference(sym,aliassym) \
OLM_DLLEXPORT extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym)));
#endif /* __APPLE__ */
#endif /* __strong_reference */
#ifndef __weak_reference
#ifdef __ELF__
#ifdef __STDC__
#define __weak_reference(sym,alias) \
__asm__(".weak " #alias); \
__asm__(".equ " #alias ", " #sym)
#ifndef __warn_references
#define __warn_references(sym,msg) \
__asm__(".section .gnu.warning." #sym); \
__asm__(".asciz \"" msg "\""); \
__asm__(".previous")
#endif /* __warn_references */
#else
#define __weak_reference(sym,alias) \
__asm__(".weak alias"); \
__asm__(".equ alias, sym")
#ifndef __warn_references
#define __warn_references(sym,msg) \
__asm__(".section .gnu.warning.sym"); \
__asm__(".asciz \"msg\""); \
__asm__(".previous")
#endif /* __warn_references */
#endif /* __STDC__ */
#elif defined(__clang__) /* CLANG */
#ifdef __STDC__
/* __asm__(".weak_reference " #alias); \
*/
#define __weak_reference(sym,alias) \
__asm__(".weak " #alias); \
__asm__(".set " #alias ", " #sym)
#else
#define __weak_reference(sym,alias) \
__asm__(".weak_reference alias");\
__asm__(".set alias, sym")
#endif
#else /* !__ELF__ */
#ifdef __STDC__
#define __weak_reference(sym,alias) \
__asm__(".stabs \"_" #alias "\",11,0,0,0"); \
__asm__(".stabs \"_" #sym "\",1,0,0,0")
#ifndef __warn_references
#define __warn_references(sym,msg) \
__asm__(".stabs \"" msg "\",30,0,0,0"); \
__asm__(".stabs \"_" #sym "\",1,0,0,0")
#endif /* __warn_references */
#else
#define __weak_reference(sym,alias) \
__asm__(".stabs \"_/**/alias\",11,0,0,0"); \
__asm__(".stabs \"_/**/sym\",1,0,0,0")
#ifndef __warn_references
#define __warn_references(sym,msg) \
__asm__(".stabs msg,30,0,0,0"); \
__asm__(".stabs \"_/**/sym\",1,0,0,0")
#endif /* __warn_references */
#endif /* __STDC__ */
#endif /* __ELF__ */
#endif /* __weak_reference */
#endif /* __GNUC__ */
#endif /* _CDEFS_COMPAT_H_ */
#ifndef _DAIFPU_HWSW_SOFTFLOAT_WRAPPER_HEADER_FILE_
#define _DAIFPU_HWSW_SOFTFLOAT_WRAPPER_HEADER_FILE_
/*
* Bitmaps correspond with selection of soft-/hard-float operations in LLVM
*
* defaultly all macros (SOFT_FOPS_HALF, SOFT_FOPS_SINGLE, SOFT_FOPS_DOUBLE, ...)
* are zero. It means all operations are in the hardware
*
*/
/* masks for SOFT_FOPS_xxx macros */
#define DAIFPU_SOFT_FPOP_ADD (0x00000001) /* FPOP_ADD */
#define DAIFPU_SOFT_FPOP_SUB (0x00000002) /* FPOP_SUB */
#define DAIFPU_SOFT_FPOP_MUL (0x00000004) /* FPOP_MUL */
#define DAIFPU_SOFT_FPOP_DIV (0x00000008) /* FPOP_DIV */
#define DAIFPU_SOFT_FPOP_MULEX (0x00000010) /* FPOP_MULEX */
#define DAIFPU_SOFT_FPOP_SQRT (0x00000020) /* FPOP_SQRT */
#define DAIFPU_SOFT_FPOP_CMP (0x00000040) /* FPOP_CMP */
#define DAIFPU_SOFT_FPOP_CI2F (0x00000080) /* FPOP_CI2F */
#define DAIFPU_SOFT_FPOP_CF2I (0x00000100) /* FPOP_CF2I */
#define DAIFPU_SOFT_FPOP_CFUP (0x00000200) /* FPOP_CFUP */
#define DAIFPU_SOFT_FPOP_CFDN (0x00000400) /* FPOP_CFDN */
#define DAIFPU_SOFT_FPOP_ABS (0x00000800) /* FPOP_ABS */
#define DAIFPU_SOFT_FPOP_PACK (0x00001000) /* FPOP_PACK */
#define DAIFPU_SOFT_FPOP_MOV (0x00002000) /* FPOP_MOV */
#define DAIFPU_SOFT_FPOP_NEG (0x00004000) /* FPOP_NEG */
#define DAIFPU_SOFT_MASK (0x00007FFF) /* mask of all operations */
#ifndef SOFT_FOPS_HALF
#if SOFT_FLOAT
#define SOFT_FOPS_HALF (0xFFFFFFFF)
#else
#define SOFT_FOPS_HALF (0)
#endif /* SOFT_FLOAT */
#endif /* SOFT_FOPS_HALF */
#ifndef SOFT_FOPS_SINGLE
#if SOFT_FLOAT
#define SOFT_FOPS_SINGLE (0xFFFFFFFF)
#else
#define SOFT_FOPS_SINGLE (0)
#endif /* SOFT_FLOAT */
#endif /* SOFT_FOPS_SINGLE */
#ifndef SOFT_FOPS_DOUBLE
#if SOFT_FLOAT
#define SOFT_FOPS_DOUBLE (0xFFFFFFFF)
#else
#define SOFT_FOPS_DOUBLE (0)
#endif /* SOFT_FLOAT */
#endif /* SOFT_FOPS_DOUBLE */
#ifndef FP_PACKEDHALF_ENABLED
#if !(SOFT_FLOAT) && (~SOFT_FOPS_HALF & DAIFPU_SOFT_MASK) // not in soft-float and at least one half operation in hardware
#define FP_PACKEDHALF_ENABLED (1)
#else
#define FP_PACKEDHALF_ENABLED (0)
#endif /* SOFT_FLOAT */
#endif /* FP_PACKEDHALF_ENABLED */
#ifndef FP_PACKEDSINGLE_ENABLED
#if !(SOFT_FLOAT) && (~SOFT_FOPS_SINGLE & DAIFPU_SOFT_MASK) // not in soft-float and at least one single operation in hardware
#define FP_PACKEDSINGLE_ENABLED (1)
#else
#define FP_PACKEDSINGLE_ENABLED (0)
#endif /* SOFT_FLOAT */
#endif /* FP_PACKEDSINGLE_ENABLED */
/* check consistency with SOFT_FLOAT */
#if SOFT_FLOAT && (~SOFT_FOPS_SINGLE || ~SOFT_FOPS_DOUBLE || ~SOFT_FOPS_HALF)
#warning Inconsistency in soft-float and soft-fp-XXXX options
#endif
#endif /* _DAIFPU_HWSW_SOFTFLOAT_WRAPPER_HEADER_FILE_ */
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!