mirror of git://gcc.gnu.org/git/gcc.git
re PR target/54222 ([avr] Implement fixed-point support)
gcc/ PR target/54222 * config/avr/avr.md (unspec) <UNSPEC_ROUND>: Add. * config/avr/avr-fixed.md (ALL4QA, ALL124QA): New mode iterators. (round<mode>3, round<mode>3_const): New expanders for fixed-mode. (*round<mode>3.libgcc): New insns for fixed-modes. * config/avr/builtins.def (ABSxx): Use a non-NULL LIBNAME. (ROUNDxx, COUNTLSxx, BITSxx, xxBITS): New DEF_BUILTINs. (ROUNDFX, COUNTLSFX, ABSFX): New DEF_BUILTINs. * config/avr/stdfix.h (absFX, bitsFX, FXbits): Remove inline implementations. Define to __builtin_avr_absFX, __builtin_avr_bitsFX, __builtin_avr_FXbits, respectively. (roundFX, countlsFX): Define to __builtin_avr_roundFX, __builtin_avr_countlsFX, respectively. * config/avr/avr-c.c (target.h): Include it. (enum avr_builtin_id): New enum. (avr_resolve_overloaded_builtin): New static function. (avr_register_target_pragmas): Use it to set targetm.resolve_overloaded_builtin. * config/avr/avr.c (avr_init_builtins): Supply myriads of local tree nodes used by DEF_BUILTIN. (avr_expand_builtin) <AVR_BUILTIN_ROUNDxx>: Sanity-check them. (avr_fold_builtin) <AVR_BUILTIN_BITSxx>: Fold to VIEW_COVERT_EXPR. <AVR_BUILTIN_xxBITS>: Same. libgcc/ PR target/54222 * config/avr/lib2funcs.c: New C sources for modules for libgcc.a. * config/avr/lib2-object.mk: New iterator to build objects from it. * config/avr/t-avr: Iterate lib2-object.mk to build objects from lib2funcs.c. (LIB2FUNCS_EXCLUDE): Add _clrsbdi2. (LIB1ASMFUNCS): Add: _ssabs_1, _mask1, _ret, _roundqq3, _rounduqq3, _round_s2, _round_u2, _round_2_const, _addmask_2, _round_s4, _round_u4, _round_4_const, _addmask_4, _round_x8, _rounddq3 _roundudq3, _roundda3 _rounduda3, _roundta3 _rounduta3. * config/avr/lib1funcs-fixed.S: Implement them. gcc/testsuite/ PR target/54222 * gcc.target/avr/torture/builtins-4-roundfx.c: New test. * gcc.target/avr/torture/builtins-5-countlsfx.c: New test. From-SVN: r195878
This commit is contained in:
parent
661bc682bc
commit
85d768f349
|
|
@ -1,3 +1,29 @@
|
||||||
|
2013-02-08 Georg-Johann Lay <avr@gjlay.de>
|
||||||
|
|
||||||
|
PR target/54222
|
||||||
|
* config/avr/avr.md (unspec) <UNSPEC_ROUND>: Add.
|
||||||
|
* config/avr/avr-fixed.md (ALL4QA, ALL124QA): New mode iterators.
|
||||||
|
(round<mode>3, round<mode>3_const): New expanders for fixed-mode.
|
||||||
|
(*round<mode>3.libgcc): New insns for fixed-modes.
|
||||||
|
* config/avr/builtins.def (ABSxx): Use a non-NULL LIBNAME.
|
||||||
|
(ROUNDxx, COUNTLSxx, BITSxx, xxBITS): New DEF_BUILTINs.
|
||||||
|
(ROUNDFX, COUNTLSFX, ABSFX): New DEF_BUILTINs.
|
||||||
|
* config/avr/stdfix.h (absFX, bitsFX, FXbits): Remove inline
|
||||||
|
implementations. Define to __builtin_avr_absFX,
|
||||||
|
__builtin_avr_bitsFX, __builtin_avr_FXbits, respectively.
|
||||||
|
(roundFX, countlsFX): Define to __builtin_avr_roundFX,
|
||||||
|
__builtin_avr_countlsFX, respectively.
|
||||||
|
* config/avr/avr-c.c (target.h): Include it.
|
||||||
|
(enum avr_builtin_id): New enum.
|
||||||
|
(avr_resolve_overloaded_builtin): New static function.
|
||||||
|
(avr_register_target_pragmas): Use it to set
|
||||||
|
targetm.resolve_overloaded_builtin.
|
||||||
|
* config/avr/avr.c (avr_init_builtins): Supply myriads of local
|
||||||
|
tree nodes used by DEF_BUILTIN.
|
||||||
|
(avr_expand_builtin) <AVR_BUILTIN_ROUNDxx>: Sanity-check them.
|
||||||
|
(avr_fold_builtin) <AVR_BUILTIN_BITSxx>: Fold to VIEW_COVERT_EXPR.
|
||||||
|
<AVR_BUILTIN_xxBITS>: Same.
|
||||||
|
|
||||||
2013-02-08 Richard Biener <rguenther@suse.de>
|
2013-02-08 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
* cfgloop.c (verify_loop_structure): Properly handle
|
* cfgloop.c (verify_loop_structure): Properly handle
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,226 @@
|
||||||
#include "tm_p.h"
|
#include "tm_p.h"
|
||||||
#include "cpplib.h"
|
#include "cpplib.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "target.h"
|
||||||
#include "c-family/c-common.h"
|
#include "c-family/c-common.h"
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* IDs for all the AVR builtins. */
|
||||||
|
|
||||||
|
enum avr_builtin_id
|
||||||
|
{
|
||||||
|
#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
|
||||||
|
AVR_BUILTIN_ ## NAME,
|
||||||
|
#include "builtins.def"
|
||||||
|
#undef DEF_BUILTIN
|
||||||
|
|
||||||
|
AVR_BUILTIN_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Implement `TARGET_RESOLVE_OVERLOADED_PLUGIN'. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
avr_resolve_overloaded_builtin (unsigned int iloc, tree fndecl, void *vargs)
|
||||||
|
{
|
||||||
|
tree type0, type1, fold = NULL_TREE;
|
||||||
|
enum avr_builtin_id id = AVR_BUILTIN_COUNT;
|
||||||
|
location_t loc = (location_t) iloc;
|
||||||
|
vec<tree, va_gc> &args = * (vec<tree, va_gc>*) vargs;
|
||||||
|
|
||||||
|
switch (DECL_FUNCTION_CODE (fndecl))
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVR_BUILTIN_ABSFX:
|
||||||
|
if (args.length() != 1)
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects 1 argument but %d given",
|
||||||
|
"absfx", (int) args.length());
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
type0 = TREE_TYPE (args[0]);
|
||||||
|
|
||||||
|
if (!FIXED_POINT_TYPE_P (type0))
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects a fixed-point value as argument",
|
||||||
|
"absfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (TYPE_MODE (type0))
|
||||||
|
{
|
||||||
|
case QQmode: id = AVR_BUILTIN_ABSHR; break;
|
||||||
|
case HQmode: id = AVR_BUILTIN_ABSR; break;
|
||||||
|
case SQmode: id = AVR_BUILTIN_ABSLR; break;
|
||||||
|
case DQmode: id = AVR_BUILTIN_ABSLLR; break;
|
||||||
|
|
||||||
|
case HAmode: id = AVR_BUILTIN_ABSHK; break;
|
||||||
|
case SAmode: id = AVR_BUILTIN_ABSK; break;
|
||||||
|
case DAmode: id = AVR_BUILTIN_ABSLK; break;
|
||||||
|
case TAmode: id = AVR_BUILTIN_ABSLLK; break;
|
||||||
|
|
||||||
|
case UQQmode:
|
||||||
|
case UHQmode:
|
||||||
|
case USQmode:
|
||||||
|
case UDQmode:
|
||||||
|
case UHAmode:
|
||||||
|
case USAmode:
|
||||||
|
case UDAmode:
|
||||||
|
case UTAmode:
|
||||||
|
warning_at (loc, 0, "using %qs with unsigned type has no effect",
|
||||||
|
"absfx");
|
||||||
|
return args[0];
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_at (loc, "no matching fixed-point overload found for %qs",
|
||||||
|
"absfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fold = targetm.builtin_decl (id, true);
|
||||||
|
|
||||||
|
if (fold != error_mark_node)
|
||||||
|
fold = build_function_call_vec (loc, fold, &args, NULL);
|
||||||
|
|
||||||
|
break; // absfx
|
||||||
|
|
||||||
|
case AVR_BUILTIN_ROUNDFX:
|
||||||
|
if (args.length() != 2)
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects 2 arguments but %d given",
|
||||||
|
"roundfx", (int) args.length());
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
type0 = TREE_TYPE (args[0]);
|
||||||
|
type1 = TREE_TYPE (args[1]);
|
||||||
|
|
||||||
|
if (!FIXED_POINT_TYPE_P (type0))
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects a fixed-point value as first argument",
|
||||||
|
"roundfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!INTEGRAL_TYPE_P (type1))
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects an integer value as second argument",
|
||||||
|
"roundfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (TYPE_MODE (type0))
|
||||||
|
{
|
||||||
|
case QQmode: id = AVR_BUILTIN_ROUNDHR; break;
|
||||||
|
case HQmode: id = AVR_BUILTIN_ROUNDR; break;
|
||||||
|
case SQmode: id = AVR_BUILTIN_ROUNDLR; break;
|
||||||
|
case DQmode: id = AVR_BUILTIN_ROUNDLLR; break;
|
||||||
|
|
||||||
|
case UQQmode: id = AVR_BUILTIN_ROUNDUHR; break;
|
||||||
|
case UHQmode: id = AVR_BUILTIN_ROUNDUR; break;
|
||||||
|
case USQmode: id = AVR_BUILTIN_ROUNDULR; break;
|
||||||
|
case UDQmode: id = AVR_BUILTIN_ROUNDULLR; break;
|
||||||
|
|
||||||
|
case HAmode: id = AVR_BUILTIN_ROUNDHK; break;
|
||||||
|
case SAmode: id = AVR_BUILTIN_ROUNDK; break;
|
||||||
|
case DAmode: id = AVR_BUILTIN_ROUNDLK; break;
|
||||||
|
case TAmode: id = AVR_BUILTIN_ROUNDLLK; break;
|
||||||
|
|
||||||
|
case UHAmode: id = AVR_BUILTIN_ROUNDUHK; break;
|
||||||
|
case USAmode: id = AVR_BUILTIN_ROUNDUK; break;
|
||||||
|
case UDAmode: id = AVR_BUILTIN_ROUNDULK; break;
|
||||||
|
case UTAmode: id = AVR_BUILTIN_ROUNDULLK; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_at (loc, "no matching fixed-point overload found for %qs",
|
||||||
|
"roundfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fold = targetm.builtin_decl (id, true);
|
||||||
|
|
||||||
|
if (fold != error_mark_node)
|
||||||
|
fold = build_function_call_vec (loc, fold, &args, NULL);
|
||||||
|
|
||||||
|
break; // roundfx
|
||||||
|
|
||||||
|
case AVR_BUILTIN_COUNTLSFX:
|
||||||
|
if (args.length() != 1)
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects 1 argument but %d given",
|
||||||
|
"countlsfx", (int) args.length());
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
type0 = TREE_TYPE (args[0]);
|
||||||
|
|
||||||
|
if (!FIXED_POINT_TYPE_P (type0))
|
||||||
|
{
|
||||||
|
error_at (loc, "%qs expects a fixed-point value as first argument",
|
||||||
|
"countlsfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (TYPE_MODE (type0))
|
||||||
|
{
|
||||||
|
case QQmode: id = AVR_BUILTIN_COUNTLSHR; break;
|
||||||
|
case HQmode: id = AVR_BUILTIN_COUNTLSR; break;
|
||||||
|
case SQmode: id = AVR_BUILTIN_COUNTLSLR; break;
|
||||||
|
case DQmode: id = AVR_BUILTIN_COUNTLSLLR; break;
|
||||||
|
|
||||||
|
case UQQmode: id = AVR_BUILTIN_COUNTLSUHR; break;
|
||||||
|
case UHQmode: id = AVR_BUILTIN_COUNTLSUR; break;
|
||||||
|
case USQmode: id = AVR_BUILTIN_COUNTLSULR; break;
|
||||||
|
case UDQmode: id = AVR_BUILTIN_COUNTLSULLR; break;
|
||||||
|
|
||||||
|
case HAmode: id = AVR_BUILTIN_COUNTLSHK; break;
|
||||||
|
case SAmode: id = AVR_BUILTIN_COUNTLSK; break;
|
||||||
|
case DAmode: id = AVR_BUILTIN_COUNTLSLK; break;
|
||||||
|
case TAmode: id = AVR_BUILTIN_COUNTLSLLK; break;
|
||||||
|
|
||||||
|
case UHAmode: id = AVR_BUILTIN_COUNTLSUHK; break;
|
||||||
|
case USAmode: id = AVR_BUILTIN_COUNTLSUK; break;
|
||||||
|
case UDAmode: id = AVR_BUILTIN_COUNTLSULK; break;
|
||||||
|
case UTAmode: id = AVR_BUILTIN_COUNTLSULLK; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_at (loc, "no matching fixed-point overload found for %qs",
|
||||||
|
"countlsfx");
|
||||||
|
|
||||||
|
fold = error_mark_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fold = targetm.builtin_decl (id, true);
|
||||||
|
|
||||||
|
if (fold != error_mark_node)
|
||||||
|
fold = build_function_call_vec (loc, fold, &args, NULL);
|
||||||
|
|
||||||
|
break; // countlsfx
|
||||||
|
}
|
||||||
|
|
||||||
|
return fold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Implement `REGISTER_TARGET_PRAGMAS'. */
|
/* Implement `REGISTER_TARGET_PRAGMAS'. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -49,6 +265,8 @@ avr_register_target_pragmas (void)
|
||||||
if (!ADDR_SPACE_GENERIC_P (i))
|
if (!ADDR_SPACE_GENERIC_P (i))
|
||||||
c_register_addr_space (avr_addrspace[i].name, avr_addrspace[i].id);
|
c_register_addr_space (avr_addrspace[i].name, avr_addrspace[i].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targetm.resolve_overloaded_builtin = avr_resolve_overloaded_builtin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,16 @@
|
||||||
(define_mode_iterator ALL1Q [QQ UQQ])
|
(define_mode_iterator ALL1Q [QQ UQQ])
|
||||||
(define_mode_iterator ALL2Q [HQ UHQ])
|
(define_mode_iterator ALL2Q [HQ UHQ])
|
||||||
(define_mode_iterator ALL2A [HA UHA])
|
(define_mode_iterator ALL2A [HA UHA])
|
||||||
(define_mode_iterator ALL2QA [HQ UHQ
|
|
||||||
HA UHA])
|
|
||||||
(define_mode_iterator ALL4A [SA USA])
|
(define_mode_iterator ALL4A [SA USA])
|
||||||
|
(define_mode_iterator ALL2QA [HQ UHQ HA UHA])
|
||||||
|
(define_mode_iterator ALL4QA [SQ USQ SA USA])
|
||||||
|
(define_mode_iterator ALL124QA [ QQ HQ HA SA SQ
|
||||||
|
UQQ UHQ UHA USA USQ])
|
||||||
|
|
||||||
(define_mode_iterator ALL2S [HQ HA])
|
(define_mode_iterator ALL2S [HQ HA])
|
||||||
(define_mode_iterator ALL4S [SA SQ])
|
(define_mode_iterator ALL4S [SA SQ])
|
||||||
(define_mode_iterator ALL24S [ HQ HA SA SQ])
|
(define_mode_iterator ALL24S [ HQ HA SA SQ])
|
||||||
(define_mode_iterator ALL124S [ QQ HQ HA SA SQ])
|
(define_mode_iterator ALL124S [ QQ HQ HA SA SQ])
|
||||||
(define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ])
|
(define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ])
|
||||||
|
|
||||||
;;; Conversions
|
;;; Conversions
|
||||||
|
|
@ -396,3 +398,131 @@
|
||||||
"%~call __<code><mode>3"
|
"%~call __<code><mode>3"
|
||||||
[(set_attr "type" "xcall")
|
[(set_attr "type" "xcall")
|
||||||
(set_attr "cc" "clobber")])
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
|
||||||
|
;******************************************************************************
|
||||||
|
;** Rounding
|
||||||
|
;******************************************************************************
|
||||||
|
|
||||||
|
;; "roundqq3" "rounduqq3"
|
||||||
|
;; "roundhq3" "rounduhq3" "roundha3" "rounduha3"
|
||||||
|
;; "roundsq3" "roundusq3" "roundsa3" "roundusa3"
|
||||||
|
(define_expand "round<mode>3"
|
||||||
|
[(set (match_dup 4)
|
||||||
|
(match_operand:ALL124QA 1 "register_operand" ""))
|
||||||
|
(set (reg:QI 24)
|
||||||
|
(match_dup 5))
|
||||||
|
(parallel [(set (match_dup 3)
|
||||||
|
(unspec:ALL124QA [(match_dup 4)
|
||||||
|
(reg:QI 24)] UNSPEC_ROUND))
|
||||||
|
(clobber (match_dup 4))])
|
||||||
|
(set (match_operand:ALL124QA 0 "register_operand" "")
|
||||||
|
(match_dup 3))
|
||||||
|
(use (match_operand:HI 2 "nonmemory_operand" ""))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
if (CONST_INT_P (operands[2])
|
||||||
|
&& !(optimize_size
|
||||||
|
&& 4 == GET_MODE_SIZE (<MODE>mode)))
|
||||||
|
{
|
||||||
|
emit_insn (gen_round<mode>3_const (operands[0], operands[1], operands[2]));
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input and output of the libgcc function
|
||||||
|
const unsigned int regno_in[] = { -1, 22, 22, -1, 18 };
|
||||||
|
const unsigned int regno_out[] = { -1, 24, 24, -1, 22 };
|
||||||
|
|
||||||
|
operands[3] = gen_rtx_REG (<MODE>mode, regno_out[(size_t) GET_MODE_SIZE (<MODE>mode)]);
|
||||||
|
operands[4] = gen_rtx_REG (<MODE>mode, regno_in[(size_t) GET_MODE_SIZE (<MODE>mode)]);
|
||||||
|
operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, operands[2]), HImode, 0);
|
||||||
|
// $2 is no more needed, but is referenced for expand.
|
||||||
|
operands[2] = const0_rtx;
|
||||||
|
})
|
||||||
|
|
||||||
|
;; Expand rounding with known rounding points inline so that the addend / mask
|
||||||
|
;; will be consumed by operation with immediate operands and there is no
|
||||||
|
;; need for a shift with variable offset.
|
||||||
|
|
||||||
|
;; "roundqq3_const" "rounduqq3_const"
|
||||||
|
;; "roundhq3_const" "rounduhq3_const" "roundha3_const" "rounduha3_const"
|
||||||
|
;; "roundsq3_const" "roundusq3_const" "roundsa3_const" "roundusa3_const"
|
||||||
|
(define_expand "round<mode>3_const"
|
||||||
|
[(parallel [(match_operand:ALL124QA 0 "register_operand" "")
|
||||||
|
(match_operand:ALL124QA 1 "register_operand" "")
|
||||||
|
(match_operand:HI 2 "const_int_operand" "")])]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
// The rounding point RP is $2. The smallest fractional
|
||||||
|
// bit that is not cleared by the rounding is 2^(-RP).
|
||||||
|
|
||||||
|
enum machine_mode imode = int_mode_for_mode (<MODE>mode);
|
||||||
|
int fbit = (int) GET_MODE_FBIT (<MODE>mode);
|
||||||
|
|
||||||
|
// Add-Saturate 1/2 * 2^(-RP)
|
||||||
|
|
||||||
|
double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (operands[2]));
|
||||||
|
rtx x_add = const_fixed_from_double_int (i_add, <MODE>mode);
|
||||||
|
|
||||||
|
if (SIGNED_FIXED_POINT_MODE_P (<MODE>mode))
|
||||||
|
emit_move_insn (operands[0],
|
||||||
|
gen_rtx_SS_PLUS (<MODE>mode, operands[1], x_add));
|
||||||
|
else
|
||||||
|
emit_move_insn (operands[0],
|
||||||
|
gen_rtx_US_PLUS (<MODE>mode, operands[1], x_add));
|
||||||
|
|
||||||
|
// Keep all bits from RP and higher: ... 2^(-RP)
|
||||||
|
// Clear all bits from RP+1 and lower: 2^(-RP-1) ...
|
||||||
|
// Rounding point ^^^^^^^
|
||||||
|
// Added above ^^^^^^^^^
|
||||||
|
|
||||||
|
rtx xreg = simplify_gen_subreg (imode, operands[0], <MODE>mode, 0);
|
||||||
|
rtx xmask = immed_double_int_const (-i_add - i_add, imode);
|
||||||
|
|
||||||
|
if (SImode == imode)
|
||||||
|
emit_insn (gen_andsi3 (xreg, xreg, xmask));
|
||||||
|
else if (HImode == imode)
|
||||||
|
emit_insn (gen_andhi3 (xreg, xreg, xmask));
|
||||||
|
else if (QImode == imode)
|
||||||
|
emit_insn (gen_andqi3 (xreg, xreg, xmask));
|
||||||
|
else
|
||||||
|
gcc_unreachable();
|
||||||
|
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
;; "*roundqq3.libgcc" "*rounduqq3.libgcc"
|
||||||
|
(define_insn "*round<mode>3.libgcc"
|
||||||
|
[(set (reg:ALL1Q 24)
|
||||||
|
(unspec:ALL1Q [(reg:ALL1Q 22)
|
||||||
|
(reg:QI 24)] UNSPEC_ROUND))
|
||||||
|
(clobber (reg:ALL1Q 22))]
|
||||||
|
""
|
||||||
|
"%~call __round<mode>3"
|
||||||
|
[(set_attr "type" "xcall")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
;; "*roundhq3.libgcc" "*rounduhq3.libgcc"
|
||||||
|
;; "*roundha3.libgcc" "*rounduha3.libgcc"
|
||||||
|
(define_insn "*round<mode>3.libgcc"
|
||||||
|
[(set (reg:ALL2QA 24)
|
||||||
|
(unspec:ALL2QA [(reg:ALL2QA 22)
|
||||||
|
(reg:QI 24)] UNSPEC_ROUND))
|
||||||
|
(clobber (reg:ALL2QA 22))]
|
||||||
|
""
|
||||||
|
"%~call __round<mode>3"
|
||||||
|
[(set_attr "type" "xcall")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
||||||
|
;; "*roundsq3.libgcc" "*roundusq3.libgcc"
|
||||||
|
;; "*roundsa3.libgcc" "*roundusa3.libgcc"
|
||||||
|
(define_insn "*round<mode>3.libgcc"
|
||||||
|
[(set (reg:ALL4QA 22)
|
||||||
|
(unspec:ALL4QA [(reg:ALL4QA 18)
|
||||||
|
(reg:QI 24)] UNSPEC_ROUND))
|
||||||
|
(clobber (reg:ALL4QA 18))]
|
||||||
|
""
|
||||||
|
"%~call __round<mode>3"
|
||||||
|
[(set_attr "type" "xcall")
|
||||||
|
(set_attr "cc" "clobber")])
|
||||||
|
|
|
||||||
|
|
@ -11489,32 +11489,118 @@ avr_init_builtins (void)
|
||||||
const_memx_ptr_type_node,
|
const_memx_ptr_type_node,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
tree hr_ftype_hr
|
#define ITYP(T) \
|
||||||
= build_function_type_list (short_fract_type_node,
|
lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
|
||||||
short_fract_type_node, NULL);
|
|
||||||
tree r_ftype_r
|
|
||||||
= build_function_type_list (fract_type_node,
|
|
||||||
fract_type_node, NULL);
|
|
||||||
tree lr_ftype_lr
|
|
||||||
= build_function_type_list (long_fract_type_node,
|
|
||||||
long_fract_type_node, NULL);
|
|
||||||
tree llr_ftype_llr
|
|
||||||
= build_function_type_list (long_long_fract_type_node,
|
|
||||||
long_long_fract_type_node, NULL);
|
|
||||||
|
|
||||||
tree hk_ftype_hk
|
|
||||||
= build_function_type_list (short_accum_type_node,
|
|
||||||
short_accum_type_node, NULL);
|
|
||||||
tree k_ftype_k
|
|
||||||
= build_function_type_list (accum_type_node,
|
|
||||||
accum_type_node, NULL);
|
|
||||||
tree lk_ftype_lk
|
|
||||||
= build_function_type_list (long_accum_type_node,
|
|
||||||
long_accum_type_node, NULL);
|
|
||||||
tree llk_ftype_llk
|
|
||||||
= build_function_type_list (long_long_accum_type_node,
|
|
||||||
long_long_accum_type_node, NULL);
|
|
||||||
|
|
||||||
|
#define FX_FTYPE_FX(fx) \
|
||||||
|
tree fx##r_ftype_##fx##r \
|
||||||
|
= build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
|
||||||
|
tree fx##k_ftype_##fx##k \
|
||||||
|
= build_function_type_list (node_##fx##k, node_##fx##k, NULL)
|
||||||
|
|
||||||
|
#define FX_FTYPE_FX_INT(fx) \
|
||||||
|
tree fx##r_ftype_##fx##r_int \
|
||||||
|
= build_function_type_list (node_##fx##r, node_##fx##r, \
|
||||||
|
integer_type_node, NULL); \
|
||||||
|
tree fx##k_ftype_##fx##k_int \
|
||||||
|
= build_function_type_list (node_##fx##k, node_##fx##k, \
|
||||||
|
integer_type_node, NULL)
|
||||||
|
|
||||||
|
#define INT_FTYPE_FX(fx) \
|
||||||
|
tree int_ftype_##fx##r \
|
||||||
|
= build_function_type_list (integer_type_node, node_##fx##r, NULL); \
|
||||||
|
tree int_ftype_##fx##k \
|
||||||
|
= build_function_type_list (integer_type_node, node_##fx##k, NULL)
|
||||||
|
|
||||||
|
#define INTX_FTYPE_FX(fx) \
|
||||||
|
tree int##fx##r_ftype_##fx##r \
|
||||||
|
= build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
|
||||||
|
tree int##fx##k_ftype_##fx##k \
|
||||||
|
= build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
|
||||||
|
|
||||||
|
#define FX_FTYPE_INTX(fx) \
|
||||||
|
tree fx##r_ftype_int##fx##r \
|
||||||
|
= build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
|
||||||
|
tree fx##k_ftype_int##fx##k \
|
||||||
|
= build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
|
||||||
|
|
||||||
|
tree node_hr = short_fract_type_node;
|
||||||
|
tree node_r = fract_type_node;
|
||||||
|
tree node_lr = long_fract_type_node;
|
||||||
|
tree node_llr = long_long_fract_type_node;
|
||||||
|
|
||||||
|
tree node_uhr = unsigned_short_fract_type_node;
|
||||||
|
tree node_ur = unsigned_fract_type_node;
|
||||||
|
tree node_ulr = unsigned_long_fract_type_node;
|
||||||
|
tree node_ullr = unsigned_long_long_fract_type_node;
|
||||||
|
|
||||||
|
tree node_hk = short_accum_type_node;
|
||||||
|
tree node_k = accum_type_node;
|
||||||
|
tree node_lk = long_accum_type_node;
|
||||||
|
tree node_llk = long_long_accum_type_node;
|
||||||
|
|
||||||
|
tree node_uhk = unsigned_short_accum_type_node;
|
||||||
|
tree node_uk = unsigned_accum_type_node;
|
||||||
|
tree node_ulk = unsigned_long_accum_type_node;
|
||||||
|
tree node_ullk = unsigned_long_long_accum_type_node;
|
||||||
|
|
||||||
|
|
||||||
|
/* For absfx builtins. */
|
||||||
|
|
||||||
|
FX_FTYPE_FX (h);
|
||||||
|
FX_FTYPE_FX ();
|
||||||
|
FX_FTYPE_FX (l);
|
||||||
|
FX_FTYPE_FX (ll);
|
||||||
|
|
||||||
|
/* For roundfx builtins. */
|
||||||
|
|
||||||
|
FX_FTYPE_FX_INT (h);
|
||||||
|
FX_FTYPE_FX_INT ();
|
||||||
|
FX_FTYPE_FX_INT (l);
|
||||||
|
FX_FTYPE_FX_INT (ll);
|
||||||
|
|
||||||
|
FX_FTYPE_FX_INT (uh);
|
||||||
|
FX_FTYPE_FX_INT (u);
|
||||||
|
FX_FTYPE_FX_INT (ul);
|
||||||
|
FX_FTYPE_FX_INT (ull);
|
||||||
|
|
||||||
|
/* For countlsfx builtins. */
|
||||||
|
|
||||||
|
INT_FTYPE_FX (h);
|
||||||
|
INT_FTYPE_FX ();
|
||||||
|
INT_FTYPE_FX (l);
|
||||||
|
INT_FTYPE_FX (ll);
|
||||||
|
|
||||||
|
INT_FTYPE_FX (uh);
|
||||||
|
INT_FTYPE_FX (u);
|
||||||
|
INT_FTYPE_FX (ul);
|
||||||
|
INT_FTYPE_FX (ull);
|
||||||
|
|
||||||
|
/* For bitsfx builtins. */
|
||||||
|
|
||||||
|
INTX_FTYPE_FX (h);
|
||||||
|
INTX_FTYPE_FX ();
|
||||||
|
INTX_FTYPE_FX (l);
|
||||||
|
INTX_FTYPE_FX (ll);
|
||||||
|
|
||||||
|
INTX_FTYPE_FX (uh);
|
||||||
|
INTX_FTYPE_FX (u);
|
||||||
|
INTX_FTYPE_FX (ul);
|
||||||
|
INTX_FTYPE_FX (ull);
|
||||||
|
|
||||||
|
/* For fxbits builtins. */
|
||||||
|
|
||||||
|
FX_FTYPE_INTX (h);
|
||||||
|
FX_FTYPE_INTX ();
|
||||||
|
FX_FTYPE_INTX (l);
|
||||||
|
FX_FTYPE_INTX (ll);
|
||||||
|
|
||||||
|
FX_FTYPE_INTX (uh);
|
||||||
|
FX_FTYPE_INTX (u);
|
||||||
|
FX_FTYPE_INTX (ul);
|
||||||
|
FX_FTYPE_INTX (ull);
|
||||||
|
|
||||||
|
|
||||||
#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
|
#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
|
||||||
{ \
|
{ \
|
||||||
int id = AVR_BUILTIN_ ## NAME; \
|
int id = AVR_BUILTIN_ ## NAME; \
|
||||||
|
|
@ -11647,7 +11733,50 @@ avr_expand_builtin (tree exp, rtx target,
|
||||||
" as first argument", bname);
|
" as first argument", bname);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
|
||||||
|
case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
|
||||||
|
case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
|
||||||
|
case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
|
||||||
|
|
||||||
|
case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
|
||||||
|
case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
|
||||||
|
case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
|
||||||
|
case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
|
||||||
|
|
||||||
|
/* Warn about odd rounding. Rounding points >= FBIT will have
|
||||||
|
no effect. */
|
||||||
|
|
||||||
|
if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
|
||||||
|
|
||||||
|
if (rbit >= (int) GET_MODE_FBIT (mode))
|
||||||
|
{
|
||||||
|
warning (OPT_Wextra, "rounding to %d bits has no effect for "
|
||||||
|
"fixed-point value with %d fractional bits",
|
||||||
|
rbit, GET_MODE_FBIT (mode));
|
||||||
|
|
||||||
|
return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
|
||||||
|
EXPAND_NORMAL);
|
||||||
|
}
|
||||||
|
else if (rbit <= - (int) GET_MODE_IBIT (mode))
|
||||||
|
{
|
||||||
|
warning (0, "rounding result will always be 0");
|
||||||
|
return CONST0_RTX (mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rounding points RP satisfies now: -IBIT < RP < FBIT.
|
||||||
|
|
||||||
|
TR 18037 only specifies results for RP > 0. However, the
|
||||||
|
remaining cases of -IBIT < RP <= 0 can easily be supported
|
||||||
|
without any additional overhead. */
|
||||||
|
|
||||||
|
break; /* round */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No fold found and no insn: Call support function from libgcc. */
|
/* No fold found and no insn: Call support function from libgcc. */
|
||||||
|
|
@ -11736,6 +11865,31 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
|
||||||
|
|
||||||
return avr_fold_absfx (arg[0]);
|
return avr_fold_absfx (arg[0]);
|
||||||
|
|
||||||
|
case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
|
||||||
|
case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
|
||||||
|
case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
|
||||||
|
case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
|
||||||
|
|
||||||
|
case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
|
||||||
|
case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
|
||||||
|
case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
|
||||||
|
case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
|
||||||
|
|
||||||
|
case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
|
||||||
|
case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
|
||||||
|
case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
|
||||||
|
case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
|
||||||
|
|
||||||
|
case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
|
||||||
|
case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
|
||||||
|
case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
|
||||||
|
case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
|
||||||
|
|
||||||
|
gcc_assert (TYPE_PRECISION (val_type)
|
||||||
|
== TYPE_PRECISION (TREE_TYPE (arg[0])));
|
||||||
|
|
||||||
|
return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
|
||||||
|
|
||||||
case AVR_BUILTIN_INSERT_BITS:
|
case AVR_BUILTIN_INSERT_BITS:
|
||||||
{
|
{
|
||||||
tree tbits = arg[1];
|
tree tbits = arg[1];
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
UNSPEC_COPYSIGN
|
UNSPEC_COPYSIGN
|
||||||
UNSPEC_IDENTITY
|
UNSPEC_IDENTITY
|
||||||
UNSPEC_INSERT_BITS
|
UNSPEC_INSERT_BITS
|
||||||
|
UNSPEC_ROUND
|
||||||
])
|
])
|
||||||
|
|
||||||
(define_c_enum "unspecv"
|
(define_c_enum "unspecv"
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,109 @@ DEF_BUILTIN (FLASH_SEGMENT, 1, char_ftype_const_memx_ptr, flash_segment, NULL)
|
||||||
|
|
||||||
/* 7.18a.6.2 The fixed-point absolute value functions. */
|
/* 7.18a.6.2 The fixed-point absolute value functions. */
|
||||||
|
|
||||||
DEF_BUILTIN (ABSHR, 1, hr_ftype_hr, ssabsqq2, NULL)
|
DEF_BUILTIN (ABSHR, 1, hr_ftype_hr, ssabsqq2, "__ssabs_1")
|
||||||
DEF_BUILTIN (ABSR, 1, r_ftype_r, ssabshq2, NULL)
|
DEF_BUILTIN (ABSR, 1, r_ftype_r, ssabshq2, "__ssabs_2")
|
||||||
DEF_BUILTIN (ABSLR, 1, lr_ftype_lr, ssabssq2, NULL)
|
DEF_BUILTIN (ABSLR, 1, lr_ftype_lr, ssabssq2, "__ssabs_4")
|
||||||
DEF_BUILTIN (ABSLLR, 1, llr_ftype_llr, nothing, "__ssabsdq2") // GCC extension
|
DEF_BUILTIN (ABSLLR, -1, llr_ftype_llr, nothing, "__ssabsdq2") // GCC extension
|
||||||
|
|
||||||
DEF_BUILTIN (ABSHK, 1, hk_ftype_hk, ssabsha2, NULL)
|
DEF_BUILTIN (ABSHK, 1, hk_ftype_hk, ssabsha2, "__ssabs_2")
|
||||||
DEF_BUILTIN (ABSK, 1, k_ftype_k, ssabssa2, NULL)
|
DEF_BUILTIN (ABSK, 1, k_ftype_k, ssabssa2, "__ssabs_4")
|
||||||
DEF_BUILTIN (ABSLK, -1, lk_ftype_lk, nothing, "__ssabsda2")
|
DEF_BUILTIN (ABSLK, -1, lk_ftype_lk, nothing, "__ssabsda2")
|
||||||
DEF_BUILTIN (ABSLLK, -1, llk_ftype_llk, nothing, "__ssabsta2") // GCC extension
|
DEF_BUILTIN (ABSLLK, -1, llk_ftype_llk, nothing, "__ssabsta2") // GCC extension
|
||||||
|
|
||||||
|
/* 7.18a.6.3 The fixed-point round functions. */
|
||||||
|
|
||||||
|
DEF_BUILTIN (ROUNDHR, 2, hr_ftype_hr_int, roundqq3, "__roundhr")
|
||||||
|
DEF_BUILTIN (ROUNDR, 2, r_ftype_r_int, roundhq3, "__roundr")
|
||||||
|
DEF_BUILTIN (ROUNDLR, 2, lr_ftype_lr_int, roundsq3, "__roundlr")
|
||||||
|
DEF_BUILTIN (ROUNDLLR, -1, llr_ftype_llr_int, nothing, "__rounddq3") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (ROUNDUHR, 2, uhr_ftype_uhr_int, rounduqq3, "__rounduhr")
|
||||||
|
DEF_BUILTIN (ROUNDUR, 2, ur_ftype_ur_int, rounduhq3, "__roundur")
|
||||||
|
DEF_BUILTIN (ROUNDULR, 2, ulr_ftype_ulr_int, roundusq3, "__roundulr")
|
||||||
|
DEF_BUILTIN (ROUNDULLR, -1, ullr_ftype_ullr_int, nothing, "__roundudq3") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (ROUNDHK, 2, hk_ftype_hk_int, roundha3, "__roundhk")
|
||||||
|
DEF_BUILTIN (ROUNDK, 2, k_ftype_k_int, roundsa3, "__roundk")
|
||||||
|
DEF_BUILTIN (ROUNDLK, -1, lk_ftype_lk_int, nothing, "__roundda3")
|
||||||
|
DEF_BUILTIN (ROUNDLLK, -1, llk_ftype_llk_int, nothing, "__roundta3") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (ROUNDUHK, 2, uhk_ftype_uhk_int, rounduha3, "__rounduhk")
|
||||||
|
DEF_BUILTIN (ROUNDUK, 2, uk_ftype_uk_int, roundusa3, "__rounduk")
|
||||||
|
DEF_BUILTIN (ROUNDULK, -1, ulk_ftype_ulk_int, nothing, "__rounduda3")
|
||||||
|
DEF_BUILTIN (ROUNDULLK, -1, ullk_ftype_ullk_int, nothing, "__rounduta3") // GCC extension
|
||||||
|
|
||||||
|
/* 7.18a.6.4 The fixed-point bit countls functions. */
|
||||||
|
|
||||||
|
DEF_BUILTIN (COUNTLSHR, -1, int_ftype_hr, nothing, "__countlsqi2")
|
||||||
|
DEF_BUILTIN (COUNTLSR, -1, int_ftype_r, nothing, "__countlshi2")
|
||||||
|
DEF_BUILTIN (COUNTLSLR, -1, int_ftype_lr, nothing, "__countlssi2")
|
||||||
|
DEF_BUILTIN (COUNTLSLLR, -1, int_ftype_llr, nothing, "__countlsdi2") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (COUNTLSUHR, -1, int_ftype_uhr, nothing, "__countlsuqi2")
|
||||||
|
DEF_BUILTIN (COUNTLSUR, -1, int_ftype_ur, nothing, "__countlsuhi2")
|
||||||
|
DEF_BUILTIN (COUNTLSULR, -1, int_ftype_ulr, nothing, "__countlsusi2")
|
||||||
|
DEF_BUILTIN (COUNTLSULLR, -1, int_ftype_ullr, nothing, "__countlsudi2") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (COUNTLSHK, -1, int_ftype_hk, nothing, "__countlshi2")
|
||||||
|
DEF_BUILTIN (COUNTLSK, -1, int_ftype_k, nothing, "__countlssi2")
|
||||||
|
DEF_BUILTIN (COUNTLSLK, -1, int_ftype_lk, nothing, "__countlsdi2")
|
||||||
|
DEF_BUILTIN (COUNTLSLLK, -1, int_ftype_llk, nothing, "__countlsdi2") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (COUNTLSUHK, -1, int_ftype_uhk, nothing, "__countlsuhi2")
|
||||||
|
DEF_BUILTIN (COUNTLSUK, -1, int_ftype_uk, nothing, "__countlsusi2")
|
||||||
|
DEF_BUILTIN (COUNTLSULK, -1, int_ftype_ulk, nothing, "__countlsudi2")
|
||||||
|
DEF_BUILTIN (COUNTLSULLK, -1, int_ftype_ullk, nothing, "__countlsudi2") // GCC extension
|
||||||
|
|
||||||
|
/* 7.18a.6.5 The bitwise fixed-point to integer conversion functions. */
|
||||||
|
|
||||||
|
DEF_BUILTIN (BITSHR, -1, inthr_ftype_hr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSR, -1, intr_ftype_r, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSLR, -1, intlr_ftype_lr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSLLR, -1, intllr_ftype_llr, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (BITSUHR, -1, intuhr_ftype_uhr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSUR, -1, intur_ftype_ur, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSULR, -1, intulr_ftype_ulr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSULLR, -1, intullr_ftype_ullr, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (BITSHK, -1, inthk_ftype_hk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSK, -1, intk_ftype_k, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSLK, -1, intlk_ftype_lk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSLLK, -1, intllk_ftype_llk, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN (BITSUHK, -1, intuhk_ftype_uhk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSUK, -1, intuk_ftype_uk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSULK, -1, intulk_ftype_ulk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (BITSULLK, -1, intullk_ftype_ullk, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
|
||||||
|
/* 7.18a.6.6 The bitwise integer to fixed-point conversion functions. */
|
||||||
|
|
||||||
|
DEF_BUILTIN ( HRBITS, -1, hr_ftype_inthr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( RBITS, -1, r_ftype_intr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( LRBITS, -1, lr_ftype_intlr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( LLRBITS, -1, llr_ftype_intllr, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN ( UHRBITS, -1, uhr_ftype_intuhr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( URBITS, -1, ur_ftype_intur, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( ULRBITS, -1, ulr_ftype_intulr, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (ULLRBITS, -1, ullr_ftype_intullr, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN ( HKBITS, -1, hk_ftype_inthk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( KBITS, -1, k_ftype_intk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( LKBITS, -1, lk_ftype_intlk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( LLKBITS, -1, llk_ftype_intllk, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
DEF_BUILTIN ( UHKBITS, -1, uhk_ftype_intuhk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( UKBITS, -1, uk_ftype_intuk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN ( ULKBITS, -1, ulk_ftype_intulk, nothing, "__ret")
|
||||||
|
DEF_BUILTIN (ULLKBITS, -1, ullk_ftype_intullk, nothing, "__ret") // GCC extension
|
||||||
|
|
||||||
|
/* Overloaded */
|
||||||
|
|
||||||
|
/* 7.18a.6.7 Type-generic fixed-point functions. */
|
||||||
|
|
||||||
|
DEF_BUILTIN (ABSFX, -1, void_ftype_void /* dummy */, nothing, NULL)
|
||||||
|
DEF_BUILTIN (ROUNDFX, -1, void_ftype_void /* dummy */, nothing, NULL)
|
||||||
|
DEF_BUILTIN (COUNTLSFX, -1, void_ftype_void /* dummy */, nothing, NULL)
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,6 @@
|
||||||
|
|
||||||
#include <stdfix-gcc.h>
|
#include <stdfix-gcc.h>
|
||||||
|
|
||||||
#define _GCC_TYPEPUN(A, B) \
|
|
||||||
__builtin_memcpy (&A, &B, sizeof (A))
|
|
||||||
|
|
||||||
/* 7.18a.6 The fixed-point intrinsic functions. */
|
|
||||||
|
|
||||||
#if __SIZEOF_INT__ == 2
|
#if __SIZEOF_INT__ == 2
|
||||||
|
|
||||||
|
|
@ -66,8 +62,7 @@ typedef long long unsigned int uint_ulk_t;
|
||||||
typedef long long int int_llk_t;
|
typedef long long int int_llk_t;
|
||||||
typedef long long unsigned int uint_ullk_t;
|
typedef long long unsigned int uint_ullk_t;
|
||||||
|
|
||||||
#else /* __SIZEOF_INT__ = 1 (for -mint8) */
|
#elif __SIZEOF_INT__ == 1 /* -mint8 */
|
||||||
|
|
||||||
|
|
||||||
typedef signed char int_hr_t;
|
typedef signed char int_hr_t;
|
||||||
typedef unsigned char uint_uhr_t;
|
typedef unsigned char uint_uhr_t;
|
||||||
|
|
@ -84,356 +79,158 @@ typedef long long unsigned int uint_ulr_t;
|
||||||
typedef long long int int_k_t;
|
typedef long long int int_k_t;
|
||||||
typedef long long unsigned int uint_uk_t;
|
typedef long long unsigned int uint_uk_t;
|
||||||
|
|
||||||
#endif /* __SIZEOF_INT__ == 2 */
|
#endif /* __SIZEOF_INT__ == 1, 2 */
|
||||||
|
|
||||||
|
|
||||||
/* 7.18a.6.2 The fixed-point absolute value functions. */
|
/* 7.18a.6 The fixed-point intrinsic functions. */
|
||||||
|
|
||||||
/* short fract (hr): abshr */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
/* 7.18a.6.2 The fixed-point absolute value functions. */
|
||||||
short fract abshr (const short fract __q)
|
|
||||||
{
|
|
||||||
return __builtin_avr_abshr (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fract (r): absr */
|
#define abshr __builtin_avr_abshr
|
||||||
|
#define absr __builtin_avr_absr
|
||||||
|
#define abslr __builtin_avr_abslr
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define abshk __builtin_avr_abshk
|
||||||
fract absr (const fract __q)
|
#define absk __builtin_avr_absk
|
||||||
{
|
|
||||||
return __builtin_avr_absr (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* long fract (lr): abslr */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
long fract abslr (const long fract __q)
|
|
||||||
{
|
|
||||||
return __builtin_avr_abslr (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* short accum (hk): abshk */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
short accum abshk (const short accum __q)
|
|
||||||
{
|
|
||||||
return __builtin_avr_abshk (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* accum (k): absk */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
accum absk (const accum __q)
|
|
||||||
{
|
|
||||||
return __builtin_avr_absk (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __SIZEOF_INT__ == 2
|
#if __SIZEOF_INT__ == 2
|
||||||
|
|
||||||
/* long long fract (llr): absllr */
|
#define abslk __builtin_avr_abslk
|
||||||
|
#define absllr __builtin_avr_absllr /* GCC Extension */
|
||||||
|
#define absllk __builtin_avr_absllk /* GCC Extension */
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#endif /* sizeof (int) == 2 */
|
||||||
long long fract absllr (const long long fract __q) /* GCC extension */
|
|
||||||
{
|
|
||||||
return __builtin_avr_absllr (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* long accum (lk): abslk */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
long accum abslk (const long accum __q)
|
|
||||||
{
|
|
||||||
return __builtin_avr_abslk (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* long long accum (llk): absllk */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
long long accum absllk (const long long accum __q) /* GCC extension */
|
|
||||||
{
|
|
||||||
return __builtin_avr_absllk (__q);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __SIZEOF_INT__ == 2 */
|
|
||||||
|
|
||||||
|
|
||||||
/* 7.18a.6.5 The bitwise fixed-point to integer conversion functions. */
|
/* 7.18a.6.3 The fixed-point round functions. */
|
||||||
/* 7.18a.6.6 The bitwise integer to fixed-point conversion functions. */
|
|
||||||
|
|
||||||
/* short fract (hr): bitshr, bitsuhr, hrbits, uhrbits */
|
/* The Embedded-C paper specifies results only for rounding points
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
0 < RP < FBIT
|
||||||
int_hr_t bitshr (const short fract __q)
|
|
||||||
{
|
As an extension, the following functions work as expected
|
||||||
int_hr_t __result;
|
with rounding points
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
-IBIT < RP < FBIT
|
||||||
uint_uhr_t bitsuhr (const unsigned short fract __q)
|
|
||||||
{
|
For example, rounding an accum with a rounding point of -1 will
|
||||||
uint_uhr_t __result;
|
result in an even integer value. */
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define roundhr __builtin_avr_roundhr
|
||||||
short fract hrbits (const int_hr_t __i)
|
#define roundr __builtin_avr_roundr
|
||||||
{
|
#define roundlr __builtin_avr_roundlr
|
||||||
short fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define rounduhr __builtin_avr_rounduhr
|
||||||
unsigned short fract uhrbits (const uint_uhr_t __i)
|
#define roundur __builtin_avr_roundur
|
||||||
{
|
#define roundulr __builtin_avr_roundulr
|
||||||
unsigned short fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fract (r): bitsr, bitsur, rbits, urbits */
|
#define roundhk __builtin_avr_roundhk
|
||||||
|
#define roundk __builtin_avr_roundk
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define rounduhk __builtin_avr_rounduhk
|
||||||
int_r_t bitsr (const fract __q)
|
#define rounduk __builtin_avr_rounduk
|
||||||
{
|
|
||||||
int_r_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
uint_ur_t bitsur (const unsigned fract __q)
|
|
||||||
{
|
|
||||||
uint_ur_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
fract rbits (const int_r_t __i)
|
|
||||||
{
|
|
||||||
fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
unsigned fract urbits (const uint_ur_t __i)
|
|
||||||
{
|
|
||||||
unsigned fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* long fract (lr): bitslr, bitsulr, lrbits, ulrbits */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
int_lr_t bitslr (const long fract __q)
|
|
||||||
{
|
|
||||||
int_lr_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
uint_ulr_t bitsulr (const unsigned long fract __q)
|
|
||||||
{
|
|
||||||
uint_ulr_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
long fract lrbits (const int_lr_t __i)
|
|
||||||
{
|
|
||||||
long fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
unsigned long fract ulrbits (const uint_ulr_t __i)
|
|
||||||
{
|
|
||||||
unsigned long fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* short accum (hk): bitshk, bitsuhk, hkbits, uhkbits */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
int_hk_t bitshk (const short accum __q)
|
|
||||||
{
|
|
||||||
int_hk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
uint_uhk_t bitsuhk (const unsigned short accum __q)
|
|
||||||
{
|
|
||||||
uint_uhk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
short accum hkbits (const int_hk_t __i)
|
|
||||||
{
|
|
||||||
short accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
unsigned short accum uhkbits (const uint_uhk_t __i)
|
|
||||||
{
|
|
||||||
unsigned short accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* accum (k): bitsk, bitsuk, kbits, ukbits */
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
int_k_t bitsk (const accum __q)
|
|
||||||
{
|
|
||||||
int_k_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
uint_uk_t bitsuk (const unsigned accum __q)
|
|
||||||
{
|
|
||||||
uint_uk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
accum kbits (const int_k_t __i)
|
|
||||||
{
|
|
||||||
accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
unsigned accum ukbits (const uint_uk_t __i)
|
|
||||||
{
|
|
||||||
unsigned accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __SIZEOF_INT__ == 2
|
#if __SIZEOF_INT__ == 2
|
||||||
|
|
||||||
/* long long fract (llr): bitsllr, bitsullr, llrbits, ullrbits */
|
#define roundlk __builtin_avr_roundlk
|
||||||
|
#define roundulk __builtin_avr_roundulk
|
||||||
|
#define roundllr __builtin_avr_roundllr /* GCC Extension */
|
||||||
|
#define roundullr __builtin_avr_roundullr /* GCC Extension */
|
||||||
|
#define roundllk __builtin_avr_roundllk /* GCC Extension */
|
||||||
|
#define roundullk __builtin_avr_roundullk /* GCC Extension */
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#endif /* sizeof (int) == 2 */
|
||||||
int_llr_t bitsllr (const long long fract __q)
|
|
||||||
{
|
|
||||||
int_llr_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
uint_ullr_t bitsullr (const unsigned long long fract __q)
|
|
||||||
{
|
|
||||||
uint_ullr_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
/* 7.18a.6.4 The fixed-point bit countls functions. */
|
||||||
long long fract llrbits (const int_llr_t __i)
|
|
||||||
{
|
|
||||||
long long fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define countlshr __builtin_avr_countlshr
|
||||||
unsigned long long fract ullrbits (const uint_ullr_t __i)
|
#define countlsr __builtin_avr_countlsr
|
||||||
{
|
#define countlslr __builtin_avr_countlslr
|
||||||
unsigned long long fract __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* long accum (lk): bitslk, bitsulk, lkbits, ulkbits */
|
#define countlsuhr __builtin_avr_countlsuhr
|
||||||
|
#define countlsur __builtin_avr_countlsur
|
||||||
|
#define countlsulr __builtin_avr_countlsulr
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define countlshk __builtin_avr_countlshk
|
||||||
int_lk_t bitslk (const long accum __q)
|
#define countlsk __builtin_avr_countlsk
|
||||||
{
|
|
||||||
int_lk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define countlsuhk __builtin_avr_countlsuhk
|
||||||
uint_ulk_t bitsulk (const unsigned long accum __q)
|
#define countlsuk __builtin_avr_countlsuk
|
||||||
{
|
|
||||||
uint_ulk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#if __SIZEOF_INT__ == 2
|
||||||
long accum lkbits (const int_lk_t __i)
|
|
||||||
{
|
|
||||||
long accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define countlslk __builtin_avr_countlslk
|
||||||
unsigned long accum ulkbits (const uint_ulk_t __i)
|
#define countlsulk __builtin_avr_countlsulk
|
||||||
{
|
#define countlsllr __builtin_avr_countlsllr /* GCC Extension */
|
||||||
unsigned long accum __result;
|
#define countlsullr __builtin_avr_countlsullr /* GCC Extension */
|
||||||
_GCC_TYPEPUN (__result, __i);
|
#define countlsllk __builtin_avr_countlsllk /* GCC Extension */
|
||||||
return __result;
|
#define countlsullk __builtin_avr_countlsullk /* GCC Extension */
|
||||||
}
|
|
||||||
|
|
||||||
/* long long accum (llk): bitsllk, bitsullk, llkbits, ullkbits */
|
#endif /* sizeof (int) == 2 */
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
|
||||||
int_llk_t bitsllk (const long long accum __q)
|
|
||||||
{
|
|
||||||
int_llk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
/* 7.18a.6.5 The bitwise fixed-point to integer conversion functions. */
|
||||||
uint_ullk_t bitsullk (const unsigned long long accum __q)
|
|
||||||
{
|
|
||||||
uint_ullk_t __result;
|
|
||||||
_GCC_TYPEPUN (__result, __q);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define bitshr __builtin_avr_bitshr
|
||||||
long long accum llkbits (const int_llk_t __i)
|
#define bitsr __builtin_avr_bitsr
|
||||||
{
|
#define bitslr __builtin_avr_bitslr
|
||||||
long long accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
|
||||||
return __result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ __attribute__((__always_inline__))
|
#define bitsuhr __builtin_avr_bitsuhr
|
||||||
unsigned long long accum ullkbits (const uint_ullk_t __i)
|
#define bitsur __builtin_avr_bitsur
|
||||||
{
|
#define bitsulr __builtin_avr_bitsulr
|
||||||
unsigned long long accum __result;
|
|
||||||
_GCC_TYPEPUN (__result, __i);
|
#define bitshk __builtin_avr_bitshk
|
||||||
return __result;
|
#define bitsk __builtin_avr_bitsk
|
||||||
}
|
|
||||||
|
#define bitsuhk __builtin_avr_bitsuhk
|
||||||
|
#define bitsuk __builtin_avr_bitsuk
|
||||||
|
|
||||||
|
#if __SIZEOF_INT__ == 2
|
||||||
|
|
||||||
|
#define bitslk __builtin_avr_bitslk
|
||||||
|
#define bitsulk __builtin_avr_bitsulk
|
||||||
|
#define bitsllr __builtin_avr_bitsllr /* GCC Extension */
|
||||||
|
#define bitsullr __builtin_avr_bitsullr /* GCC Extension */
|
||||||
|
#define bitsllk __builtin_avr_bitsllk /* GCC Extension */
|
||||||
|
#define bitsullk __builtin_avr_bitsullk /* GCC Extension */
|
||||||
|
|
||||||
|
#endif /* sizeof (int) == 2 */
|
||||||
|
|
||||||
|
|
||||||
|
/* 7.18a.6.6 The bitwise integer to fixed-point conversion functions. */
|
||||||
|
|
||||||
|
#define hrbits __builtin_avr_hrbits
|
||||||
|
#define rbits __builtin_avr_rbits
|
||||||
|
#define lrbits __builtin_avr_lrbits
|
||||||
|
|
||||||
|
#define uhrbits __builtin_avr_uhrbits
|
||||||
|
#define urbits __builtin_avr_urbits
|
||||||
|
#define ulrbits __builtin_avr_ulrbits
|
||||||
|
|
||||||
|
#define hkbits __builtin_avr_hkbits
|
||||||
|
#define kbits __builtin_avr_kbits
|
||||||
|
|
||||||
|
#define uhkbits __builtin_avr_uhkbits
|
||||||
|
#define ukbits __builtin_avr_ukbits
|
||||||
|
|
||||||
|
#if __SIZEOF_INT__ == 2
|
||||||
|
|
||||||
|
#define lkbits __builtin_avr_lkbits
|
||||||
|
#define ulkbits __builtin_avr_ulkbits
|
||||||
|
#define llrbits __builtin_avr_llrbits /* GCC Extension */
|
||||||
|
#define ullrbits __builtin_avr_ullrbits /* GCC Extension */
|
||||||
|
#define llkbits __builtin_avr_llkbits /* GCC Extension */
|
||||||
|
#define ullkbits __builtin_avr_ullkbits /* GCC Extension */
|
||||||
|
|
||||||
|
#endif /* sizeof (int) == 2 */
|
||||||
|
|
||||||
|
|
||||||
|
/* 7.18a.6.7 Type-generic fixed-point functions. */
|
||||||
|
|
||||||
|
#define absfx __builtin_avr_absfx
|
||||||
|
#define roundfx __builtin_avr_roundfx
|
||||||
|
#define countlsfx __builtin_avr_countlsfx
|
||||||
|
|
||||||
#endif /* __SIZEOF_INT__ == 2 */
|
|
||||||
#endif /* _AVRGCC_STDFIX_H */
|
#endif /* _AVRGCC_STDFIX_H */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2013-02-08 Georg-Johann Lay <avr@gjlay.de>
|
||||||
|
|
||||||
|
PR target/54222
|
||||||
|
* gcc.target/avr/torture/builtins-4-roundfx.c: New test.
|
||||||
|
* gcc.target/avr/torture/builtins-5-countlsfx.c: New test.
|
||||||
|
|
||||||
2013-02-07 Jakub Jelinek <jakub@redhat.com>
|
2013-02-07 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR c++/56241
|
PR c++/56241
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* { dg-options "-std=gnu99" } */
|
||||||
|
/* { dg-do run } */
|
||||||
|
|
||||||
|
#include <stdfix.h>
|
||||||
|
|
||||||
|
extern void abort (void);
|
||||||
|
|
||||||
|
typedef short _Fract fx_hr_t;
|
||||||
|
typedef _Fract fx_r_t;
|
||||||
|
typedef long _Fract fx_lr_t;
|
||||||
|
typedef long long _Fract fx_llr_t;
|
||||||
|
|
||||||
|
typedef unsigned short _Fract fx_uhr_t;
|
||||||
|
typedef unsigned _Fract fx_ur_t;
|
||||||
|
typedef unsigned long _Fract fx_ulr_t;
|
||||||
|
typedef unsigned long long _Fract fx_ullr_t;
|
||||||
|
|
||||||
|
typedef short _Accum fx_hk_t;
|
||||||
|
typedef _Accum fx_k_t;
|
||||||
|
typedef long _Accum fx_lk_t;
|
||||||
|
typedef long long _Accum fx_llk_t;
|
||||||
|
|
||||||
|
typedef unsigned short _Accum fx_uhk_t;
|
||||||
|
typedef unsigned _Accum fx_uk_t;
|
||||||
|
typedef unsigned long _Accum fx_ulk_t;
|
||||||
|
typedef unsigned long long _Accum fx_ullk_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned char int_uhr_t;
|
||||||
|
typedef unsigned int int_ur_t;
|
||||||
|
typedef unsigned long int_ulr_t;
|
||||||
|
typedef unsigned long long int_ullr_t;
|
||||||
|
|
||||||
|
typedef unsigned int int_uhk_t;
|
||||||
|
typedef unsigned long int_uk_t;
|
||||||
|
typedef unsigned long long int_ulk_t;
|
||||||
|
typedef unsigned long long int_ullk_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFTEST1(T,FX) \
|
||||||
|
T test1_##FX (T x, int rp) \
|
||||||
|
{ \
|
||||||
|
return round##FX (x, rp); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
unsigned T test1_u##FX (unsigned T x, int rp) \
|
||||||
|
{ \
|
||||||
|
return roundu##FX (x, rp); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFTEST1 (short fract, hr)
|
||||||
|
DEFTEST1 (fract, r)
|
||||||
|
DEFTEST1 (long fract, lr)
|
||||||
|
DEFTEST1 (long long fract, llr)
|
||||||
|
|
||||||
|
DEFTEST1 (short accum, hk)
|
||||||
|
DEFTEST1 (accum, k)
|
||||||
|
|
||||||
|
DEFTEST1 (long accum, lk)
|
||||||
|
DEFTEST1 (long long accum, llk)
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST2(FX, RP, VAL, ROUND) \
|
||||||
|
{ \
|
||||||
|
if (round##FX (FX##bits (VAL), RP) != FX##bits (ROUND)) \
|
||||||
|
abort(); \
|
||||||
|
fx_##FX##_t (*f)(fx_##FX##_t,int) = round##FX; \
|
||||||
|
asm ("" : "+r" (f)); \
|
||||||
|
if (f (FX##bits (VAL), RP) != FX##bits (ROUND)) \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test2hr (void)
|
||||||
|
{
|
||||||
|
TEST2 (hr, 1, 0x7f, 0x40);
|
||||||
|
TEST2 (hr, 2, 0x7f, 0b1100000);
|
||||||
|
TEST2 (hr, 3, 0x7f, 0b1110000);
|
||||||
|
TEST2 (hr, 4, 0x7f, 0b1111000);
|
||||||
|
|
||||||
|
TEST2 (uhr, 1, 0x7f, 0x80);
|
||||||
|
TEST2 (uhr, 2, 0x7f, 0x80);
|
||||||
|
TEST2 (uhr, 3, 0x7f, 0x80);
|
||||||
|
TEST2 (uhr, 4, 0x7f, 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test2k (void)
|
||||||
|
{
|
||||||
|
TEST2 (k, 1, 0x7fffffff, 0x7fff8000 | 0b100000000000000);
|
||||||
|
TEST2 (k, 2, 0x7fffffff, 0x7fff8000 | 0b110000000000000);
|
||||||
|
TEST2 (k, 3, 0x7fffffff, 0x7fff8000 | 0b111000000000000);
|
||||||
|
TEST2 (k, 4, 0x7fffffff, 0x7fff8000 | 0b111100000000000);
|
||||||
|
|
||||||
|
TEST2 (uk, 1, 0x7fffffff, 1ul << 31);
|
||||||
|
TEST2 (uk, 2, 0x7fffffff, 1ul << 31);
|
||||||
|
TEST2 (uk, 3, 0x7fffffff, 1ul << 31);
|
||||||
|
TEST2 (uk, 4, 0x7fffffff, 1ul << 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFTEST3(FX, FBIT) \
|
||||||
|
void test3##FX (void) \
|
||||||
|
{ \
|
||||||
|
TEST2 (FX, FBIT-1, 0b01100, 0b01100); \
|
||||||
|
TEST2 (FX, FBIT-2, 0b01100, 0b01100); \
|
||||||
|
TEST2 (FX, FBIT-3, 0b01100, 0b10000); \
|
||||||
|
TEST2 (FX, FBIT-4, 0b01100, 0b10000); \
|
||||||
|
TEST2 (FX, FBIT-5, 0b01100, 0); \
|
||||||
|
\
|
||||||
|
if (FX##bits ((int_##FX##_t) -1) > 0) \
|
||||||
|
return; \
|
||||||
|
\
|
||||||
|
TEST2 (FX, FBIT-1, -0b01100, -0b01100); \
|
||||||
|
TEST2 (FX, FBIT-2, -0b01100, -0b01100); \
|
||||||
|
TEST2 (FX, FBIT-3, -0b01100, -0b01000); \
|
||||||
|
TEST2 (FX, FBIT-4, -0b01100, -0b10000); \
|
||||||
|
TEST2 (FX, FBIT-5, -0b01100, -0b00000); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFTEST3 (hr, SFRACT_FBIT)
|
||||||
|
DEFTEST3 (r, FRACT_FBIT)
|
||||||
|
DEFTEST3 (lr, LFRACT_FBIT)
|
||||||
|
|
||||||
|
DEFTEST3 (uhr, USFRACT_FBIT)
|
||||||
|
DEFTEST3 (ur, UFRACT_FBIT)
|
||||||
|
DEFTEST3 (ulr, ULFRACT_FBIT)
|
||||||
|
|
||||||
|
DEFTEST3 (hk, SACCUM_FBIT)
|
||||||
|
DEFTEST3 (k, ACCUM_FBIT)
|
||||||
|
DEFTEST3 (lk, LACCUM_FBIT)
|
||||||
|
DEFTEST3 (llk, LLACCUM_FBIT)
|
||||||
|
|
||||||
|
DEFTEST3 (uhk, USACCUM_FBIT)
|
||||||
|
DEFTEST3 (uk, UACCUM_FBIT)
|
||||||
|
DEFTEST3 (ulk, ULACCUM_FBIT)
|
||||||
|
DEFTEST3 (ullk, ULLACCUM_FBIT)
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
test2hr();
|
||||||
|
test2k();
|
||||||
|
|
||||||
|
test3hr();
|
||||||
|
test3r();
|
||||||
|
test3lr();
|
||||||
|
|
||||||
|
test3uhr();
|
||||||
|
test3ur();
|
||||||
|
test3ulr();
|
||||||
|
|
||||||
|
test3hk();
|
||||||
|
test3k();
|
||||||
|
test3lk();
|
||||||
|
test3llk();
|
||||||
|
|
||||||
|
test3uhk();
|
||||||
|
test3uk();
|
||||||
|
test3ulk();
|
||||||
|
test3ullk();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* { dg-options "-std=gnu99" } */
|
||||||
|
/* { dg-do run } */
|
||||||
|
|
||||||
|
#include <stdfix.h>
|
||||||
|
|
||||||
|
extern void abort (void);
|
||||||
|
|
||||||
|
#define DEFTEST1(T,FX) \
|
||||||
|
int test1_##FX (T x) \
|
||||||
|
{ \
|
||||||
|
return countls##FX (x); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
int test1_u##FX (unsigned T x) \
|
||||||
|
{ \
|
||||||
|
return countlsu##FX (x); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFTEST1 (short fract, hr)
|
||||||
|
DEFTEST1 (fract, r)
|
||||||
|
DEFTEST1 (long fract, lr)
|
||||||
|
DEFTEST1 (long long fract, llr)
|
||||||
|
|
||||||
|
DEFTEST1 (short accum, hk)
|
||||||
|
DEFTEST1 (accum, k)
|
||||||
|
DEFTEST1 (long accum, lk)
|
||||||
|
DEFTEST1 (long long accum, llk)
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST2P(FX, VAL, DD) \
|
||||||
|
{ \
|
||||||
|
if (countls##FX (FX##bits (VAL)) != 8 * sizeof (0##FX) - DD) \
|
||||||
|
abort(); \
|
||||||
|
\
|
||||||
|
if (countlsu##FX (u##FX##bits (VAL)) != 8 * sizeof (0u##FX) + 1 - DD) \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST2M(FX, VAL, DD) \
|
||||||
|
{ \
|
||||||
|
if (countls##FX (FX##bits (VAL)) != 8 * sizeof (0##FX) - (DD)) \
|
||||||
|
abort(); \
|
||||||
|
\
|
||||||
|
if (countlsu##FX (u##FX##bits (VAL)) != 0) \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST2PX(VAL, DD) \
|
||||||
|
TEST2P (hr, VAL, DD); \
|
||||||
|
TEST2P (r, VAL, DD); \
|
||||||
|
TEST2P (lr, VAL, DD); \
|
||||||
|
\
|
||||||
|
TEST2P (hk, VAL, DD); \
|
||||||
|
TEST2P (k, VAL, DD); \
|
||||||
|
TEST2P (lk, VAL, DD); \
|
||||||
|
TEST2P (llk, VAL, DD)
|
||||||
|
|
||||||
|
#define TEST2MX(VAL, DD) \
|
||||||
|
TEST2M (hr, VAL, DD); \
|
||||||
|
TEST2M (r, VAL, DD); \
|
||||||
|
TEST2M (lr, VAL, DD); \
|
||||||
|
\
|
||||||
|
TEST2M (hk, VAL, DD); \
|
||||||
|
TEST2M (k, VAL, DD); \
|
||||||
|
TEST2M (lk, VAL, DD); \
|
||||||
|
TEST2M (llk, VAL, DD)
|
||||||
|
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
TEST2PX (1, 2);
|
||||||
|
TEST2PX (2, 3);
|
||||||
|
TEST2PX (3, 3);
|
||||||
|
|
||||||
|
TEST2MX (-1, 1);
|
||||||
|
TEST2MX (-2, 2);
|
||||||
|
TEST2MX (-3, 3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,17 @@
|
||||||
|
2013-02-08 Georg-Johann Lay <avr@gjlay.de>
|
||||||
|
|
||||||
|
PR target/54222
|
||||||
|
* config/avr/lib2funcs.c: New C sources for modules for libgcc.a.
|
||||||
|
* config/avr/lib2-object.mk: New iterator to build objects from it.
|
||||||
|
* config/avr/t-avr: Iterate lib2-object.mk to build objects from
|
||||||
|
lib2funcs.c.
|
||||||
|
(LIB2FUNCS_EXCLUDE): Add _clrsbdi2.
|
||||||
|
(LIB1ASMFUNCS): Add: _ssabs_1, _mask1, _ret, _roundqq3, _rounduqq3,
|
||||||
|
_round_s2, _round_u2, _round_2_const, _addmask_2, _round_s4,
|
||||||
|
_round_u4, _round_4_const, _addmask_4, _round_x8, _rounddq3
|
||||||
|
_roundudq3, _roundda3 _rounduda3, _roundta3 _rounduta3.
|
||||||
|
* config/avr/lib1funcs-fixed.S: Implement them.
|
||||||
|
|
||||||
2013-02-04 Richard Sandiford <rdsandiford@googlemail.com>
|
2013-02-04 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
Update copyright years.
|
Update copyright years.
|
||||||
|
|
|
||||||
|
|
@ -957,6 +957,28 @@ ENDF __udivusa3
|
||||||
#undef r_divHH
|
#undef r_divHH
|
||||||
#undef r_cnt
|
#undef r_cnt
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Saturation, 1 Byte
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; First Argument and Return Register
|
||||||
|
#define A0 24
|
||||||
|
|
||||||
|
#if defined (L_ssabs_1)
|
||||||
|
DEFUN __ssabs_1
|
||||||
|
sbrs A0, 7
|
||||||
|
ret
|
||||||
|
neg A0
|
||||||
|
sbrc A0,7
|
||||||
|
dec A0
|
||||||
|
ret
|
||||||
|
ENDF __ssabs_1
|
||||||
|
#endif /* L_ssabs_1 */
|
||||||
|
|
||||||
|
#undef A0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Saturation, 2 Bytes
|
;; Saturation, 2 Bytes
|
||||||
|
|
@ -1176,3 +1198,509 @@ ENDF __sssub_8
|
||||||
#undef B5
|
#undef B5
|
||||||
#undef B6
|
#undef B6
|
||||||
#undef B7
|
#undef B7
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Rounding Helpers
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
#ifdef L_mask1
|
||||||
|
|
||||||
|
#define AA 24
|
||||||
|
#define CC 25
|
||||||
|
|
||||||
|
;; R25 = 1 << (R24 & 7)
|
||||||
|
;; CC = 1 << (AA & 7)
|
||||||
|
;; Clobbers: None
|
||||||
|
DEFUN __mask1
|
||||||
|
;; CC = 2 ^ AA.1
|
||||||
|
ldi CC, 1 << 2
|
||||||
|
sbrs AA, 1
|
||||||
|
ldi CC, 1 << 0
|
||||||
|
;; CC *= 2 ^ AA.0
|
||||||
|
sbrc AA, 0
|
||||||
|
lsl CC
|
||||||
|
;; CC *= 2 ^ AA.2
|
||||||
|
sbrc AA, 2
|
||||||
|
swap CC
|
||||||
|
ret
|
||||||
|
ENDF __mask1
|
||||||
|
|
||||||
|
#undef AA
|
||||||
|
#undef CC
|
||||||
|
#endif /* L_mask1 */
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; The rounding point. Any bits smaller than
|
||||||
|
;; 2^{-RP} will be cleared.
|
||||||
|
#define RP R24
|
||||||
|
|
||||||
|
#define A0 22
|
||||||
|
#define A1 A0 + 1
|
||||||
|
|
||||||
|
#define C0 24
|
||||||
|
#define C1 C0 + 1
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Rounding, 1 Byte
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
#ifdef L_roundqq3
|
||||||
|
|
||||||
|
;; R24 = round (R22, R24)
|
||||||
|
;; Clobbers: R22, __tmp_reg__
|
||||||
|
DEFUN __roundqq3
|
||||||
|
mov __tmp_reg__, C1
|
||||||
|
subi RP, __QQ_FBIT__ - 1
|
||||||
|
neg RP
|
||||||
|
;; R25 = 1 << RP (Total offset is FBIT-1 - RP)
|
||||||
|
XCALL __mask1
|
||||||
|
mov C0, C1
|
||||||
|
;; Add-Saturate 2^{-RP-1}
|
||||||
|
add A0, C0
|
||||||
|
brvc 0f
|
||||||
|
ldi A0, 0x7f
|
||||||
|
0: ;; Mask out bits beyond RP
|
||||||
|
lsl C0
|
||||||
|
neg C0
|
||||||
|
and C0, A0
|
||||||
|
mov C1, __tmp_reg__
|
||||||
|
ret
|
||||||
|
ENDF __roundqq3
|
||||||
|
#endif /* L_roundqq3 */
|
||||||
|
|
||||||
|
#ifdef L_rounduqq3
|
||||||
|
|
||||||
|
;; R24 = round (R22, R24)
|
||||||
|
;; Clobbers: R22, __tmp_reg__
|
||||||
|
DEFUN __rounduqq3
|
||||||
|
mov __tmp_reg__, C1
|
||||||
|
subi RP, __UQQ_FBIT__ - 1
|
||||||
|
neg RP
|
||||||
|
;; R25 = 1 << RP (Total offset is FBIT-1 - RP)
|
||||||
|
XCALL __mask1
|
||||||
|
mov C0, C1
|
||||||
|
;; Add-Saturate 2^{-RP-1}
|
||||||
|
add A0, C0
|
||||||
|
brcc 0f
|
||||||
|
ldi A0, 0xff
|
||||||
|
0: ;; Mask out bits beyond RP
|
||||||
|
lsl C0
|
||||||
|
neg C0
|
||||||
|
and C0, A0
|
||||||
|
mov C1, __tmp_reg__
|
||||||
|
ret
|
||||||
|
ENDF __rounduqq3
|
||||||
|
#endif /* L_rounduqq3 */
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Rounding, 2 Bytes
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
#ifdef L_addmask_2
|
||||||
|
|
||||||
|
;; [ R25:R24 = 1 << (R24 & 15)
|
||||||
|
;; R23:R22 += 1 << (R24 & 15) ]
|
||||||
|
;; SREG is set according to the addition
|
||||||
|
DEFUN __addmask_2
|
||||||
|
;; R25 = 1 << (R24 & 7)
|
||||||
|
XCALL __mask1
|
||||||
|
cpi RP, 1 << 3
|
||||||
|
sbc C0, C0
|
||||||
|
;; Swap C0 and C1 if RP.3 was set
|
||||||
|
and C0, C1
|
||||||
|
eor C1, C0
|
||||||
|
;; Finally, add the power-of-two: A[] += C[]
|
||||||
|
add A0, C0
|
||||||
|
adc A1, C1
|
||||||
|
ret
|
||||||
|
ENDF __addmask_2
|
||||||
|
#endif /* L_addmask_2 */
|
||||||
|
|
||||||
|
#ifdef L_round_s2
|
||||||
|
|
||||||
|
;; R25:R24 = round (R23:R22, R24)
|
||||||
|
;; Clobbers: R23, R22
|
||||||
|
DEFUN __roundhq3
|
||||||
|
subi RP, __HQ_FBIT__ - __HA_FBIT__
|
||||||
|
ENDF __roundhq3
|
||||||
|
DEFUN __roundha3
|
||||||
|
subi RP, __HA_FBIT__ - 1
|
||||||
|
neg RP
|
||||||
|
;; [ R25:R24 = 1 << (FBIT-1 - RP)
|
||||||
|
;; R23:R22 += 1 << (FBIT-1 - RP) ]
|
||||||
|
XCALL __addmask_2
|
||||||
|
XJMP __round_s2_const
|
||||||
|
ENDF __roundha3
|
||||||
|
|
||||||
|
#endif /* L_round_s2 */
|
||||||
|
|
||||||
|
#ifdef L_round_u2
|
||||||
|
|
||||||
|
;; R25:R24 = round (R23:R22, R24)
|
||||||
|
;; Clobbers: R23, R22
|
||||||
|
DEFUN __rounduhq3
|
||||||
|
subi RP, __UHQ_FBIT__ - __UHA_FBIT__
|
||||||
|
ENDF __rounduhq3
|
||||||
|
DEFUN __rounduha3
|
||||||
|
subi RP, __UHA_FBIT__ - 1
|
||||||
|
neg RP
|
||||||
|
;; [ R25:R24 = 1 << (FBIT-1 - RP)
|
||||||
|
;; R23:R22 += 1 << (FBIT-1 - RP) ]
|
||||||
|
XCALL __addmask_2
|
||||||
|
XJMP __round_u2_const
|
||||||
|
ENDF __rounduha3
|
||||||
|
|
||||||
|
#endif /* L_round_u2 */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef L_round_2_const
|
||||||
|
|
||||||
|
;; Helpers for 2 byte wide rounding
|
||||||
|
|
||||||
|
DEFUN __round_s2_const
|
||||||
|
brvc 2f
|
||||||
|
ldi A1, 0x7f
|
||||||
|
rjmp 1f
|
||||||
|
;; FALLTHRU (Barrier)
|
||||||
|
ENDF __round_s2_const
|
||||||
|
|
||||||
|
DEFUN __round_u2_const
|
||||||
|
brcc 2f
|
||||||
|
ldi A1, 0xff
|
||||||
|
1:
|
||||||
|
ldi A0, 0xff
|
||||||
|
2:
|
||||||
|
;; Saturation is performed now.
|
||||||
|
;; Currently, we have C[] = 2^{-RP-1}
|
||||||
|
;; C[] = 2^{-RP}
|
||||||
|
lsl C0
|
||||||
|
rol C1
|
||||||
|
;;
|
||||||
|
NEG2 C0
|
||||||
|
;; Clear the bits beyond the rounding point.
|
||||||
|
and C0, A0
|
||||||
|
and C1, A1
|
||||||
|
ret
|
||||||
|
ENDF __round_u2_const
|
||||||
|
|
||||||
|
#endif /* L_round_2_const */
|
||||||
|
|
||||||
|
#undef A0
|
||||||
|
#undef A1
|
||||||
|
#undef C0
|
||||||
|
#undef C1
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Rounding, 4 Bytes
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
#define A0 18
|
||||||
|
#define A1 A0 + 1
|
||||||
|
#define A2 A0 + 2
|
||||||
|
#define A3 A0 + 3
|
||||||
|
|
||||||
|
#define C0 22
|
||||||
|
#define C1 C0 + 1
|
||||||
|
#define C2 C0 + 2
|
||||||
|
#define C3 C0 + 3
|
||||||
|
|
||||||
|
#ifdef L_addmask_4
|
||||||
|
|
||||||
|
;; [ R25:R22 = 1 << (R24 & 31)
|
||||||
|
;; R21:R18 += 1 << (R24 & 31) ]
|
||||||
|
;; SREG is set according to the addition
|
||||||
|
DEFUN __addmask_4
|
||||||
|
;; R25 = 1 << (R24 & 7)
|
||||||
|
XCALL __mask1
|
||||||
|
cpi RP, 1 << 4
|
||||||
|
sbc C0, C0
|
||||||
|
sbc C1, C1
|
||||||
|
;; Swap C2 with C3 if RP.3 is not set
|
||||||
|
cpi RP, 1 << 3
|
||||||
|
sbc C2, C2
|
||||||
|
and C2, C3
|
||||||
|
eor C3, C2
|
||||||
|
;; Swap C3:C2 with C1:C0 if RP.4 is not set
|
||||||
|
and C0, C2 $ eor C2, C0
|
||||||
|
and C1, C3 $ eor C3, C1
|
||||||
|
;; Finally, add the power-of-two: A[] += C[]
|
||||||
|
add A0, C0
|
||||||
|
adc A1, C1
|
||||||
|
adc A2, C2
|
||||||
|
adc A3, C3
|
||||||
|
ret
|
||||||
|
ENDF __addmask_4
|
||||||
|
#endif /* L_addmask_4 */
|
||||||
|
|
||||||
|
#ifdef L_round_s4
|
||||||
|
|
||||||
|
;; R25:R22 = round (R21:R18, R24)
|
||||||
|
;; Clobbers: R18...R21
|
||||||
|
DEFUN __roundsq3
|
||||||
|
subi RP, __SQ_FBIT__ - __SA_FBIT__
|
||||||
|
ENDF __roundsq3
|
||||||
|
DEFUN __roundsa3
|
||||||
|
subi RP, __SA_FBIT__ - 1
|
||||||
|
neg RP
|
||||||
|
;; [ R25:R22 = 1 << (FBIT-1 - RP)
|
||||||
|
;; R21:R18 += 1 << (FBIT-1 - RP) ]
|
||||||
|
XCALL __addmask_4
|
||||||
|
XJMP __round_s4_const
|
||||||
|
ENDF __roundsa3
|
||||||
|
|
||||||
|
#endif /* L_round_s4 */
|
||||||
|
|
||||||
|
#ifdef L_round_u4
|
||||||
|
|
||||||
|
;; R25:R22 = round (R21:R18, R24)
|
||||||
|
;; Clobbers: R18...R21
|
||||||
|
DEFUN __roundusq3
|
||||||
|
subi RP, __USQ_FBIT__ - __USA_FBIT__
|
||||||
|
ENDF __roundusq3
|
||||||
|
DEFUN __roundusa3
|
||||||
|
subi RP, __USA_FBIT__ - 1
|
||||||
|
neg RP
|
||||||
|
;; [ R25:R22 = 1 << (FBIT-1 - RP)
|
||||||
|
;; R21:R18 += 1 << (FBIT-1 - RP) ]
|
||||||
|
XCALL __addmask_4
|
||||||
|
XJMP __round_u4_const
|
||||||
|
ENDF __roundusa3
|
||||||
|
|
||||||
|
#endif /* L_round_u4 */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef L_round_4_const
|
||||||
|
|
||||||
|
;; Helpers for 4 byte wide rounding
|
||||||
|
|
||||||
|
DEFUN __round_s4_const
|
||||||
|
brvc 2f
|
||||||
|
ldi A3, 0x7f
|
||||||
|
rjmp 1f
|
||||||
|
;; FALLTHRU (Barrier)
|
||||||
|
ENDF __round_s4_const
|
||||||
|
|
||||||
|
DEFUN __round_u4_const
|
||||||
|
brcc 2f
|
||||||
|
ldi A3, 0xff
|
||||||
|
1:
|
||||||
|
ldi A2, 0xff
|
||||||
|
ldi A1, 0xff
|
||||||
|
ldi A0, 0xff
|
||||||
|
2:
|
||||||
|
;; Saturation is performed now.
|
||||||
|
;; Currently, we have C[] = 2^{-RP-1}
|
||||||
|
;; C[] = 2^{-RP}
|
||||||
|
lsl C0
|
||||||
|
rol C1
|
||||||
|
rol C2
|
||||||
|
rol C3
|
||||||
|
XCALL __negsi2
|
||||||
|
;; Clear the bits beyond the rounding point.
|
||||||
|
and C0, A0
|
||||||
|
and C1, A1
|
||||||
|
and C2, A2
|
||||||
|
and C3, A3
|
||||||
|
ret
|
||||||
|
ENDF __round_u4_const
|
||||||
|
|
||||||
|
#endif /* L_round_4_const */
|
||||||
|
|
||||||
|
#undef A0
|
||||||
|
#undef A1
|
||||||
|
#undef A2
|
||||||
|
#undef A3
|
||||||
|
#undef C0
|
||||||
|
#undef C1
|
||||||
|
#undef C2
|
||||||
|
#undef C3
|
||||||
|
|
||||||
|
#undef RP
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Rounding, 8 Bytes
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
#define RP 16
|
||||||
|
#define FBITm1 31
|
||||||
|
|
||||||
|
#define C0 18
|
||||||
|
#define C1 C0 + 1
|
||||||
|
#define C2 C0 + 2
|
||||||
|
#define C3 C0 + 3
|
||||||
|
#define C4 C0 + 4
|
||||||
|
#define C5 C0 + 5
|
||||||
|
#define C6 C0 + 6
|
||||||
|
#define C7 C0 + 7
|
||||||
|
|
||||||
|
#define A0 16
|
||||||
|
#define A1 17
|
||||||
|
#define A2 26
|
||||||
|
#define A3 27
|
||||||
|
#define A4 28
|
||||||
|
#define A5 29
|
||||||
|
#define A6 30
|
||||||
|
#define A7 31
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef L_rounddq3
|
||||||
|
;; R25:R18 = round (R25:R18, R16)
|
||||||
|
;; Clobbers: ABI
|
||||||
|
DEFUN __rounddq3
|
||||||
|
ldi FBITm1, __DQ_FBIT__ - 1
|
||||||
|
clt
|
||||||
|
XJMP __round_x8
|
||||||
|
ENDF __rounddq3
|
||||||
|
#endif /* L_rounddq3 */
|
||||||
|
|
||||||
|
#ifdef L_roundudq3
|
||||||
|
;; R25:R18 = round (R25:R18, R16)
|
||||||
|
;; Clobbers: ABI
|
||||||
|
DEFUN __roundudq3
|
||||||
|
ldi FBITm1, __UDQ_FBIT__ - 1
|
||||||
|
set
|
||||||
|
XJMP __round_x8
|
||||||
|
ENDF __roundudq3
|
||||||
|
#endif /* L_roundudq3 */
|
||||||
|
|
||||||
|
#ifdef L_roundda3
|
||||||
|
;; R25:R18 = round (R25:R18, R16)
|
||||||
|
;; Clobbers: ABI
|
||||||
|
DEFUN __roundda3
|
||||||
|
ldi FBITm1, __DA_FBIT__ - 1
|
||||||
|
clt
|
||||||
|
XJMP __round_x8
|
||||||
|
ENDF __roundda3
|
||||||
|
#endif /* L_roundda3 */
|
||||||
|
|
||||||
|
#ifdef L_rounduda3
|
||||||
|
;; R25:R18 = round (R25:R18, R16)
|
||||||
|
;; Clobbers: ABI
|
||||||
|
DEFUN __rounduda3
|
||||||
|
ldi FBITm1, __UDA_FBIT__ - 1
|
||||||
|
set
|
||||||
|
XJMP __round_x8
|
||||||
|
ENDF __rounduda3
|
||||||
|
#endif /* L_rounduda3 */
|
||||||
|
|
||||||
|
#ifdef L_roundta3
|
||||||
|
;; R25:R18 = round (R25:R18, R16)
|
||||||
|
;; Clobbers: ABI
|
||||||
|
DEFUN __roundta3
|
||||||
|
ldi FBITm1, __TA_FBIT__ - 1
|
||||||
|
clt
|
||||||
|
XJMP __round_x8
|
||||||
|
ENDF __roundta3
|
||||||
|
#endif /* L_roundta3 */
|
||||||
|
|
||||||
|
#ifdef L_rounduta3
|
||||||
|
;; R25:R18 = round (R25:R18, R16)
|
||||||
|
;; Clobbers: ABI
|
||||||
|
DEFUN __rounduta3
|
||||||
|
ldi FBITm1, __UTA_FBIT__ - 1
|
||||||
|
set
|
||||||
|
XJMP __round_x8
|
||||||
|
ENDF __rounduta3
|
||||||
|
#endif /* L_rounduta3 */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef L_round_x8
|
||||||
|
DEFUN __round_x8
|
||||||
|
push r16
|
||||||
|
push r17
|
||||||
|
push r28
|
||||||
|
push r29
|
||||||
|
;; Compute log2 of addend from rounding point
|
||||||
|
sub RP, FBITm1
|
||||||
|
neg RP
|
||||||
|
;; Move input to work register A[]
|
||||||
|
push C0
|
||||||
|
mov A1, C1
|
||||||
|
wmov A2, C2
|
||||||
|
wmov A4, C4
|
||||||
|
wmov A6, C6
|
||||||
|
;; C[] = 1 << (FBIT-1 - RP)
|
||||||
|
XCALL __clr_8
|
||||||
|
inc C0
|
||||||
|
XCALL __ashldi3
|
||||||
|
pop A0
|
||||||
|
;; A[] += C[]
|
||||||
|
add A0, C0
|
||||||
|
adc A1, C1
|
||||||
|
adc A2, C2
|
||||||
|
adc A3, C3
|
||||||
|
adc A4, C4
|
||||||
|
adc A5, C5
|
||||||
|
adc A6, C6
|
||||||
|
adc A7, C7
|
||||||
|
brts 1f
|
||||||
|
;; Signed
|
||||||
|
brvc 3f
|
||||||
|
;; Signed overflow: A[] = 0x7f...
|
||||||
|
brvs 2f
|
||||||
|
1: ;; Unsigned
|
||||||
|
brcc 3f
|
||||||
|
;; Unsigned overflow: A[] = 0xff...
|
||||||
|
2: ldi A7, 0xff
|
||||||
|
ldi A6, 0xff
|
||||||
|
wmov A0, A6
|
||||||
|
wmov A2, A6
|
||||||
|
wmov A4, A6
|
||||||
|
bld A7, 7
|
||||||
|
3:
|
||||||
|
;; C[] = -C[] - C[]
|
||||||
|
push A0
|
||||||
|
ldi r16, 1
|
||||||
|
XCALL __ashldi3
|
||||||
|
pop A0
|
||||||
|
XCALL __negdi2
|
||||||
|
;; Clear the bits beyond the rounding point.
|
||||||
|
and C0, A0
|
||||||
|
and C1, A1
|
||||||
|
and C2, A2
|
||||||
|
and C3, A3
|
||||||
|
and C4, A4
|
||||||
|
and C5, A5
|
||||||
|
and C6, A6
|
||||||
|
and C7, A7
|
||||||
|
;; Epilogue
|
||||||
|
pop r29
|
||||||
|
pop r28
|
||||||
|
pop r17
|
||||||
|
pop r16
|
||||||
|
ret
|
||||||
|
ENDF __round_x8
|
||||||
|
|
||||||
|
#endif /* L_round_x8 */
|
||||||
|
|
||||||
|
#undef A0
|
||||||
|
#undef A1
|
||||||
|
#undef A2
|
||||||
|
#undef A3
|
||||||
|
#undef A4
|
||||||
|
#undef A5
|
||||||
|
#undef A6
|
||||||
|
#undef A7
|
||||||
|
|
||||||
|
#undef C0
|
||||||
|
#undef C1
|
||||||
|
#undef C2
|
||||||
|
#undef C3
|
||||||
|
#undef C4
|
||||||
|
#undef C5
|
||||||
|
#undef C6
|
||||||
|
#undef C7
|
||||||
|
|
||||||
|
#undef RP
|
||||||
|
#undef FBITm1
|
||||||
|
|
||||||
|
|
||||||
|
;; Supply implementations / symbols for the bit-banging functions
|
||||||
|
;; __builtin_avr_bitsfx and __builtin_avr_fxbits
|
||||||
|
#ifdef L_ret
|
||||||
|
DEFUN __ret
|
||||||
|
ret
|
||||||
|
ENDF __ret
|
||||||
|
#endif /* L_ret */
|
||||||
|
|
|
||||||
|
|
@ -1684,12 +1684,12 @@ DEFUN __divdi3_moddi3
|
||||||
|
|
||||||
ENDF __divdi3_moddi3
|
ENDF __divdi3_moddi3
|
||||||
|
|
||||||
|
#endif /* L_divdi3 */
|
||||||
|
|
||||||
#undef R_cnt
|
#undef R_cnt
|
||||||
#undef SS
|
#undef SS
|
||||||
#undef NN
|
#undef NN
|
||||||
|
|
||||||
#endif /* L_divdi3 */
|
|
||||||
|
|
||||||
.section .text.libgcc, "ax", @progbits
|
.section .text.libgcc, "ax", @progbits
|
||||||
|
|
||||||
#define TT __tmp_reg__
|
#define TT __tmp_reg__
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# This file is included several times in a row, once for each element of
|
||||||
|
# $(iter-items). On each inclusion, we advance $o to the next element.
|
||||||
|
# $(iter-labels) and $(iter-flags) are also advanced.
|
||||||
|
# This works similar to $(srcdir)/siditi-object.mk.
|
||||||
|
|
||||||
|
o := $(firstword $(iter-items))
|
||||||
|
iter-items := $(filter-out $o,$(iter-items))
|
||||||
|
|
||||||
|
$o-label := $(firstword $(iter-labels))
|
||||||
|
iter-labels := $(wordlist 2,$(words $(iter-labels)),$(iter-labels))
|
||||||
|
|
||||||
|
$o-flag := $(firstword $(iter-flags))
|
||||||
|
iter-flags := $(wordlist 2,$(words $(iter-flags)),$(iter-flags))
|
||||||
|
|
||||||
|
$o$(objext): %$(objext): $(srcdir)/config/avr/lib2funcs.c
|
||||||
|
$(gcc_compile) -DL_$($*-label) -DL_LABEL=$($*-label) $($*-flag) \
|
||||||
|
-c $< $(vis_hide)
|
||||||
|
|
||||||
|
ifeq ($(enable_shared),yes)
|
||||||
|
$(o)_s$(objext): %_s$(objext): $(srcdir)/config/avr/lib2funcs.c
|
||||||
|
$(gcc_s_compile) -DL_$($*-label) -DL_LABEL=$($*-label) $($*-flag) \
|
||||||
|
-c $<
|
||||||
|
endif
|
||||||
|
|
@ -0,0 +1,226 @@
|
||||||
|
/* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 3, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
/* This file supplies implementations for some AVR-specific builtin
|
||||||
|
functions so that code like the following works as expected:
|
||||||
|
|
||||||
|
int (*f (void))(_Fract)
|
||||||
|
{
|
||||||
|
return __builtin_avr_countlsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
In this specific case, the generated code is:
|
||||||
|
|
||||||
|
f:
|
||||||
|
ldi r24,lo8(gs(__countlsHI))
|
||||||
|
ldi r25,hi8(gs(__countlsHI))
|
||||||
|
ret
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Map fixed-point suffix to the corresponding fixed-point type. */
|
||||||
|
|
||||||
|
typedef short _Fract fx_hr_t;
|
||||||
|
typedef _Fract fx_r_t;
|
||||||
|
typedef long _Fract fx_lr_t;
|
||||||
|
typedef long long _Fract fx_llr_t;
|
||||||
|
|
||||||
|
typedef unsigned short _Fract fx_uhr_t;
|
||||||
|
typedef unsigned _Fract fx_ur_t;
|
||||||
|
typedef unsigned long _Fract fx_ulr_t;
|
||||||
|
typedef unsigned long long _Fract fx_ullr_t;
|
||||||
|
|
||||||
|
typedef short _Accum fx_hk_t;
|
||||||
|
typedef _Accum fx_k_t;
|
||||||
|
typedef long _Accum fx_lk_t;
|
||||||
|
typedef long long _Accum fx_llk_t;
|
||||||
|
|
||||||
|
typedef unsigned short _Accum fx_uhk_t;
|
||||||
|
typedef unsigned _Accum fx_uk_t;
|
||||||
|
typedef unsigned long _Accum fx_ulk_t;
|
||||||
|
typedef unsigned long long _Accum fx_ullk_t;
|
||||||
|
|
||||||
|
/* Map fixed-point suffix to the corresponding natural integer type. */
|
||||||
|
|
||||||
|
typedef char int_hr_t;
|
||||||
|
typedef int int_r_t;
|
||||||
|
typedef long int_lr_t;
|
||||||
|
typedef long long int_llr_t;
|
||||||
|
|
||||||
|
typedef unsigned char int_uhr_t;
|
||||||
|
typedef unsigned int int_ur_t;
|
||||||
|
typedef unsigned long int_ulr_t;
|
||||||
|
typedef unsigned long long int_ullr_t;
|
||||||
|
|
||||||
|
typedef int int_hk_t;
|
||||||
|
typedef long int_k_t;
|
||||||
|
typedef long long int_lk_t;
|
||||||
|
typedef long long int_llk_t;
|
||||||
|
|
||||||
|
typedef unsigned int int_uhk_t;
|
||||||
|
typedef unsigned long int_uk_t;
|
||||||
|
typedef unsigned long long int_ulk_t;
|
||||||
|
typedef unsigned long long int_ullk_t;
|
||||||
|
|
||||||
|
/* Map mode to the corresponding integer type. */
|
||||||
|
|
||||||
|
typedef char int_qi_t;
|
||||||
|
typedef int int_hi_t;
|
||||||
|
typedef long int_si_t;
|
||||||
|
typedef long long int_di_t;
|
||||||
|
|
||||||
|
typedef unsigned char uint_qi_t;
|
||||||
|
typedef unsigned int uint_hi_t;
|
||||||
|
typedef unsigned long uint_si_t;
|
||||||
|
typedef unsigned long long uint_di_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
/* Supply implementations / symbols for __builtin_roundFX ASM_NAME. */
|
||||||
|
|
||||||
|
#ifdef L_round
|
||||||
|
|
||||||
|
#define ROUND1(FX) \
|
||||||
|
ROUND2 (FX)
|
||||||
|
|
||||||
|
#define ROUND2(FX) \
|
||||||
|
extern fx_## FX ##_t __round## FX (fx_## FX ##_t x, int rpoint); \
|
||||||
|
\
|
||||||
|
fx_## FX ##_t \
|
||||||
|
__round## FX (fx_## FX ##_t x, int rpoint) \
|
||||||
|
{ \
|
||||||
|
return __builtin_avr_round ##FX (x, rpoint); \
|
||||||
|
}
|
||||||
|
|
||||||
|
ROUND1(L_LABEL)
|
||||||
|
|
||||||
|
#endif /* L_round */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
|
||||||
|
/* Implement some count-leading-redundant-sign-bits to be used with
|
||||||
|
coundlsFX implementation. */
|
||||||
|
|
||||||
|
#ifdef L__clrsbqi
|
||||||
|
extern int __clrsbqi2 (char x);
|
||||||
|
|
||||||
|
int
|
||||||
|
__clrsbqi2 (char x)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (x < 0)
|
||||||
|
x = ~x;
|
||||||
|
|
||||||
|
if (x == 0)
|
||||||
|
return 8 * sizeof (x) -1;
|
||||||
|
|
||||||
|
ret = __builtin_clz (x << 8);
|
||||||
|
return ret - 1;
|
||||||
|
}
|
||||||
|
#endif /* L__clrsbqi */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef L__clrsbdi
|
||||||
|
extern int __clrsbdi2 (long long x);
|
||||||
|
|
||||||
|
int
|
||||||
|
__clrsbdi2 (long long x)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (x < 0LL)
|
||||||
|
x = ~x;
|
||||||
|
|
||||||
|
if (x == 0LL)
|
||||||
|
return 8 * sizeof (x) -1;
|
||||||
|
|
||||||
|
ret = __builtin_clzll ((unsigned long long) x);
|
||||||
|
return ret - 1;
|
||||||
|
}
|
||||||
|
#endif /* L__clrsbdi */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
|
||||||
|
/* Supply implementations / symbols for __builtin_avr_countlsFX. */
|
||||||
|
|
||||||
|
/* Signed */
|
||||||
|
|
||||||
|
#ifdef L_countls
|
||||||
|
|
||||||
|
#define COUNTLS1(MM) \
|
||||||
|
COUNTLS2 (MM)
|
||||||
|
|
||||||
|
#define COUNTLS2(MM) \
|
||||||
|
extern int __countls## MM ##2 (int_## MM ##_t); \
|
||||||
|
extern int __clrsb## MM ##2 (int_## MM ##_t); \
|
||||||
|
\
|
||||||
|
int \
|
||||||
|
__countls## MM ##2 (int_## MM ##_t x) \
|
||||||
|
{ \
|
||||||
|
if (x == 0) \
|
||||||
|
return __INT8_MAX__; \
|
||||||
|
\
|
||||||
|
return __clrsb## MM ##2 (x); \
|
||||||
|
}
|
||||||
|
|
||||||
|
COUNTLS1(L_LABEL)
|
||||||
|
|
||||||
|
#endif /* L_countls */
|
||||||
|
|
||||||
|
/* Unsigned */
|
||||||
|
|
||||||
|
#ifdef L_countlsu
|
||||||
|
|
||||||
|
#define clz_qi2 __builtin_clz /* unused, avoid warning */
|
||||||
|
#define clz_hi2 __builtin_clz
|
||||||
|
#define clz_si2 __builtin_clzl
|
||||||
|
#define clz_di2 __builtin_clzll
|
||||||
|
|
||||||
|
#define COUNTLS1(MM) \
|
||||||
|
COUNTLS2 (MM)
|
||||||
|
|
||||||
|
#define COUNTLS2(MM) \
|
||||||
|
extern int __countlsu## MM ##2 (uint_## MM ##_t); \
|
||||||
|
\
|
||||||
|
int \
|
||||||
|
__countlsu## MM ##2 (uint_## MM ##_t x) \
|
||||||
|
{ \
|
||||||
|
if (x == 0) \
|
||||||
|
return __INT8_MAX__; \
|
||||||
|
\
|
||||||
|
if (sizeof (x) == 1) \
|
||||||
|
return clz_hi2 (x << 8); \
|
||||||
|
else \
|
||||||
|
return clz_## MM ##2 (x); \
|
||||||
|
}
|
||||||
|
|
||||||
|
COUNTLS1(L_LABEL)
|
||||||
|
|
||||||
|
#endif /* L_countlsu */
|
||||||
|
|
@ -75,13 +75,24 @@ LIB1ASMFUNCS += \
|
||||||
_divsa3 _udivusa3 \
|
_divsa3 _udivusa3 \
|
||||||
_clr_8 \
|
_clr_8 \
|
||||||
_ssneg_2 _ssneg_4 _ssneg_8 \
|
_ssneg_2 _ssneg_4 _ssneg_8 \
|
||||||
_ssabs_2 _ssabs_4 _ssabs_8 \
|
_ssabs_1 _ssabs_2 _ssabs_4 _ssabs_8 \
|
||||||
_ssadd_8 _sssub_8 \
|
_ssadd_8 _sssub_8 \
|
||||||
_usadd_8 _ussub_8
|
_usadd_8 _ussub_8 \
|
||||||
|
_mask1 _ret \
|
||||||
|
_roundqq3 _rounduqq3 \
|
||||||
|
_round_s2 _round_u2 _round_2_const _addmask_2 \
|
||||||
|
_round_s4 _round_u4 _round_4_const _addmask_4 \
|
||||||
|
_round_x8 \
|
||||||
|
_rounddq3 _roundudq3 \
|
||||||
|
_roundda3 _rounduda3 \
|
||||||
|
_roundta3 _rounduta3 \
|
||||||
|
|
||||||
|
|
||||||
LIB2FUNCS_EXCLUDE = \
|
LIB2FUNCS_EXCLUDE = \
|
||||||
_moddi3 _umoddi3 \
|
_moddi3 _umoddi3 \
|
||||||
_clz
|
_clz \
|
||||||
|
_clrsbdi2 \
|
||||||
|
|
||||||
|
|
||||||
# We do not have the DF type.
|
# We do not have the DF type.
|
||||||
# Most of the C functions in libgcc2 use almost all registers,
|
# Most of the C functions in libgcc2 use almost all registers,
|
||||||
|
|
@ -106,13 +117,84 @@ ifeq ($(enable_shared),yes)
|
||||||
libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16))
|
libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
###
|
||||||
# Filter out supported conversions from fixed-bit.c
|
|
||||||
# Also filter out TQ and UTQ.
|
|
||||||
|
|
||||||
conv_XY=$(conv)$(mode1)$(mode2)
|
conv_XY=$(conv)$(mode1)$(mode2)
|
||||||
func_X=$(func)$(mode)
|
func_X=$(func)$(mode)
|
||||||
|
|
||||||
|
# Compile C functions from lib2funcs.c and add them to libgcc.a.
|
||||||
|
#
|
||||||
|
# Some functions which are not performance.critical are more convenient
|
||||||
|
# to implement in C than in assembler. Most of them serve as implementation
|
||||||
|
# for AVR-specific builtins in the case where the address of a builtin
|
||||||
|
# function is taken or if there is no insn that implements the builtin.
|
||||||
|
#
|
||||||
|
# We don't use LIB2ADD because we want to iterate over the source for
|
||||||
|
# different modes, fixed-point suffixes, etc. See iter-labels and L_LABEL.
|
||||||
|
# iter-label will get one more underscore in order to avoid too short
|
||||||
|
# labels like -DLk and we use -DL_k instead.
|
||||||
|
|
||||||
|
# Build roundFX functions from lib2funcs.c
|
||||||
|
|
||||||
|
round_suffix := hr r lr uhr ur ulr \
|
||||||
|
hk k uhk uk
|
||||||
|
round_funcs := $(foreach func,_round,\
|
||||||
|
$(foreach mode,$(round_suffix),$(func_X)))
|
||||||
|
|
||||||
|
iter-items := $(round_funcs)
|
||||||
|
iter-labels := $(round_suffix)
|
||||||
|
iter-flags := $(patsubst %,-DL_round,$(iter-items))
|
||||||
|
|
||||||
|
include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
|
||||||
|
|
||||||
|
libgcc-objects += $(patsubst %,%$(objext),$(round_funcs))
|
||||||
|
|
||||||
|
# Build clrsbXX functions from lib2funcs.c
|
||||||
|
|
||||||
|
clrsb_modes := qi di
|
||||||
|
clrsb_funcs := $(foreach func,_clrsb,\
|
||||||
|
$(foreach mode,$(clrsb_modes),$(func_X)))
|
||||||
|
|
||||||
|
iter-items := $(clrsb_funcs)
|
||||||
|
iter-labels := $(clrsb_funcs)
|
||||||
|
iter-flags := $(patsubst %,-DL_clrsb,$(iter-items))
|
||||||
|
|
||||||
|
include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
|
||||||
|
|
||||||
|
libgcc-objects += $(patsubst %,%$(objext),$(clrsb_funcs))
|
||||||
|
|
||||||
|
# Build signed countlsFX functions from lib2funcs.c
|
||||||
|
|
||||||
|
countls_modes := qi hi si di
|
||||||
|
countls_funcs := $(foreach func,_countls,\
|
||||||
|
$(foreach mode,$(countls_modes),$(func_X)))
|
||||||
|
|
||||||
|
iter-items := $(countls_funcs)
|
||||||
|
iter-labels := $(countls_modes)
|
||||||
|
iter-flags := $(patsubst %,-DL_countls,$(iter-items))
|
||||||
|
|
||||||
|
include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
|
||||||
|
|
||||||
|
libgcc-objects += $(patsubst %,%$(objext),$(countls_funcs))
|
||||||
|
|
||||||
|
# Build unsigned countlsFX functions from lib2funcs.c
|
||||||
|
|
||||||
|
countlsu_modes := qi hi si di
|
||||||
|
countlsu_funcs := $(foreach func,_countlsu,\
|
||||||
|
$(foreach mode,$(countlsu_modes),$(func_X)))
|
||||||
|
|
||||||
|
iter-items := $(countlsu_funcs)
|
||||||
|
iter-labels := $(countlsu_modes)
|
||||||
|
iter-flags := $(patsubst %,-DL_countlsu,$(iter-items))
|
||||||
|
|
||||||
|
include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
|
||||||
|
|
||||||
|
libgcc-objects += $(patsubst %,%$(objext),$(countlsu_funcs))
|
||||||
|
|
||||||
|
|
||||||
|
# Filter out supported conversions from fixed-bit.c
|
||||||
|
# Also filter out TQ and UTQ.
|
||||||
|
|
||||||
# Conversions supported by the compiler
|
# Conversions supported by the compiler
|
||||||
|
|
||||||
convf_modes = QI UQI QQ UQQ \
|
convf_modes = QI UQI QQ UQQ \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue