diff options
| author | Yue Du <daviddu@us.ibm.com> | 2015-10-08 13:40:33 -0500 |
|---|---|---|
| committer | Joshua Hunsberger <jahunsbe@us.ibm.com> | 2017-10-23 15:56:18 -0500 |
| commit | a1268463544386716f41f17da0e7e35ee9375343 (patch) | |
| tree | 6ed1fd767335b79422c9605c1b5bc90e4af8330e /import/chips/p9/common/pmlib/ppc405lib | |
| parent | 286b12fc048eae37ea3ac04ac4aba8778d02d2a4 (diff) | |
| download | talos-hcode-a1268463544386716f41f17da0e7e35ee9375343.tar.gz talos-hcode-a1268463544386716f41f17da0e7e35ee9375343.zip | |
first draft of ppe_closed/cme & sgpe, and common/pmlib/
Change-Id: I08440fadfeff7e4777a776167d4fdcffe5fec82f
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/21058
Tested-by: Jenkins Server
Reviewed-by: Gregory S. Still <stillgs@us.ibm.com>
Diffstat (limited to 'import/chips/p9/common/pmlib/ppc405lib')
31 files changed, 5803 insertions, 0 deletions
diff --git a/import/chips/p9/common/pmlib/ppc405lib/Makefile b/import/chips/p9/common/pmlib/ppc405lib/Makefile new file mode 100644 index 00000000..d6165113 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/Makefile @@ -0,0 +1,56 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: import/chips/p9/common/pmlib/ppc405lib/Makefile $ +# +# OpenPOWER HCODE Project +# +# COPYRIGHT 2015,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +# This Makefile currently builds a single archive, 'libppc405.a', from +# various library source files. +# +# part of the complete application build. +# + +#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/ppc405lib +export SUB_OBJDIR = /ppc405lib + +include img_defs.mk +include libppc405files.mk + +OBJS := $(addprefix $(OBJDIR)/, $(LIBPPC405_OBJECTS)) + +libppc405.a: local + $(AR) crs $(OBJDIR)/libppc405.a $(OBJDIR)/*.o + +.PHONY: clean + +local: $(OBJS) + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +#include $(OBJS:.o=.d) +endif diff --git a/import/chips/p9/common/pmlib/ppc405lib/README.txt b/import/chips/p9/common/pmlib/ppc405lib/README.txt new file mode 100644 index 00000000..cc0076fc --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/README.txt @@ -0,0 +1,4 @@ +This directory contains all of the library code that only can run on the ppc405. +For most of the files, the only reason it can not run on the ppe42 is because of +it's dependence on SSX. Eventually, we would like to fix this so that most, if +not all files can be made common. diff --git a/import/chips/p9/common/pmlib/ppc405lib/assert.c b/import/chips/p9/common/pmlib/ppc405lib/assert.c new file mode 100644 index 00000000..5c7a587e --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/assert.c @@ -0,0 +1,72 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/assert.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: assert.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/assert.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file assert.c +/// \brief Implementation of library routines implied by <assert.h> + +#include "ssx.h" +#include "ssx_io.h" +#include "libssx.h" + +/// The __assert_fail() function is used to implement the assert() interface +/// of ISO POSIX (2003). The __assert_fail() function prints the given \a +/// file filename, \a line line number, \a function function name and a +/// message on the standard error stream then causes a kernel panic. If there +/// is no standard error stream then the error message is printed on the \a +/// ssxout (printk()) stream. +/// +/// If function is NULL, __assert_fail() omits information about the +/// function. The aguments \a assertion, \a file, and \a line must be +/// non-NULL. + +void +__assert_fail(const char* assertion, + const char* file, + unsigned line, + const char* function) +{ + FILE* stream; + + stream = stderr; + + if (stream == 0) + { + stream = ssxout; + } + + fprintf(stream, "%s:%u:%s%s Assertion '%s' failed\n", + file, line, + function ? function : "", function ? ":" : "", + assertion); + + SSX_PANIC(ASSERTION_FAILURE); +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/chip_config.h b/import/chips/p9/common/pmlib/ppc405lib/chip_config.h new file mode 100644 index 00000000..54e498fa --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/chip_config.h @@ -0,0 +1,109 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/chip_config.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __CHIP_CONFIG_H__ +#define __CHIP_CONFIG_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file chip_config.h +/// \brief Chip configuration data structures for OCC procedures + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +/// A bitmask defining a chip configuration +/// +/// Since we are using the conventional big-endian notation, any use of these +/// bitmasks requires that the data being tested is of this type - otherwise +/// the masks won't work. +/// +/// Layout: +/// +/// Bits 0:15 - Core chiplet 0..15 is configured +/// Bits 16:23 - MCS 0..7 is configured +/// Bits 24:31 - Centaur 0..7 is configured + +typedef uint64_t ChipConfig; +typedef uint16_t ChipConfigCores; +typedef uint8_t ChipConfigMcs; +typedef uint8_t ChipConfigCentaur; + + +/// Convert a ChipConfig into a mask suitable for use as the 32-bit chiplet +/// mask argument of a PORE wakeup program. +#if 0 +static inline uint32_t +pore_exe_mask(ChipConfig config) +{ + return (uint32_t)((config >> 32) & 0xffff0000); +} +#endif + +/// Left justify and mask core chiplet configuration into a uint32_t + +static inline uint32_t +left_justify_core_config(ChipConfig config) +{ + return (uint32_t)((config >> 32) & 0xffff0000); +} + +/// Left justify and mask MCS configuration into a uint32_t + +static inline uint32_t +left_justify_mcs_config(ChipConfig config) +{ + return (uint32_t)((config >> 16) & 0xff000000); +} + +/// Left justify and mask Centaur configuration into a uint32_t + +static inline uint32_t +left_justify_centaur_config(ChipConfig config) +{ + return (uint32_t)((config >> 8) & 0xff000000); +} + +#endif // __ASSEMBLER__ + + +#define CHIP_CONFIG_CORE_BASE 0 +#define CHIP_CONFIG_CORE(n) \ + ((0x8000000000000000ull >> CHIP_CONFIG_CORE_BASE) >> (n)) + +#define CHIP_CONFIG_MCS_BASE 16 +#define CHIP_CONFIG_MCS(n) \ + ((0x8000000000000000ull >> CHIP_CONFIG_MCS_BASE) >> (n)) + +#define CHIP_CONFIG_CENTAUR_BASE 24 +#define CHIP_CONFIG_CENTAUR(n) \ + ((0x8000000000000000ull >> CHIP_CONFIG_CENTAUR_BASE) >> (n)) + + +#endif /* __CHIP_CONFIG_H__ */ diff --git a/import/chips/p9/common/pmlib/ppc405lib/ctype.c b/import/chips/p9/common/pmlib/ppc405lib/ctype.c new file mode 100644 index 00000000..d570b49d --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ctype.c @@ -0,0 +1,42 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ctype.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: ctype.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ctype.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ctype.c +/// \brief Replacement for <ctype.h> functions +/// +/// This file contains entry point equivalents for the "ctype.h" macros. +/// These would only ever be used by assembler programs, therefore it's likely +/// that the object file will never be linked into an image. + +#define __CTYPE_C__ +#include "ctype.h" +#undef __CTYPE_C__ diff --git a/import/chips/p9/common/pmlib/ppc405lib/ctype.h b/import/chips/p9/common/pmlib/ppc405lib/ctype.h new file mode 100644 index 00000000..0e3fbece --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ctype.h @@ -0,0 +1,149 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ctype.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __CTYPE_H__ +#define __CTYPE_H__ + +// $Id: ctype.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ctype.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ctype.h +/// \brief Replacement for <ctype.h> +/// +/// The Gnu <ctype.h> requires some locale information to be defined. We +/// avoid this overhead and implement the simple functions, simply assuming +/// standard 8-bit ASCII. The standard requires that these be defined as entry +/// points, but may be defined as macros, therefore all macros defined by +/// ctype.h are also be replicated in \c ctype.c + +// The reference for which characters are included in each set was: +// +// http://www.cplusplus.com/reference/clibrary/cctype/ +// +// Note that no code was copied from the above or any other published +// description of the ctype.h functionality. + +// To keep space to a minimum we encode the 8 common types directly into +// an 8-bit mask. Other types take a little longer to compute. + +#define _CTYPE_CNTRL 0x01 +#define _CTYPE_SPACE 0x02 +#define _CTYPE_PRINT 0x04 +#define _CTYPE_PUNCT 0x08 +#define _CTYPE_UPPER 0x10 +#define _CTYPE_LOWER 0x20 +#define _CTYPE_DIGIT 0x40 +#define _CTYPE_XDIGIT 0x80 + +#ifndef __ASSEMBLER__ + +#include "stdint.h" + +/// \bug <ctype.h> can not include <stdio.h> to get the definition of +/// EOF. This is because it causes conflicts withe the pore_inline* code which +/// is portable (and ported) to Linux and PHYP. We need to go back through the +/// way the includes are done in SSX and this library and fix this. We should +/// have redefined <stdio.h> rather than creating a new "ssx_io.h" + +#define _CTYPE_EOF -1 + +// Note that in all of the type macros, 'c' is an unsigned char. + +extern const uint8_t _ctype[256]; + +#define _CTYPE_ISLOWER(c) (_ctype[c] & _CTYPE_LOWER) + +#define _CTYPE_ISUPPER(c) (_ctype[c] & _CTYPE_UPPER) + +#define _CTYPE_ISALPHA(c) (_CTYPE_ISUPPER(c) || _CTYPE_ISLOWER(c)) + +#define _CTYPE_ISDIGIT(c) (_ctype[c] & _CTYPE_DIGIT) + +#define _CTYPE_ISALNUM(c) (_CTYPE_ISALPHA(c) || _CTYPE_ISDIGIT(c)) + +#define _CTYPE_ISXDIGIT(c) (_ctype[c] & _CTYPE_XDIGIT) + +#define _CTYPE_ISCNTRL(c) (_ctype[c] & _CTYPE_CNTRL) + +#define _CTYPE_ISSPACE(c) (_ctype[c] & _CTYPE_SPACE) + +#define _CTYPE_ISPRINT(c) (_ctype[c] & _CTYPE_PRINT) + +#define _CTYPE_ISGRAPH(c) (_CTYPE_ISPRINT(c) && ((c) != 0x20)) + +#define _CTYPE_ISPUNCT(c) (_ctype[c] & _CTYPE_PUNCT) + +#define _CTYPE_TOUPPER(c) (islower(c) ? ((c) + ('A' - 'a')) : (c)) + +#define _CTYPE_TOLOWER(c) (isupper(c) ? ((c) - ('A' - 'a')) : (c)) + +// When #include'ed into ctype.c, the non-inline forms of the functions are +// created. +// +// Note that the specification requires that 'c' "must have the value of an +// unsigned char or EOF". The specification also stipulates that "The values +// returned are non-zero if the character c falls into the tested class, and a +// zero value if not." + +#ifdef __CTYPE_C__ + #define _CTYPE_EXTERN_INLINE +#else + #define _CTYPE_EXTERN_INLINE extern inline +#endif + +#define _CTYPE_PREDICATE(predicate, def) \ + _CTYPE_EXTERN_INLINE int predicate(int c) { \ + return ((c == _CTYPE_EOF) ? \ + 0 : _CTYPE_##def((unsigned char)c)); \ + } + +#define _CTYPE_FUNCTION(function, def) \ + _CTYPE_EXTERN_INLINE int function(int c) { \ + return ((c == _CTYPE_EOF) ? \ + _CTYPE_EOF : _CTYPE_##def((unsigned char)c)); \ + } + +_CTYPE_PREDICATE(islower, ISLOWER) +_CTYPE_PREDICATE(isupper, ISUPPER) +_CTYPE_PREDICATE(isalpha, ISALPHA) +_CTYPE_PREDICATE(isdigit, ISDIGIT) +_CTYPE_PREDICATE(isalnum, ISALNUM) +_CTYPE_PREDICATE(isxdigit, ISXDIGIT) +_CTYPE_PREDICATE(iscntrl, ISCNTRL) +_CTYPE_PREDICATE(isspace, ISSPACE) +_CTYPE_PREDICATE(isprint, ISPRINT) +_CTYPE_PREDICATE(isgraph, ISGRAPH) +_CTYPE_PREDICATE(ispunct, ISPUNCT) + +_CTYPE_FUNCTION(tolower, TOLOWER) +_CTYPE_FUNCTION(toupper, TOUPPER) + +#endif // __ASSEMBLER__ + +#endif /* __CTYPE_H__ */ diff --git a/import/chips/p9/common/pmlib/ppc405lib/ctype_table.c b/import/chips/p9/common/pmlib/ppc405lib/ctype_table.c new file mode 100644 index 00000000..9b407585 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ctype_table.c @@ -0,0 +1,303 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ctype_table.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: ctype_table.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ctype_table.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ctype_table.c +/// \brief Character table for <ctype.h> functions. +/// +/// This table is used by the <ctype.h> functions for a quick lookup of +/// character type information. Because the true functional forms of <ctype.h> +/// functions are likely never required, but this file is always required, it +/// is stored separately from ctype.c to (slightly) reduce code/data space +/// requirements. + +#include <stdint.h> +#include <ctype.h> + +const uint8_t _ctype[256] = +{ + _CTYPE_CNTRL, /* 0 00 NUL Null char */ + _CTYPE_CNTRL, /* 1 01 SOH Start of Heading */ + _CTYPE_CNTRL, /* 2 02 STX Start of Text */ + _CTYPE_CNTRL, /* 3 03 ETX End of Text */ + _CTYPE_CNTRL, /* 4 04 EOT End of Transmission */ + _CTYPE_CNTRL, /* 5 05 ENQ Enquiry */ + _CTYPE_CNTRL, /* 6 06 ACK Acknowledgment */ + _CTYPE_CNTRL, /* 7 07 BEL Bell */ + _CTYPE_CNTRL, /* 8 08 BS Back Space */ + _CTYPE_CNTRL | _CTYPE_SPACE, /* 9 09 HT Horizontal Tab */ + _CTYPE_CNTRL | _CTYPE_SPACE, /* 10 0A LF Line Feed */ + _CTYPE_CNTRL | _CTYPE_SPACE, /* 11 0B VT Vertical Tab */ + _CTYPE_CNTRL | _CTYPE_SPACE, /* 12 0C FF Form Feed */ + _CTYPE_CNTRL | _CTYPE_SPACE, /* 13 0D CR Carriage Return */ + _CTYPE_CNTRL, /* 14 0E SO Shift Out / X-On */ + _CTYPE_CNTRL, /* 15 0F SI Shift In / X-Off */ + 0, /* 16 10 DLE Data Line Escape */ + 0, /* 17 11 DC1 Device Control 1 (oft. XON) */ + 0, /* 18 12 DC2 Device Control 2 */ + 0, /* 19 13 DC3 Device Control 3 (oft. XOFF) */ + 0, /* 20 14 DC4 Device Control 4 */ + 0, /* 21 15 NAK Negative Acknowledgement */ + 0, /* 22 16 SYN Synchronous Idle */ + 0, /* 23 17 ETB End of Transmit Block */ + 0, /* 24 18 CAN Cancel */ + 0, /* 25 19 EM End of Medium */ + 0, /* 26 1A SUB Substitute */ + 0, /* 27 1B ESC Escape */ + 0, /* 28 1C FS File Separator */ + 0, /* 29 1D GS Group Separator */ + 0, /* 30 1E RS Record Separator */ + 0, /* 31 1F US Unit Separator */ + _CTYPE_PRINT | _CTYPE_SPACE, /* 32 20 Space */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 33 21 ! Exclamation mark */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 34 22 " Double quotes (or speech marks) */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 35 23 # Number */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 36 24 $ Dollar */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 37 25 % Procenttecken */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 38 26 & Ampersand */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 39 27 ' Single quote */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 40 28 ( Open parenthesis (or open bracket) */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 41 29 ) Close parenthesis (or close bracket) */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 42 2A * Asterisk */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 43 2B + Plus */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 44 2C , Comma */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 45 2D - Hyphen */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 46 2E . Period, dot or full stop */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 47 2F / Slash or divide */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 48 30 0 Zero */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 49 31 1 One */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 50 32 2 Two */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 51 33 3 Three */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 52 34 4 Four */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 53 35 5 Five */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 54 36 6 Six */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 55 37 7 Seven */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 56 38 8 Eight */ + _CTYPE_PRINT | _CTYPE_DIGIT, /* 57 39 9 Nine */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 58 3A : Colon */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 59 3B ; Semicolon */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 60 3C < Less than (or open angled bracket) */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 61 3D = Equals */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 62 3E > Greater than (or close angled bracket) */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 63 3F ? Question mark */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 64 40 @ At symbol */ + _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 65 41 A Uppercase A */ + _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 66 42 B Uppercase B */ + _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 67 43 C Uppercase C */ + _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 68 44 D Uppercase D */ + _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 69 45 E Uppercase E */ + _CTYPE_PRINT | _CTYPE_UPPER | _CTYPE_XDIGIT, /* 70 46 F Uppercase F */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 71 47 G Uppercase G */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 72 48 H Uppercase H */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 73 49 I Uppercase I */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 74 4A J Uppercase J */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 75 4B K Uppercase K */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 76 4C L Uppercase L */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 77 4D M Uppercase M */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 78 4E N Uppercase N */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 79 4F O Uppercase O */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 80 50 P Uppercase P */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 81 51 Q Uppercase Q */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 82 52 R Uppercase R */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 83 53 S Uppercase S */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 84 54 T Uppercase T */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 85 55 U Uppercase U */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 86 56 V Uppercase V */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 87 57 W Uppercase W */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 88 58 X Uppercase X */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 89 59 Y Uppercase Y */ + _CTYPE_PRINT | _CTYPE_UPPER, /* 90 5A Z Uppercase Z */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 91 5B [ Opening bracket */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 92 5C \ Backslash */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 93 5D ] Closing bracket */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 94 5E ^ Caret - circumflex */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 95 5F _ Underscore */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 96 60 ` Grave accent */ + _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 97 61 a Lowercase a */ + _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 98 62 b Lowercase b */ + _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 99 63 c Lowercase c */ + _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 100 64 d Lowercase d */ + _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 101 65 e Lowercase e */ + _CTYPE_PRINT | _CTYPE_LOWER | _CTYPE_XDIGIT, /* 102 66 f Lowercase f */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 103 67 g Lowercase g */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 104 68 h Lowercase h */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 105 69 i Lowercase i */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 106 6A j Lowercase j */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 107 6B k Lowercase k */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 108 6C l Lowercase l */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 109 6D m Lowercase m */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 110 6E n Lowercase n */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 111 6F o Lowercase o */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 112 70 p Lowercase p */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 113 71 q Lowercase q */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 114 72 r Lowercase r */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 115 73 s Lowercase s */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 116 74 t Lowercase t */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 117 75 u Lowercase u */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 118 76 v Lowercase v */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 119 77 w Lowercase w */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 120 78 x Lowercase x */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 121 79 y Lowercase y */ + _CTYPE_PRINT | _CTYPE_LOWER, /* 122 7A z Lowercase z */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 123 7B { Opening brace */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 124 7C | Vertical bar */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 125 7D } Closing brace */ + _CTYPE_PRINT | _CTYPE_PUNCT, /* 126 7E ~ Equivalency sign - tilde */ + 0, /* 127 7F Delete */ + 0, /* 128 80 Euro sign */ + 0, /* 129 81 */ + 0, /* 130 82 ' Single low-9 quotation mark */ + 0, /* 131 83 Latin small letter f with hook */ + 0, /* 132 84 " Double low-9 quotation mark */ + 0, /* 133 85 Horizontal ellipsis */ + 0, /* 134 86 Dagger */ + 0, /* 135 87 Double dagger */ + 0, /* 136 88 Modifier letter circumflex accent */ + 0, /* 137 89 Per mille sign */ + 0, /* 138 8A Latin capital letter S with caron */ + 0, /* 139 8B Single left-pointing angle quotation */ + 0, /* 140 8C Latin capital ligature OE */ + 0, /* 141 8D */ + 0, /* 142 8E Latin captial letter Z with caron */ + 0, /* 143 8F */ + 0, /* 144 90 */ + 0, /* 145 91 ' Left single quotation mark */ + 0, /* 146 92 ' Right single quotation mark */ + 0, /* 147 93 " Left double quotation mark */ + 0, /* 148 94 " Right double quotation mark */ + 0, /* 149 95 Bullet */ + 0, /* 150 96 En dash */ + 0, /* 151 97 Em dash */ + 0, /* 152 98 Small tilde */ + 0, /* 153 99 Trade mark sign */ + 0, /* 154 9A Latin small letter S with caron */ + 0, /* 155 9B Single right-pointing angle quotation mark */ + 0, /* 156 9C Latin small ligature oe */ + 0, /* 157 9D */ + 0, /* 158 9E Latin small letter z with caron */ + 0, /* 159 9F Latin capital letter Y with diaeresis */ + 0, /* 160 A0 Non-breaking space */ + 0, /* 161 A1 Inverted exclamation mark */ + 0, /* 162 A2 Cent sign */ + 0, /* 163 A3 Pound sign */ + 0, /* 164 A4 Currency sign */ + 0, /* 165 A5 Yen sign */ + 0, /* 166 A6 Pipe, Broken vertical bar */ + 0, /* 167 A7 Section sign */ + 0, /* 168 A8 Spacing diaeresis - umlaut */ + 0, /* 169 A9 Copyright sign */ + 0, /* 170 AA Feminine ordinal indicator */ + 0, /* 171 AB Left double angle quotes */ + 0, /* 172 AC Not sign */ + 0, /* 173 AD Soft hyphen */ + 0, /* 174 AE Registered trade mark sign */ + 0, /* 175 AF Spacing macron - overline */ + 0, /* 176 B0 Degree sign */ + 0, /* 177 B1 Plus-or-minus sign */ + 0, /* 178 B2 Superscript two - squared */ + 0, /* 179 B3 Superscript three - cubed */ + 0, /* 180 B4 Acute accent - spacing acute */ + 0, /* 181 B5 Micro sign */ + 0, /* 182 B6 Pilcrow sign - paragraph sign */ + 0, /* 183 B7 Middle dot - Georgian comma */ + 0, /* 184 B8 Spacing cedilla */ + 0, /* 185 B9 Superscript one */ + 0, /* 186 BA Masculine ordinal indicator */ + 0, /* 187 BB Right double angle quotes */ + 0, /* 188 BC one quarter */ + 0, /* 189 BD Fraction one half */ + 0, /* 190 BE Fraction three quarters */ + 0, /* 191 BF Inverted question mark */ + 0, /* 192 C0 Latin capital letter A with grave */ + 0, /* 193 C1 Latin capital letter A with acute */ + 0, /* 194 C2 Latin capital letter A with circumflex */ + 0, /* 195 C3 Latin capital letter A with tilde */ + 0, /* 196 C4 Latin capital letter A with diaeresis */ + 0, /* 197 C5 Latin capital letter A with ring above */ + 0, /* 198 C6 Latin capital letter AE */ + 0, /* 199 C7 Latin capital letter C with cedilla */ + 0, /* 200 C8 Latin capital letter E with grave */ + 0, /* 201 C9 Latin capital letter E with acute */ + 0, /* 202 CA Latin capital letter E with circumflex */ + 0, /* 203 CB Latin capital letter E with diaeresis */ + 0, /* 204 CC Latin capital letter I with grave */ + 0, /* 205 CD Latin capital letter I with acute */ + 0, /* 206 CE Latin capital letter I with circumflex */ + 0, /* 207 CF Latin capital letter I with diaeresis */ + 0, /* 208 D0 Latin capital letter ETH */ + 0, /* 209 D1 Latin capital letter N with tilde */ + 0, /* 210 D2 Latin capital letter O with grave */ + 0, /* 211 D3 Latin capital letter O with acute */ + 0, /* 212 D4 Latin capital letter O with circumflex */ + 0, /* 213 D5 Latin capital letter O with tilde */ + 0, /* 214 D6 Latin capital letter O with diaeresis */ + 0, /* 215 D7 Multiplication sign */ + 0, /* 216 D8 Latin capital letter O with slash */ + 0, /* 217 D9 Latin capital letter U with grave */ + 0, /* 218 DA Latin capital letter U with acute */ + 0, /* 219 DB Latin capital letter U with circumflex */ + 0, /* 220 DC Latin capital letter U with diaeresis */ + 0, /* 221 DD Latin capital letter Y with acute */ + 0, /* 222 DE Latin capital letter THORN */ + 0, /* 223 DF Latin small letter sharp s - ess-zed */ + 0, /* 224 E0 Latin small letter a with grave */ + 0, /* 225 E1 Latin small letter a with acute */ + 0, /* 226 E2 Latin small letter a with circumflex */ + 0, /* 227 E3 Latin small letter a with tilde */ + 0, /* 228 E4 Latin small letter a with diaeresis */ + 0, /* 229 E5 Latin small letter a with ring above */ + 0, /* 230 E6 Latin small letter ae */ + 0, /* 231 E7 Latin small letter c with cedilla */ + 0, /* 232 E8 Latin small letter e with grave */ + 0, /* 233 E9 Latin small letter e with acute */ + 0, /* 234 EA Latin small letter e with circumflex */ + 0, /* 235 EB Latin small letter e with diaeresis */ + 0, /* 236 EC Latin small letter i with grave */ + 0, /* 237 ED Latin small letter i with acute */ + 0, /* 238 EE Latin small letter i with circumflex */ + 0, /* 239 EF Latin small letter i with diaeresis */ + 0, /* 240 F0 Latin small letter eth */ + 0, /* 241 F1 Latin small letter n with tilde */ + 0, /* 242 F2 Latin small letter o with grave */ + 0, /* 243 F3 Latin small letter o with acute */ + 0, /* 244 F4 Latin small letter o with circumflex */ + 0, /* 245 F5 Latin small letter o with tilde */ + 0, /* 246 F6 Latin small letter o with diaeresis */ + 0, /* 247 F7 Division sign */ + 0, /* 248 F8 Latin small letter o with slash */ + 0, /* 249 F9 Latin small letter u with grave */ + 0, /* 250 FA Latin small letter u with acute */ + 0, /* 251 FB Latin small letter u with circumflex */ + 0, /* 252 FC Latin small letter u with diaeresis */ + 0, /* 253 FD Latin small letter y with acute */ + 0, /* 254 FE Latin small letter thorn */ + 0, /* 255 FF Latin small letter y with diaeresis */ +}; diff --git a/import/chips/p9/common/pmlib/ppc405lib/errno.h b/import/chips/p9/common/pmlib/ppc405lib/errno.h new file mode 100644 index 00000000..8a2303ee --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/errno.h @@ -0,0 +1,49 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/errno.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __ERRNO_H__ +#define __ERRNO_H__ + +// $Id: errno.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/errno.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file errno.h +/// \brief Replacement for <errno.h> +/// +/// SSX does not support a per-thread or global 'errno'. The standard Unix +/// errno values returned by library functions are defined here. The prefix +/// code is the 'telephone code' for "errn". + +#define EINVAL 0x00377601 +#define EBADF 0x00377602 +#define EAGAIN 0x00377603 +#define ENXIO 0x00377604 +#define ENOMEM 0x00377605 + +#endif /* __ERRNO_H__ */ diff --git a/import/chips/p9/common/pmlib/ppc405lib/fgetc.c b/import/chips/p9/common/pmlib/ppc405lib/fgetc.c new file mode 100644 index 00000000..a5f543a1 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/fgetc.c @@ -0,0 +1,122 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/fgetc.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: fgetc.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/fgetc.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file fgetc.c +/// \brief Implementation of fgetc() and ungetc() +/// +/// The implementations of these APIs are split out to save code space for +/// applications that do not require them. + +#include "ssx_io.h" + + +/// Read a character from a stream +/// +/// fgetc() reads the next character from \a stream and returns it as an +/// unsigned char cast to an int, or EOF on end of file or error. + +int +fgetc(FILE* stream) +{ + unsigned char c; + size_t read; + int rc; + + if (stream->flags & SSX_FILE_HAS_CHARACTER) + { + stream->flags &= ~SSX_FILE_HAS_CHARACTER; + rc = stream->character; + } + else + { + rc = sread(stream, &c, 1, &read); + + if (rc || (read != 1)) + { + rc = EOF; + } + else + { + rc = c; + + if (c == '\n') + { + stream->lines++; + } + } + } + + return rc; +} + + +/// Push a character back onto a stream +/// +/// ungetc() pushes \a c back to \a stream, cast to unsigned char, where it is +/// available for subsequent fgetc() operations. Only one pushback is +/// implemented. A call of ungetc() on a stream that already has a character +/// pushed back will drop the new push-back and return EOF. Otherwise +/// ungetc() returns \a c. + +int +ungetc(int c, FILE* stream) +{ + int rc; + + if (stream->flags & SSX_FILE_HAS_CHARACTER) + { + rc = EOF; + } + else + { + stream->flags |= SSX_FILE_HAS_CHARACTER; + stream->character = c; + rc = c; + } + + return rc; +} + +/// Return the number of newline characters read from a stream +/// +/// This API is an SSX entension to the \<stdio\> APIs. It returns the number +/// of newline characters read from the stream using fgetc(). Newline +/// characters read via direct calls to sread() in the stream are not counted. +/// +/// An application that sees an error while reading from a stream can print +/// flines() or flines() + 1 (depending on the application) to help users +/// track down errors in their input. +size_t +flines(FILE* stream) +{ + return stream->lines; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/libppc405files.mk b/import/chips/p9/common/pmlib/ppc405lib/libppc405files.mk new file mode 100644 index 00000000..ec672607 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/libppc405files.mk @@ -0,0 +1,74 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: import/chips/p9/common/pmlib/ppc405lib/libppc405files.mk $ +# +# OpenPOWER HCODE Project +# +# COPYRIGHT 2015,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +# @file libppc405files.mk +# +# @brief mk for libppc405.a object files +# +# @page ChangeLogs Change Logs +# @section libppc405files.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# INCLUDES +########################################################################## + +C-SOURCES = \ + assert.c \ + byte_pool.c \ + ctype.c \ + ctype_table.c \ + fgetc.c \ + initcall.c \ + lfsr.c \ + mutex.c \ + periodic_semaphore.c \ + polling.c \ + printf.c \ + progress.c \ + puts.c \ + rtx_stdio.c \ + simics_stdio.c \ + sprintf.c \ + ssx_dump.c \ + ssx_io.c \ + stdlib.c \ + strcasecmp.c \ + strdup.c \ + string.c \ + string_stream.c \ + strtox.c \ + sxlock.c \ + time.c + +S-SOURCES = + +LIBPPC405_OBJECTS = $(C-SOURCES:.c=.o) $(S-SOURCES:.S=.o) diff --git a/import/chips/p9/common/pmlib/ppc405lib/libssx.h b/import/chips/p9/common/pmlib/ppc405lib/libssx.h new file mode 100644 index 00000000..3938c5f1 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/libssx.h @@ -0,0 +1,44 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/libssx.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __LIBSSX_H__ +#define __LIBSSX_H__ + +// $Id: libssx.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/libssx.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file libssx.h +/// \brief Header definitions with no other obvious home + +// Kernel panics + +#define ASSERTION_FAILURE 0x00542701 +#define ERROR_EXIT 0x00542702 + +#endif // __LIBSSX_H__ diff --git a/import/chips/p9/common/pmlib/ppc405lib/polling.c b/import/chips/p9/common/pmlib/ppc405lib/polling.c new file mode 100644 index 00000000..283a784a --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/polling.c @@ -0,0 +1,112 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/polling.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: polling.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/polling.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file polling.c +/// \brief Library APIs for polling + +#include "polling.h" + +int +polling(int* o_rc, + int (*i_condition)(void* io_arg, int* o_satisfied), + void* io_arg, + SsxInterval i_timeout, + SsxInterval i_sleep) +{ + SsxTimebase start; + int rc, pollRc, timed_out, done; + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((i_condition == 0), POLLING_ERROR); + } + + start = ssx_timebase_get(); + timed_out = 0; + + do + { + pollRc = i_condition(io_arg, &done); + + if (pollRc) + { + rc = POLLING_CONDITION; + break; + } + + if (done) + { + rc = 0; + break; + } + + if (timed_out) + { + rc = POLLING_TIMEOUT; + break; + } + + if (i_sleep != 0) + { + rc = ssx_sleep(i_sleep); + + if (rc) + { + break; + } + } + + timed_out = + ((i_timeout != SSX_WAIT_FOREVER) && + ((ssx_timebase_get() - start) >= i_timeout)); + + } + while (1); + + if (o_rc) + { + *o_rc = pollRc; + } + + return rc; +} + + +void +busy_wait(SsxInterval i_interval) +{ + SsxTimebase start; + + start = ssx_timebase_get(); + + while ((ssx_timebase_get() - start) < i_interval); +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/polling.h b/import/chips/p9/common/pmlib/ppc405lib/polling.h new file mode 100644 index 00000000..0cdb266c --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/polling.h @@ -0,0 +1,118 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/polling.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __POLLING_H__ +#define __POLLING_H__ + +// $Id: polling.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/polling.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file polling.c +/// \brief Library APIs for polling and busy-waiting + +#include "ssx.h" + +// Return/Panic codes + +#define POLLING_TIMEOUT 0x00765501 +#define POLLING_ERROR 0x00765502 +#define POLLING_CONDITION 0x00765503 + + +#ifndef __ASSEMBLER__ + +/// Poll for a condition or a timeout with optional sleep +/// +/// \param[out] o_rc The last return code from calling \a i_condition. This +/// will only be valid if the return code from polling() is +/// POLLING_CONDITION. This argument may be passed as NULL (0) if the caller +/// does not require this information. +/// +/// \param[in] i_condition A function of two arguments, returning an integer +/// return code - 0 for success, non-0 for failure. The first argument is a +/// private state or parameter variable. The second argument is used to +/// return the truth value of the \a i_condition predicate (0 for false, non-0 +/// for true), and is only considered if the return value of \a i_condition is +/// 0. +/// +/// \param[in,out] io_arg The private argument of the \a condition function. +/// +/// \param[in] i_timeout The maximum amount of time to poll the \a condition +/// before declaring a timeout. The special value SSX_WAIT_FOREVER can be +/// used to specify polling without timeout. +/// +/// \param[in] i_sleep If non-0 at entry, then the thread will sleep for this +/// interval between polls of the condition. Otherwise the polling is +/// continuous. polling() can only be called with i_sleep non-0 from a +/// thread context (since interrupt contexts can not block). +/// +/// polling() implements a generic polling protocol for conditions that can +/// not be recognized as interrupt events. polling() polls the \a i_condition +/// until either an error is encountered, the condition is true, or the +/// polling times out as measured by the SSX timebase. Whenever a timeout is +/// detected the condition is polled once more to exclude false timeouts that +/// may have been caused by thread preemption. +/// +/// The \a i_sleep A non-0 value of \a i_sleep specifies that the thread +/// should sleep for the given interval between polling tries instead of +/// polling continuously. A non-0 \a i_sleep argument is only legal in thread +/// contexts. +/// +/// \retval 0 Success; The condition was satisfied prior to the timeout. +/// +/// \retval POLLING_TIMEOUT A timeout was detected before the condition became +/// valid. +/// +/// \retval POLLING_ERROR This code is returned if any of the arguments of +/// polling() are invalid. +/// +/// \retval POLLING_CONDITION This code is returned if the \a i_condition +/// function returns a non-0 return code. +/// +/// If the embedded call of ssx_sleep() fails for some reason then the return +/// code will be the code returned by ssx_sleep(). +int +polling(int* o_rc, + int (*i_condition)(void* io_arg, int* o_satisfied), + void* io_arg, + SsxInterval i_timeout, + SsxInterval i_sleep); + + +/// A busy-wait loop +/// +/// \param[in] i_interval The interval of time to busy-wait. The actual +/// interval may be more than this if the thread is interrupted. If called +/// from a context with interrupts disabled the timing should be very precise. +void +busy_wait(SsxInterval i_interval); + +#endif // __ASSEMBLER__ + +#endif // __POLLING_H__ diff --git a/import/chips/p9/common/pmlib/ppc405lib/printf.c b/import/chips/p9/common/pmlib/ppc405lib/printf.c new file mode 100644 index 00000000..ea895de3 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/printf.c @@ -0,0 +1,986 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/printf.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: printf.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/printf.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file printf.c +/// \brief Clean-room implementation of printf() functions for SSX I/O +/// +/// For licensing reasons we are required to create our own version of the +/// printf() family of functions. This implementation was created without +/// reference to or inclusion of any licensed or copyrighted code. +/// +/// The functions defined in this file have prototypes, behavior and return +/// values as defined by C language standards. In the event of an error a +/// negative value is returned, generally corresponding to a standard Unix +/// 'errno' code. Note that SSX does not support either an application- or +/// per-thread 'errno', so the only record of any error is the \a error field +/// of the stream. Also note that SSX may be configured to cause a panic if an +/// error is detected rather than returning an error code. +/// +/// This implementation defines a limited but useful subset of the C standard +/// for format control. This implementation includes the following: +/// +/// - \b c, \b d, \b i, \b n, \b p, \b s, \b u, \b x, and \b X conversion +/// specifiers, as well as '%%' to output a single '%' +/// +/// - \b #, \b 0, \b ' ' and \b + flag characters +/// +/// - Decimal field width specifiers including * (but indirect field widths +/// must be positive as left-justification is not supported) +/// +/// - Decimal precision specifiers (currently only apply to %s formats, may be +/// indirect using *) +/// +/// - \b l, \b ll and \b z length modifiers +/// +/// \b Notes: +/// +/// \a If a \c p conversion specifier is used without any flags (\c '%p'), the +/// \c p conversion is interptered as if it were \c 0x%08lx for 32-bit address +/// machines and \c 0x%016llx for 64-bit address machines. The GCC builtin +/// format checker gives warnings about '0' flag characters for \c p +/// conversion specifiers, so there is otherwise no 'un-warned' way to get +/// this preferred (by some) format of pointer values. If you do include +/// explicit flags (e.g., \c %30p) they will be processed as expected. +/// +/// Similar to how printf() behaves on an X86-Linux machine, a null pointer +/// will print as "(null)" with the %s format (unless the precision specifier +/// precludes it) and "(nil)" with the %p format. +/// +/// Note that calling formatted I/O functions on non-blocking streams may fail +/// with the -EAGAIN error, and there is no clean way to restart these +/// calls. Calling formatted (or any) I/O functions on blocking streams from +/// interrupt contexts in SSX is also likely to fail intermittently since +/// interrupt contexts can not block in SSX. +/// +/// \todo I'd really like to implement the '-' flag for +/// left-justification. Implementing the precision specifer for integers +/// should be done for completeness. + +#include "ssx.h" +#include "ssx_io.h" + +// Formatting options + +#define OPTION_ALTERNATE 0x0001 +#define OPTION_PAD_ZERO 0x0002 +#define OPTION_PLUS_SIGN 0x0004 +#define OPTION_FIELD_WIDTH 0x0008 +#define OPTION_PRECISION 0x0010 +#define OPTION_LONG 0x0020 +#define OPTION_LONG_LONG 0x0040 +#define OPTION_SIZE_T 0x0080 +#define OPTION_UPPERCASE 0x0100 +#define OPTION_HEX 0x0200 +#define OPTION_SPACE 0x0400 + + +// Generate padding if required, returning the total number of pad characters +// output or a negative error code. The 'nchars' argument is the number of +// non-pad characters to be output by the caller. + +#define PAD_SIZE 8 +static const char zeros[PAD_SIZE] = {'0', '0', '0', '0', '0', '0', '0', '0'}; +static const char blanks[PAD_SIZE] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; + +static ssize_t +pad(FILE* stream, size_t nchars, int options, size_t width) +{ + const char* padchars; + size_t chars, written; + int rc; + + if (!(options & OPTION_FIELD_WIDTH) || (nchars >= width)) + { + return 0; + } + + chars = width - nchars; + + if (options & OPTION_PAD_ZERO) + { + padchars = zeros; + } + else + { + padchars = blanks; + } + + while (chars) + { + rc = swrite(stream, (void*)padchars, MIN(chars, PAD_SIZE), &written); + + if (rc < 0) + { + return rc; + } + + chars -= written; + } + + return width - nchars; +} + + +// Format a character + +static ssize_t +format_char(FILE* stream, unsigned char c, int options, size_t width) +{ + ssize_t padchars, nchars; + int rc; + + padchars = pad(stream, 1, options, width); + + if (padchars < 0) + { + return padchars; + } + + nchars = padchars + 1; + rc = swrite(stream, (void*)(&c), 1, 0); + + if (rc < 0) + { + return rc; + } + + return nchars; +} + + +// Format a string +// +// If the string is the NULL pointer then normally "(null)" is printed +// unless the precision is < 6, in which case the empty string is printed. +// The specification leaves it as undefined what happens if a string requests +// 0 padding; Here we always pad with blanks (although GCC/PowerPC catches +// this as an error). + +static ssize_t +format_string(FILE* stream, const char* s, int options, + size_t width, size_t precision) +{ + size_t len; + ssize_t padchars, nchars; + int rc; + + if (s == 0) + { + if ((options & OPTION_PRECISION) && (precision < 6)) + { + s = ""; + } + else + { + s = "(null)"; + } + } + + len = strlen(s); + + if (options & OPTION_PRECISION) + { + len = MIN(len, precision); + } + + options &= ~OPTION_PAD_ZERO; + padchars = pad(stream, len, options, width); + + if (padchars < 0) + { + return padchars; + } + + nchars = padchars + len; + rc = swrite(stream, (void*)s, len, 0); + + if (rc < 0) + { + return rc; + } + + return nchars; +} + + +// Format an integer - signed and unsigned. A 64-bit integer (assumed to be +// the longest we'll see) has 20 decimal digits. An extra space is reserved +// for the sign. If zero-padding is specified, the sign will be output +// separately. + +static const char lower[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +static const char upper[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +static ssize_t +format_int(FILE* stream, long long int lli, int options, size_t width) +{ + char digits[21]; + int rc, k, ndigits, negative, positive, i; + ssize_t output; + + negative = (lli < 0); + positive = (lli > 0); + + // Unpack the integer to characters. The code is optimized for 32-bit + // machines where 64-bit division is not built in. The first part of the + // loop handles integers requiring a 64-bit divide, the second loop + // handles 32-bit integers. + + if (lli == 0) + { + digits[20] = '0'; + k = 20; + } + else if (negative) + { + for (k = 21; + lli != (int)lli; + digits[--k] = lower[-(lli % 10)], lli = lli / 10); + + for (i = (int)lli; + i != 0; + digits[--k] = lower[-(i % 10)], i = i / 10); + } + else + { + for (k = 21; + lli != (int)lli; + digits[--k] = lower[lli % 10], lli = lli / 10); + + for (i = (int)lli; + i != 0; + digits[--k] = lower[i % 10], i = i / 10); + } + + ndigits = 21 - k; + + // Handle other options and output + + output = 0; + + if (options & OPTION_PAD_ZERO) + { + + if (negative) + { + rc = swrite(stream, "-", 1, 0); + + if (rc < 0) + { + return rc; + } + + output++; + } + else if (positive) + { + if (options & OPTION_PLUS_SIGN) + { + rc = swrite(stream, "+", 1, 0); + + if (rc < 0) + { + return rc; + } + + output++; + } + else if (options & OPTION_SPACE) + { + rc = swrite(stream, " ", 1, 0); + + if (rc < 0) + { + return rc; + } + + output++; + } + } + + rc = pad(stream, ndigits + output, options, width); + + if (rc < 0) + { + return rc; + } + + output += rc; + rc = swrite(stream, &(digits[k]), ndigits, 0); + + if (rc < 0) + { + return rc; + } + + output += ndigits; + + } + else + { + + if (negative) + { + digits[--k] = '-'; + ndigits++; + } + else if (positive) + { + if (options & OPTION_PLUS_SIGN) + { + digits[--k] = '+'; + ndigits++; + } + else if (options & OPTION_SPACE) + { + digits[--k] = ' '; + ndigits++; + } + } + + rc = pad(stream, ndigits, options, width); + + if (rc < 0) + { + return rc; + } + + output += rc; + rc = swrite(stream, &(digits[k]), ndigits, 0); + + if (rc < 0) + { + return rc; + } + + output += ndigits; + } + + return output; +} + + +static ssize_t +format_unsigned(FILE* stream, unsigned long long ull, int options, size_t width) +{ + char digits[21], *alternate; + const char* xchars; + int rc, k, ndigits, zero; + unsigned u; + ssize_t output; + + zero = (ull == 0); + + // Determine hex case and alternate string + + alternate = 0; + + if (options & OPTION_HEX) + { + if (options & OPTION_UPPERCASE) + { + xchars = upper; + + if (options & OPTION_ALTERNATE) + { + alternate = "0X"; + } + } + else + { + xchars = lower; + + if (options & OPTION_ALTERNATE) + { + alternate = "0x"; + } + } + } + else + { + xchars = lower; + } + + // Unpack the unsigned integer to characters. The Hex conversions are + // easier since they can be done with shift and mask rather than + // divison. The code is optimized for a 32-bit machine where 64-bit + // division is not built-in. + + if (zero) + { + digits[20] = '0'; + k = 20; + } + else if (options & OPTION_HEX) + { + for (k = 21; + ull != (unsigned)ull; + digits[--k] = xchars[ull & 0xf], ull = ull >> 4); + + for (u = (unsigned)ull; + u != 0; + digits[--k] = xchars[u & 0xf], u = u >> 4); + } + else + { + for (k = 21; + ull != (unsigned)ull; + digits[--k] = xchars[ull % 10], ull = ull / 10); + + for (u = (unsigned)ull; + u != 0; + digits[--k] = xchars[u % 10], u = u / 10); + } + + ndigits = 21 - k; + + // Handle other options and output + + output = 0; + + if (options & OPTION_PAD_ZERO) + { + + if (!zero && alternate) + { + rc = swrite(stream, (void*)alternate, 2, 0); + + if (rc < 0) + { + return rc; + } + + output += 2; + } + + rc = pad(stream, ndigits + output, options, width); + + if (rc < 0) + { + return rc; + } + + output += rc; + rc = swrite(stream, &(digits[k]), ndigits, 0); + + if (rc < 0) + { + return rc; + } + + output += ndigits; + + } + else + { + + if (!zero && alternate) + { + output += 2; + } + + rc = pad(stream, ndigits + output, options, width); + + if (rc < 0) + { + return rc; + } + + output += rc; + + if (!zero && alternate) + { + rc = swrite(stream, alternate, 2, 0); + + if (rc < 0) + { + return rc; + } + + output += 2; + } + + rc = swrite(stream, &(digits[k]), ndigits, 0); + + if (rc < 0) + { + return rc; + } + + output += ndigits; + } + + return output; +} + + +int +vfprintf(FILE* stream, const char* format, va_list argp) +{ + const char* fmt, *scan; + int rc, total_chars, options, done; + size_t width, precision; + + int arg_i, *arg_pi; + long int arg_li; + long long int arg_lli; + ssize_t arg_zi; + unsigned arg_u; + unsigned long arg_lu; + unsigned long long arg_llu; + size_t arg_zu; + char* arg_s; + + total_chars = 0; + + fmt = format; + + while (*fmt) + { + + // Scan until '%' or the end of the format, then output the text. + + scan = fmt; + + while (*scan && (*scan != '%')) + { + scan++; + } + + if (scan != fmt) + { + rc = swrite(stream, fmt, scan - fmt, 0); + + if (rc < 0) + { + return rc; + } + + total_chars += scan - fmt; + } + + fmt = scan; + + if (!*fmt) + { + return total_chars; + } + + fmt++; + + // We got a '%'. Check for %% and %n. + + switch (*fmt) + { + case '\0': + SSX_IO_ERROR(stream, EINVAL); + break; + + case '%': + rc = swrite(stream, "%", 1, 0); + + if (rc < 0) + { + return rc; + } + + total_chars++; + fmt++; + continue; + + case 'n': + arg_pi = va_arg(argp, int*); + *arg_pi = total_chars; + fmt++; + continue; + } + + // Collect padding options, if any. Left justification is not + // implemeted. + + options = 0; + done = 0; + + do + { + switch (*fmt) + { + case '\0': + SSX_IO_ERROR(stream, EINVAL); + break; + + case '#': + options |= OPTION_ALTERNATE; + break; + + case '0': + options |= OPTION_PAD_ZERO; + break; + + case '+': + options |= OPTION_PLUS_SIGN; + break; + + case ' ': + options |= OPTION_SPACE; + break; + + case '-': + SSX_IO_ERROR(stream, EINVAL); // Left just. not impl. + break; + + default: + done = 1; + break; + } + + if (!done) + { + fmt++; + } + } + while (!done); + + // Collect the field width, if specified. A negative precision + // specified as an argument indicates left justification (not + // implemented). + + width = 0; + + if (isdigit(*fmt)) + { + options |= OPTION_FIELD_WIDTH; + + for (; isdigit(*fmt); fmt++) + { + width = (width * 10) + (*fmt - '0'); + } + } + else if (*fmt == '*') + { + fmt++; + options |= OPTION_FIELD_WIDTH; + arg_i = va_arg(argp, int); + + if (arg_i < 0) + { + SSX_IO_ERROR(stream, EINVAL); // Left just. not impl. + } + + width = arg_i; + } + + // Collect the precision, if specified. By standard specification an + // empty or negative precision is interpreted as 0. + + precision = 0; + + if (*fmt == '.') + { + fmt++; + options |= OPTION_PRECISION; + + if (isdigit(*fmt)) + { + for(; isdigit(*fmt); fmt++) + { + precision = (precision * 10) + (*fmt - '0'); + } + } + else if (*fmt == '*') + { + fmt++; + arg_i = va_arg(argp, int); + + if (arg_i < 0) + { + arg_i = 0; + } + + precision = arg_i; + } + } + + // Collect length modifiers. + + done = 0; + + do + { + switch (*fmt) + { + case '\0': + SSX_IO_ERROR(stream, EINVAL); + break; + + case 'l': + if (options & OPTION_LONG) + { + options &= ~OPTION_LONG; + options |= OPTION_LONG_LONG; + } + else if (options & OPTION_LONG_LONG) + { + SSX_IO_ERROR(stream, EINVAL); + } + else + { + options |= OPTION_LONG; + } + + if (options & OPTION_SIZE_T) + { + SSX_IO_ERROR(stream, EINVAL); + } + + break; + + case 'z': + if ((options & OPTION_LONG) || (options & OPTION_LONG_LONG)) + { + SSX_IO_ERROR(stream, EINVAL); + } + + options |= OPTION_SIZE_T; + break; + + default: + done = 1; + break; + } + + if (!done) + { + fmt++; + } + } + while (!done); + + // Use the conversion specifier to format the next argument + + switch (*fmt) + { + + case 'c': + arg_i = va_arg(argp, int); + rc = format_char(stream, (unsigned char)arg_i, options, width); + + if (rc < 0) + { + return rc; + } + + total_chars++; + break; + + case 'd': + case 'i': + if (options & OPTION_LONG) + { + arg_li = va_arg(argp, long int); + rc = format_int(stream, (long long int)arg_li, options, + width); + } + else if (options & OPTION_LONG_LONG) + { + arg_lli = va_arg(argp, long long int); + rc = format_int(stream, (long long int)arg_lli, options, + width); + } + else if (options & OPTION_SIZE_T) + { + arg_zi = va_arg(argp, ssize_t); + rc = format_int(stream, (long long int)arg_zi, options, + width); + } + else + { + arg_i = va_arg(argp, int); + rc = format_int(stream, (long long int)arg_i, options, + width); + } + + if (rc < 0) + { + return rc; + } + + total_chars += rc; + break; + + case 'p': + arg_lu = va_arg(argp, unsigned long); + options |= (OPTION_ALTERNATE | OPTION_HEX); + + if (!(options & OPTION_PAD_ZERO) && + !(options & OPTION_FIELD_WIDTH)) + { + options |= (OPTION_PAD_ZERO | OPTION_FIELD_WIDTH); + width = (2 * sizeof(unsigned long)) + 2; /* 0x........ */ + } + + if (arg_lu == 0) + { + options &= ~OPTION_PRECISION; + rc = format_string(stream, "(nil)", options, width, precision); + } + else + { + rc = format_unsigned(stream, (unsigned long long)arg_lu, + options, width); + } + + if (rc < 0) + { + return rc; + } + + total_chars += rc; + break; + + case 's': + arg_s = va_arg(argp, char*); + rc = format_string(stream, arg_s, options, width, precision); + + if (rc < 0) + { + return rc; + } + + total_chars += rc; + break; + + case 'X': + options |= OPTION_UPPERCASE; + + case 'x': + options |= OPTION_HEX; + + case 'u': + if (options & OPTION_LONG) + { + arg_lu = va_arg(argp, unsigned long); + rc = format_unsigned(stream, (unsigned long long)arg_lu, + options, width); + } + else if (options & OPTION_LONG_LONG) + { + arg_llu = va_arg(argp, unsigned long long); + rc = format_unsigned(stream, (unsigned long long)arg_llu, + options, width); + } + else if (options & OPTION_SIZE_T) + { + arg_zu = va_arg(argp, size_t); + rc = format_unsigned(stream, (unsigned long long)arg_zu, + options, width); + } + else + { + arg_u = va_arg(argp, unsigned); + rc = format_unsigned(stream, (unsigned long long )arg_u, + options, width); + } + + if (rc < 0) + { + return rc; + } + + total_chars += rc; + break; + + default: + SSX_IO_ERROR(stream, EINVAL); + break; + } + + fmt++; + } + + return total_chars; +} + + +int +vprintf(const char* format, va_list argp) +{ + return vfprintf(stdout, format, argp); +} + + +int +fprintf(FILE* stream, const char* format, ...) +{ + va_list argp; + int rc; + + va_start(argp, format); + rc = vfprintf(stream, format, argp); + va_end(argp); + return rc; +} + + +int +printf(const char* format, ...) +{ + va_list argp; + int rc; + + va_start(argp, format); + rc = vfprintf(stdout, format, argp); + va_end(argp); + return rc; +} + + +int +printk(const char* format, ...) +{ + va_list argp; + int rc; + + va_start(argp, format); + rc = vfprintf(ssxout, format, argp); + va_end(argp); + return rc; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/puts.c b/import/chips/p9/common/pmlib/ppc405lib/puts.c new file mode 100644 index 00000000..dc2214fa --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/puts.c @@ -0,0 +1,131 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/puts.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: puts.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/puts.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file puts.c +/// \brief Implementation of puts(), fputs(), putchar(), fputc() +/// +/// The implementations of these APIs are split out to save code space for +/// applications that do not require them. + +#include "ssx_io.h" + + +/// Put a character to a stream +/// +/// The fputc() function writes the byte specified by \a c (converted to an +/// unsigned char) to the stream pointed to by \a stream. On success, fputc() +/// returns the value written, i.e., the \c unsigned \c char form of \a c. +/// +/// The POSIX standard fputc() returns EOF on error; this version returns the +/// negative error code of the underlying I/O error, which will also be set in +/// the \a error field of the \a stream. Note that SSX may also be configured +/// to panic in the event of an I/O error. + +int +fputc(int c, FILE* stream) +{ + unsigned char uc = (unsigned char)c; + int rc = swrite(stream, (void*)(&uc), 1, 0); + + if (rc < 0) + { + return rc; + } + else + { + return uc; + } +} + + +/// Put a string to a stream +/// +/// The fputs() function writes the null-terminated string \a s to the stream +/// pointed to by \a stream. The terminating null byte is not written. On +/// success, fputs() returns 0. +/// +/// The POSIX standard fputc() returns EOF on error; this version returns the +/// negative error code of the underlying I/O error, which will also be set in +/// the \a error field of the \a stream. Note that SSX may also be configured +/// to panic in the event of an I/O error. + +int +fputs(const char* s, FILE* stream) +{ + return swrite(stream, s, strlen(s), 0); +} + +/// Put a string to \c stdout +/// +/// The puts() function writes the null-terminated string \a s followed by a +/// newline to \a stdout. The terminating null byte is not written. On +/// success, puts() returns 0. +/// +/// The POSIX standard fputc() returns EOF on error; this version returns the +/// negative error code of the underlying I/O error, which will also be set in +/// the \a error field of the \a stream. Note that SSX may also be configured +/// to panic in the event of an I/O error. + +int +puts(const char* s) +{ + int rc = fputs(s, stdout); + + if (rc < 0) + { + return rc; + } + else + { + rc = fputc('\n', stdout); + + if (rc < 0) + { + return rc; + } + else + { + return 0; + } + } +} + + +/// Put a character to \a stdout. +/// +/// \c putchar(c) is equivalent to <c> fputc(c, stdout) </c>. + +int +putchar(int c) +{ + return fputc(c, stdout); +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/simics_stdio.c b/import/chips/p9/common/pmlib/ppc405lib/simics_stdio.c new file mode 100644 index 00000000..33678474 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/simics_stdio.c @@ -0,0 +1,190 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/simics_stdio.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: simics_stdio.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/simics_stdio.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file simics_stdio.c +/// \brief SSX I/O drivers for Simics stdio streams +/// +/// The Simics 'stdio' component is a pseudo serial port for I/O to stdio, +/// stdout and stderr, as well as to other configurable streams. Each virtual +/// file potentially has a read port, write port and flush port. +/// +/// The write ports accept 1, 2 and 4-byte transactions on a 32-bit OCI +/// address and write the data to the associated stream. Writing any value to +/// the flush port flushes the output stream. The input ports are not yet +/// implemented. + +#include "ssx.h" +#include "simics_stdio.h" + + +SimicsStdio simics_stdin; +SimicsStdio simics_stdout; +SimicsStdio simics_stderr; + +int +simics_stdio_sread(FILE* stream, void* buf, size_t count, size_t* read) +{ + SSX_PANIC(ENXIO); + return -ENXIO; +} + + +int +simics_stdio_swrite(FILE* stream, const void* buf, + size_t count, size_t* written) +{ + SimicsStdio* simics = (SimicsStdio*)stream; + size_t n; + + n = count; + + while (n) + { + if (n >= 4) + { + out32(simics->write_address, *((uint32_t*)buf)); + buf += 4; + n -= 4; + } + else if (n >= 2) + { + out16(simics->write_address, *((uint16_t*)buf)); + buf += 2; + n -= 2; + } + else + { + out8(simics->write_address, *((uint8_t*)buf)); + buf++; + n--; + } + } + + *written = count; + + return 0; +} + + +ssize_t +simics_stdio_fflush(FILE* stream) +{ + SimicsStdio* simics = (SimicsStdio*)stream; + + out8(simics->flush_address, 0); + return 0; +} + + +/// Create a SimicsStdio stream +/// +/// Any of the \a read_address, \a write_address or \a flush_address which are +/// non-0 specify that the stream supports the associated method. The Simics +/// I/O drivers do not require locking. + +int +simics_stdio_create(SimicsStdio* stream, + SsxAddress read_address, + SsxAddress write_address, + SsxAddress flush_address) +{ + FILE* base = (FILE*)stream; + int rc; + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(stream == 0, EBADF); + } + + rc = FILE_create((FILE*)stream, 0); + + if (!rc) + { + + stream->read_address = read_address; + + if (read_address != 0) + { + base->sread = simics_stdio_sread; + } + + stream->write_address = write_address; + + if (write_address != 0) + { + base->swrite = simics_stdio_swrite; + } + + stream->flush_address = flush_address; + + if (flush_address != 0) + { + base->fflush = simics_stdio_fflush; + } + } + + return rc; +} + + +int +simics_stdin_create(SimicsStdio* stream) +{ + return simics_stdio_create(stream, SIMICS_STDIN, 0, 0); +} + + +int +simics_stdout_create(SimicsStdio* stream) +{ + return simics_stdio_create(stream, 0, SIMICS_STDOUT, SIMICS_STDOUT_FLUSH); +} + +int +simics_stderr_create(SimicsStdio* stream) +{ + return simics_stdio_create(stream, 0, SIMICS_STDERR, SIMICS_STDERR_FLUSH); +} + +int +simics_stdfile_create(SimicsStdio* stream, int fn) +{ + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((fn < 0) > (fn >= SIMICS_STDFILE_STREAMS), EBADF); + } + + return simics_stdio_create(stream, + SIMICS_STDFILE_READ(fn), + SIMICS_STDFILE_WRITE(fn), + SIMICS_STDFILE_FLUSH(fn)); +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/simics_stdio.h b/import/chips/p9/common/pmlib/ppc405lib/simics_stdio.h new file mode 100644 index 00000000..9ab2b4bb --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/simics_stdio.h @@ -0,0 +1,94 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/simics_stdio.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SIMICS_STDIO_H__ +#define __SIMICS_STDIO_H__ + +// $Id: simics_stdio.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/simics_stdio.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file simics_stdio.h +/// \brief SSX I/O implementations for Simics stdio streams + +#include "ssx_io.h" +#include "simics_stdio_addresses.h" +#include "string.h" + +/// A FILE structure for a Simics fake stdio stream + +typedef struct +{ + + /// The base class + FILE stream; + + /// The MMIO address of the Simics read port for the stream + SsxAddress read_address; + + /// The MMIO address of the Simics write port for the stream + SsxAddress write_address; + + /// The MMIO address of the Simics device for flushing the stream; + SsxAddress flush_address; + +} SimicsStdio; + +extern SimicsStdio simics_stdin; +extern SimicsStdio simics_stdout; +extern SimicsStdio simics_stderr; + +int +simics_stdio_create(SimicsStdio* stream, + SsxAddress read_address, + SsxAddress write_address, + SsxAddress flush_address); + +int +simics_stdin_create(SimicsStdio* stream); + +int +simics_stdout_create(SimicsStdio* stream); + +int +simics_stderr_create(SimicsStdio* stream); + +int +simics_stdfile_create(SimicsStdio* stream, int fn); + +int +simics_stdio_sread(FILE* stream, void* buf, size_t count, size_t* read); + +int +simics_stdio_swrite(FILE* stream, const void* buf, + size_t count, size_t* written); + +int +simics_stdio_sflush(FILE* stream); + +#endif /* __SIMICS_STDIO_H__ */ diff --git a/import/chips/p9/common/pmlib/ppc405lib/simics_stdio_addresses.h b/import/chips/p9/common/pmlib/ppc405lib/simics_stdio_addresses.h new file mode 100644 index 00000000..fe5daad3 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/simics_stdio_addresses.h @@ -0,0 +1,91 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/simics_stdio_addresses.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SIMICS_STDIO_ADDRESSES_H__ +#define __SIMICS_STDIO_ADDRESSES_H__ + +// $Id: simics_stdio_addresses.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/simics_stdio_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file simics_stdio_adresses.h +/// \brief MMIO addresses and offsets of the Simics fake stdio model +/// +/// The Simics 'stdio' component is a pseudo serial port for I/O to stdio, +/// stdout and stderr, as well as to other configurable streams. Each virtual +/// file potentially has a read port, write port and flush port. +/// +/// The write ports accept 1, 2 and 4-byte transactions on a 32-bit OCI +/// address and write the data to the associated stream. Writing any value to +/// the flush port flushes the output stream. The input ports are not yet +/// implemented. + +// -*- This header is maintained as part of the PMX Simics model. -*- +// -*- Do not edit in the SSX library as your edits will be lost. -*- + +#define SIMICS_STDIO_BASE 0x40060000 + +#define SIMICS_STDIN_OFFSET 0x00 +#define SIMICS_STDOUT_OFFSET 0x04 +#define SIMICS_STDOUT_FLUSH_OFFSET 0x08 +#define SIMICS_STDERR_OFFSET 0x0c +#define SIMICS_STDERR_FLUSH_OFFSET 0x10 + +#define SIMICS_STDFILE_0_OFFSET 0x14 +#define SIMICS_STDFILE_1_OFFSET 0x20 +#define SIMICS_STDFILE_2_OFFSET 0x2c +#define SIMICS_STDFILE_3_OFFSET 0x38 + +#define SIMICS_STDFILE_STREAMS 4 + +#define SIMICS_STDIN (SIMICS_STDIO_BASE + SIMICS_STDIN_OFFSET) +#define SIMICS_STDOUT (SIMICS_STDIO_BASE + SIMICS_STDOUT_OFFSET) +#define SIMICS_STDOUT_FLUSH (SIMICS_STDIO_BASE + SIMICS_STDOUT_FLUSH_OFFSET) +#define SIMICS_STDERR (SIMICS_STDIO_BASE + SIMICS_STDERR_OFFSET) +#define SIMICS_STDERR_FLUSH (SIMICS_STDIO_BASE + SIMICS_STDERR_FLUSH_OFFSET) + +#define SIMICS_STDFILE_READ_OFFSET(fn) \ + (SIMICS_STDFILE_0_OFFSET + (12 * fn) + 0x00) + +#define SIMICS_STDFILE_WRITE_OFFSET(fn) \ + (SIMICS_STDFILE_0_OFFSET + (12 * fn) + 0x04) + +#define SIMICS_STDFILE_FLUSH_OFFSET(fn) \ + (SIMICS_STDFILE_0_OFFSET + (12 * fn) + 0x08) + +#define SIMICS_STDFILE_READ(fn) \ + (SIMICS_STDIO_BASE + SIMICS_STDFILE_READ_OFFSET(fn)) + +#define SIMICS_STDFILE_WRITE(fn) \ + (SIMICS_STDIO_BASE + SIMICS_STDFILE_WRITE_OFFSET(fn)) + +#define SIMICS_STDFILE_FLUSH(fn) \ + (SIMICS_STDIO_BASE + SIMICS_STDFILE_FLUSH_OFFSET(fn)) + + +#endif /* __SIMICS_STDIO_ADDRESSES_H__ */ diff --git a/import/chips/p9/common/pmlib/ppc405lib/sprintf.c b/import/chips/p9/common/pmlib/ppc405lib/sprintf.c new file mode 100644 index 00000000..6011ad9c --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/sprintf.c @@ -0,0 +1,138 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/sprintf.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: sprintf.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/sprintf.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sprintf.c \brief Implementations of sprintf() and snprintf() using +/// StringStream. + +#include "ssx.h" +#include "ssx_io.h" +#include "string_stream.h" + + +// sprintf() is easy - just blindly copy in the data. + +static int +sprintf_swrite(FILE* stream, const void* buf, size_t size, size_t* written) +{ + StringStream* string = (StringStream*)stream; + + memcpy((void*)(&(string->data[string->next_write])), buf, size); + string->next_write += size; + *written = size; + return 0; +} + + +// snprintf() requires that bytes that won't fit in the array are simply +// discarded, but still accounted for. Note that vfprintf() is doing the +// high-level accounting. + +static int +snprintf_swrite(FILE* stream, const void* buf, size_t size, size_t* written) +{ + StringStream* string = (StringStream*)stream; + + size_t to_write = MIN(size, string->size - string->next_write - 1); + + memcpy((void*)(&(string->data[string->next_write])), buf, to_write); + string->next_write += to_write; + *written = size; + return 0; +} + + +// We use a StringStream to implement [v]sprintf() and [v]snprintf(). Once +// the formatting is finished the NULL terminator is added. + +int +vsprintf(char* str, const char* format, va_list argp) +{ + ssize_t rc; + StringStream stream; + + _string_stream_create(&stream, str, 1, 0, sprintf_swrite); + rc = vfprintf((FILE*)(&stream), format, argp); + stream.data[stream.next_write] = 0; + return rc; +} + + + +int +sprintf(char* str, const char* format, ...) +{ + va_list argp; + ssize_t rc; + + va_start(argp, format); + rc = vsprintf(str, format, argp); + va_end(argp); + + return rc; +} + + +int +vsnprintf(char* str, size_t size, const char* format, va_list argp) +{ + ssize_t rc; + StringStream stream; + + if (size == 0) + { + return 0; + } + + _string_stream_create(&stream, str, size, 0, snprintf_swrite); + rc = vfprintf((FILE*)(&stream), format, argp); + stream.data[stream.next_write] = 0; + return rc; +} + + +int +snprintf(char* str, size_t size, const char* format, ...) +{ + va_list argp; + ssize_t rc; + + if (size == 0) + { + return 0; + } + + va_start(argp, format); + rc = vsnprintf(str, size, format, argp); + va_end(argp); + + return rc; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/ssx_dump.c b/import/chips/p9/common/pmlib/ppc405lib/ssx_dump.c new file mode 100644 index 00000000..bbd82e71 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ssx_dump.c @@ -0,0 +1,245 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ssx_dump.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: ssx_dump.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_dump.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_dump.c +/// \brief Routines for dumping SSX kernel data structures +/// +/// \note This is a quick hack to help solve a P8 bringup issue. This code is +/// PPC405 (OCC) specific, i.e., not "portable" SSX. Ideally this type of dump +/// would be implemented in an external debugging tool as well, however it's +/// simplest to implement here in the execution context. + +#include "ssx_dump.h" + +#define SSX_DUMP_UNIMPLEMENTED 0x00d86701 + +static const char* _threadState[] = +{ + 0, + "Suspended Runnable", + "Mapped", + "Suspended Blocked", + "Completed", + "Deleted", +}; + +static const char* _threadFlags[] = +{ + 0, + "Semaphore Pend", + "Timer Pend", + "Timer Pend | Semaphore Pend", + "Timed Out", + "Timed Out | Semaphore Pend", + "Timed Out | Timer Pend", + "Timed Out | Timer Pend | Semaphore Pend", +}; + + +static void +_dumpTimer(FILE* stream, SsxTimer* timer) +{ + fprintf(stream, + "-- Timer @ %p\n" + "-- Deque.previous = %p\n" + "-- Deque.next = %p\n" + "-- Timeout = 0x%016llx\n" + "-- Period = 0x%016llx\n" + "-- Callback = %p\n" + "-- Arg = %p\n" + "-- Options = 0x%02x\n", + timer, + timer->deque.previous, + timer->deque.next, + timer->timeout, + (unsigned long long)(timer->period), + timer->callback, + timer->arg, + timer->options); +} + + +static void +_dumpThread(FILE* stream, SsxThread* thread) +{ + SsxThreadContext* threadCtx; + SsxThreadContextFullIrq* threadCtxIrq; + uint32_t srr[4], lr, sp; + + fprintf(stream, + "-- Thread mapped at priority %d (%p)\n" + "-- Thread state = %s (%d)\n" + "-- Thread flags = %s (0x%02x)\n" + "-- Saved Stack Pointer = %p\n", + thread->priority, thread, + _threadState[thread->state], thread->state, + _threadFlags[thread->flags], thread->flags, + (void*)thread->saved_stack_pointer); + + if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) + { + + fprintf(stream, + "-- Semaphore = %p\n", + (void*)thread->semaphore); + } + + fprintf(stream, + "---------------------------------------------\n"); + + if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) + { + + _dumpTimer(stream, &(thread->timer)); + fprintf(stream, + "---------------------------------------------\n"); + } + + if ((thread == ssx_current()) && !__ssx_kernel_context_any_interrupt()) + { + + fprintf(stream, + "-- This thread is executing ssx_dump()\n"); + + } + else + { + + if (thread == ssx_current()) + { + + // This is the interrupted thread, and only has its volatile + // context saved. The thread stack pointer is stored in a global + // kernel variable. + + if (__ssx_kernel_context_critical_interrupt()) + { + + SSX_PANIC(SSX_DUMP_UNIMPLEMENTED); + srr[0] = srr[1] = srr[2] = srr[3] = lr = sp = 0; /* For GCC */ + + } + else + { + + threadCtxIrq = + (SsxThreadContextFullIrq*)__ssx_saved_sp_noncritical; + srr[0] = threadCtxIrq->srr0; + srr[1] = threadCtxIrq->srr1; + srr[2] = threadCtxIrq->srr2; + srr[3] = threadCtxIrq->srr3; + lr = threadCtxIrq->lr; + sp = threadCtxIrq->r1; + } + } + else + { + + // This is a fully swapped-out thread. The context is saved in + // at the stored stack pointer. + + threadCtx = (SsxThreadContext*)(thread->saved_stack_pointer); + srr[0] = threadCtx->srr0; + srr[1] = threadCtx->srr1; + srr[2] = threadCtx->srr2; + srr[3] = threadCtx->srr3; + lr = threadCtx->lr; + sp = ((uint32_t*)threadCtx->r1)[0]; + } + + fprintf(stream, + "-- SRR0: 0x%08x SRR1: 0x%08x " + "SRR2: 0x%08x SRR3: 0x%08x\n" + "-- LR: 0x%08x\n", + srr[0], srr[1], srr[2], srr[3], + lr); + + fprintf(stream, + "---------------------------------------------\n"); + + // Unwind the stack + + while (sp != 0) + { + + fprintf(stream, + "-- SP: 0x%08x *LR*:0x%08x\n", + sp, ((uint32_t*)sp)[1]); + sp = ((uint32_t*)sp)[0]; + } + } +} + + + + +void +ssx_dump(FILE* stream, int options) +{ + int i, sep; + SsxThread* thread; + + fprintf(stream, + "------------------------------------------------------------\n"); + fprintf(stream, + "-- SSX Kernel Dump @ 0x%016llx\n" + "-- USPRG0 = 0x%08x\n" + "-- __ssx_run_queue = 0x%08x\n", + ssx_timebase_get(), + mfspr(SPRN_USPRG0), + __ssx_run_queue); + fprintf(stream, + "------------------------------------------------------------\n"); + + sep = 0; + + for (i = 0; i < SSX_THREADS; i++) + { + + ssx_thread_at_priority(i, &thread); + + if (thread) + { + if (sep) + { + fprintf(stream, + "*********************************************\n"); + } + + _dumpThread(stream, thread); + sep = 1; + } + } + + fprintf(stream, + "------------------------------------------------------------\n"); +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/ssx_dump.h b/import/chips/p9/common/pmlib/ppc405lib/ssx_dump.h new file mode 100644 index 00000000..2be84bae --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ssx_dump.h @@ -0,0 +1,82 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ssx_dump.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SSX_DUMP_H__ +#define __SSX_DUMP_H__ + +// $Id: ssx_dump.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_dump.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_dump.h +/// \brief Routines for dumping SSX kernel data structures + +#include "ssx.h" + +/// \defgroup ssx_dump_options Options for ssx_dump() +/// +/// No options are currently specified. +/// +/// @{ + +/// @} + +#ifndef __ASSEMBLER__ + + /// Dump the kernel state + /// + /// \param i_stream The stream to receive the dump. If the dump is being + /// generated prior to a kernel panic then this would typically be \a ssxout, + /// the stream used by printk. + /// + /// \param i_options AN OR-mask of option flags; See \ref ssx_dump_options + /// + /// The SSX kernel dump produces a formatted snapshot of the state of the + /// kernel and the mapped threads. This API does not manipulate the machine + /// context; If it is required to produce a precise snapshot then the caller + /// will need to make the call from a critical section. + /// + /// The following information is standard in the dump + /// + /// - The interrupt and thread state of the kernel + /// - The state of each thread + /// - A stack trace for each thread + /// + /// Options : TBD + /// + /// \bug There are likely several bugs in the current implementation due to + /// the assumption that the code is being called from a state in which the + /// kernel context is not changing. We don't have time to code and test the + /// most general implementation now. To guarantee correct operation the API + /// must currently be called from an SSX_CRITICAL critical section. + void + ssx_dump(FILE* stream, int options); + +#endif // __ASSEMBLER__ + +#endif // __SSX_DUMP_H__ diff --git a/import/chips/p9/common/pmlib/ppc405lib/ssx_io.c b/import/chips/p9/common/pmlib/ppc405lib/ssx_io.c new file mode 100644 index 00000000..adf67770 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ssx_io.c @@ -0,0 +1,363 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ssx_io.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: ssx_io.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_io.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_io.c +/// \brief SSX analog-replacement for C \<stdio.h\> and \<unistd.h\> functions +/// +/// The SSX library provides simple analogs for I/O functions found in the +/// typical C libraries and Posix standards. I/O is not considered part of the +/// SSX kernel per-se - I/O is implemented by the application creating I/O +/// abstractions and drivers using the simple SSX kernel services. [However, +/// the ssx_io library does provide a printk() function for use by kernel +/// drivers, so the lines are not completely clear.] +/// +/// This library provides a FILE structure or 'base class' to represent a +/// character stream. Abstractions for different devices will 'derive' a +/// subclass from this base class by including the FILE as the first member of +/// the subclass, and then likely adding more data members. The FILE +/// structure contains pointers to the routines that implement I/O operations +/// for derived classes. There is no requiremengt that a stream type implement +/// every possible stream operation. If an unsupported operation is invoked +/// on a stream then the call will simply return -ENXIO, unless otherwise +/// specified. +/// +/// The generic I/O calls use the same error-handling protocol as used by the +/// SSX kernel services. A configuration setting (\c SSX_ERROR_CHECK_API) +/// determines if error checks are made at all, and another setting (\c +/// SSX_ERROR_PANIC) determines whether the presence of a fatal error causes a +/// bad return code or an immediate panic. +/// +/// The following errors are never considered fatal errors: +/// +/// \b EOF Used to signal end-of-file +/// +/// \b EAGAIN Used to signal that an operation was made to a non-blocking +/// stream and the call would block. +/// +/// Following are the specifications and requirements for the stream methods +/// that implement a stream type. +/// +/// <b> int sread(FILE *stream, void *buf, size_t count, size_t *read) </b> +/// +/// The low-level read() function is named sread() here due to differences in +/// the prototype and semantics from the Unix counterpart. The sread() +/// functions attempts to read \a count bytes from the \a stream into \a buf, +/// sets the number of bytes read, and returns either 0 for success or a +/// negative error code. The only reason that sread() may terminate without +/// reading \a count bytes is if sread() also returns a negative return +/// code. +/// +/// The device-specific sread() function may assume that the \a stream, \a buf +/// and \a read parameters are non-NULL at entry, and the \a count is greater +/// than 0. These conditions are checked/guaranteed by the generic interface. +/// +/// <b> int swrite(FILE *stream, void *buf, size_t count, size_t *written) </b> +/// +/// The low-level write() function is named swrite() here due to differences +/// in the prototype and semantics from the Unix counterpart. The swrite() +/// function attempts to writes \a count bytes from buf to the \a stream, sets +/// the number of bytes written, and returns either 0 for success or a +/// negative error code. The only reason that swrite() may terminate without +/// writing \a count bytes is if write() also returns a negative return +/// code. +/// +/// The device-specific swrite() function may assume that the \a stream, \a +/// buf and \a written parameters are non-NULL at entry, and the \a count is +/// greater than 0. These conditions are checked/guaranteed by the generic +/// interface. +/// +/// <b> int fflush(FILE *stream) </b> +/// +/// SSX implements the fflush() call, even though the semantics are slightly +/// different from the Posix standard. The Posix fflush() returns either 0 +/// for success, or EOF to indicate an error. Here, fflush() returns negative +/// 'errno' codes directly in the event of errors. The Posix standard +/// specifies that calling fflush() with a NULL \a stream causes all open +/// files to be flushed - here it returns the -EBADF error. +/// +/// The stream-specific fflush() implementation should return one of the +/// 'errno' codes specified by the Posix standard in the event of +/// problems. + +#include "ssx.h" +#include "ssx_io.h" + +/// Initialize an SSX I/O FILE structure +/// +/// \param file A pointer to an uninitialized FILE +/// +/// \param flags Flags for the generic FILE +/// +/// This API is designed to be called from "constructors of classes derived +/// from FILE", e.g., the StringStream. The generic FILE structure is +/// cleared, and the flags are installed and other initialization based on the +/// flags is performed. The subclass constructors then install function +/// pointers for any of the FILE functions that they implement. +/// +/// \retval 0 Success +/// +/// \retval -FILE_INVALID_OBJECT The \a file pointer is null (0). +/// +/// \retval -FILE_INVALID_ARGUMENT The \a flags are not valid. + +int +FILE_create(FILE* file, int flags) +{ + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(file == 0, FILE_INVALID_OBJECT); + SSX_ERROR_IF(flags & ~SSX_FILE_VALID_FLAGS, FILE_INVALID_ARGUMENT); + SSX_ERROR_IF(__builtin_popcount(flags & SSX_FILE_OP_LOCK_OPTIONS) > 1, + FILE_INVALID_ARGUMENT); + } + + memset((void*)file, 0, sizeof(FILE)); + file->flags = flags; + ssx_semaphore_create(&(file->fop_sem), 1, 1); + return 0; +} + + +/// Assign an error code to a stream, returning a non-zero value for errors +/// considered fatal. + +int +ssx_io_error_set(FILE* stream, int code) +{ + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(stream == 0, EBADF); + } + + stream->error = code; + + if ((code == EOF) || + (code == EAGAIN)) + { + return 0; + } + else + { + return -1; + } +} + + +static int +null_stream_sread(FILE* stream, void* buf, size_t count, size_t* read) +{ + *read = 0; + ssx_io_error_set(stream, EOF); + return EOF; +} + + +static int +null_stream_swrite(FILE* stream, const void* buf, size_t count, size_t* written) +{ + *written = count; + return 0; +} + + +static int +null_stream_fflush(FILE* stream) +{ + return 0; +} + + +/// A null stream; equivalent to Unix /dev/null +/// +/// This stream is statically initialized as it is required to be assigned to +/// \a ssxout at load time. The NULL stream does not require any locking. + +FILE _null_stream = +{ + .sread = null_stream_sread, + .swrite = null_stream_swrite, + .fflush = null_stream_fflush, + .error = 0, + .flags = 0 +}; + + +// It's up to the application to initialize the standard streams if it wishes +// to use them. Reading or writing a NULL stream will signal an error. + +FILE* stdin = 0; +FILE* stdout = 0; +FILE* stderr = 0; + +/// Stream used by printk() +/// +/// \a ssxout is the stream used by printk(). \a ssxout \e must be assigned +/// to a non-blocking stream as it may be called from interrupt handlers. \a +/// ssxout defaults to _null_stream, the equivalent of Unix' /dev/null. + +FILE* ssxout = &_null_stream; + + +/// /dev/null for SSX +FILE* ssxnull = &_null_stream; + + +/// Lock low-level file operations +/// +/// The decision on if and how low-level FILE operations needs to be locked is +/// made by the class derived from FILE, and may also require an argument +/// about its intended use. The minimum bar is always correctness. The next +/// bar is whether the application allows data from multiple writers to be +/// intermixed, or allows multiple readers to access the same input stream. +/// +/// A device like the StringStream used to implement sprintf() and snprintf() +/// does not require locking at all because it is only called from a single +/// context. String streams that implement circular buffers must be locked if +/// there is the possibility of multiple readers or writers, and the wrapping +/// buffer always needs to be locked. +/// +/// The lock implemented here is a lock on the low-level stream operations +/// sread(), swrite() and fflush(). + +#define LOCK_FILE_OPERATION(stream, operation) \ + ({ \ + int __rc; \ + SsxMachineContext __ctx = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; /* GCC */ \ + if ((stream)->flags & SSX_FILE_OP_LOCK_OPTIONS) { \ + if ((stream)->flags & SSX_FILE_OP_LOCK_CRITICAL) { \ + ssx_critical_section_enter(SSX_CRITICAL, &__ctx); \ + } else if ((stream)->flags & SSX_FILE_OP_LOCK_NONCRITICAL) { \ + ssx_critical_section_enter(SSX_NONCRITICAL, &__ctx); \ + } else { \ + ssx_semaphore_pend(&((stream)->fop_sem), SSX_WAIT_FOREVER); \ + } \ + } \ + __rc = (operation); \ + if ((stream)->flags & SSX_FILE_OP_LOCK_OPTIONS) { \ + if ((stream)->flags & (SSX_FILE_OP_LOCK_CRITICAL | \ + SSX_FILE_OP_LOCK_NONCRITICAL)) { \ + ssx_critical_section_exit(&__ctx); \ + } else { \ + ssx_semaphore_post(&((stream)->fop_sem)); \ + } \ + } \ + __rc; \ + }) + + +/// Call the sread() operation of a stream + +int +sread(FILE* stream, void* buf, size_t count, size_t* read) +{ + ssize_t rc; + size_t _read; + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((stream == 0), EBADF); + SSX_IO_ERROR_IF(stream, (stream->sread == 0), ENXIO); + SSX_IO_ERROR_IF(stream, (buf == 0), EINVAL); + } + + if (count == 0) + { + if (read != 0) + { + *read = 0; + } + + return 0; + } + + rc = LOCK_FILE_OPERATION(stream, stream->sread(stream, buf, count, &_read)); + + if (read != 0) + { + *read = _read; + } + + return rc; +} + + +/// Call the swrite() operation of a stream + +ssize_t +swrite(FILE* stream, const void* buf, size_t count, size_t* written) +{ + ssize_t rc; + size_t _written; + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((stream == 0), EBADF); + SSX_IO_ERROR_IF(stream, (stream->swrite == 0), ENXIO); + SSX_IO_ERROR_IF(stream, (buf == 0), EINVAL); + } + + if (count == 0) + { + rc = 0; + _written = 0; + } + else + { + rc = LOCK_FILE_OPERATION(stream, + stream->swrite(stream, buf, count, &_written)); + } + + if (written != 0) + { + *written = _written; + } + + return rc; +} + + +/// Call the fflush() operation of the stream + +int +fflush(FILE* stream) +{ + int rc; + + if (SSX_ERROR_CHECK_API) + { + SSX_IO_ERROR_IF(stream, (stream == 0), EBADF); + SSX_IO_ERROR_IF(stream, (stream->fflush == 0), ENXIO); + } + + rc = LOCK_FILE_OPERATION(stream, stream->fflush(stream)); + return rc; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/ssx_io.h b/import/chips/p9/common/pmlib/ppc405lib/ssx_io.h new file mode 100644 index 00000000..c6ef55d8 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/ssx_io.h @@ -0,0 +1,229 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/ssx_io.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SSX_IO_H__ +#define __SSX_IO_H__ + +// $Id: ssx_io.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/ssx_io.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_io.h +/// \brief SSX analog-replacement for C <stdio.h> and <unistd.h> functions + +#if !defined(_STDIO_H) && !defined(_UNISTD_H) + +#include "ssx_macros.h" +#include "ssx_api.h" + +#include "ctype.h" +#include "errno.h" +#include "string.h" + +#define EOF -1 + +#define FILE_INVALID_OBJECT 0x00345301 +#define FILE_INVALID_ARGUMENT 0x00345302 + +#ifndef __ASSEMBLER__ + +#include <stdarg.h> + +/// The SSX implementation of the FILE structure + +typedef struct FILE +{ + + /// The sread() method + int (*sread)(struct FILE* stream, void* buf, + size_t count, size_t* read); + + /// The swrite() method + int (*swrite)(struct FILE* stream, const void* buf, + size_t count, size_t* written); + + /// The fflush() method + int (*fflush)(struct FILE* stream); + + /// The last error code encountered + /// + /// This field is not set in the event of an error panic. + int error; + + /// SSX file/stream flags; See \ref ssx_file_flags + int flags; + + /// The semaphore used to lock low-level file operations if required. + SsxSemaphore fop_sem; + + /// The number of newline characters read by fgetc. + /// + /// This variable supports an SSX extension to <stdio.h>, the flines() + /// API. flines() returns the number of newline characters read by + /// fgetc(). This counter does not count newline characters read using + /// sread() on the stream directly. + size_t lines; + + /// The character pushed back by ungetc() + /// + /// If a character is back the flag SSX_FILE_HAS_CHARACTER will be + /// set. Note that characters pushed back with ungetc() are not returned + /// by any subsequent sread() call on the stream, so it is best not to mix + /// sread() and fgetc(). + unsigned char character; + +} FILE; + + +/// \defgroup ssx_file_flags SSX File/Stream Flags +/// @{ + +/// Low-level access is locked by an SSX_CRITICAL critical section +#define SSX_FILE_OP_LOCK_CRITICAL 0x1 + +/// Low-level access is locked by an SSX_NONCRITICAL critical section +#define SSX_FILE_OP_LOCK_NONCRITICAL 0x2 + +/// Low-level access is locked by a semaphore +#define SSX_FILE_OP_LOCK_SEMAPHORE 0x4 + +/// Mask of all locking options; +#define SSX_FILE_OP_LOCK_OPTIONS 0x7 + +/// The FILE has a character pushed back by ungetc() +#define SSX_FILE_HAS_CHARACTER 0xf + +/// All valid flags +#define SSX_FILE_VALID_FLAGS 0xf + +/// @} + + +extern FILE* stdin; +extern FILE* stdout; +extern FILE* stderr; + +/// SSX kernel output stream +/// +/// This stream implements the printk() API. It must be a non-blocking stream +/// so that it can be used in interrupt contexts. + +extern FILE* ssxout; + +extern FILE* ssxnull; + +int +FILE_create(FILE* stream, int flags); + +int +sread(FILE* stream, void* buf, size_t count, size_t* read); + +int +swrite(FILE* stream, const void* buf, size_t count, size_t* written); + +int +fflush(FILE* stream); + +int +vfprintf(FILE* stream, const char* format, va_list argp) +__attribute__ ((format (printf, 2, 0))); + +int +vprintf(const char* format, va_list argp) +__attribute__ ((format (printf, 1, 0))); + +int +fprintf(FILE* stream, const char* fmt, ...) +__attribute__ ((format (printf, 2, 3))); + +int +printf(const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); + +int +printk(const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); + +int +vsprintf(char* str, const char* format, va_list argp) +__attribute__ ((format (printf, 2, 0))); + +int +sprintf(char* str, const char* format, ...) +__attribute__ ((format (printf, 2, 3))); + +int +vsnprintf(char* str, size_t size, const char* format, va_list argp) +__attribute__ ((format (printf, 3, 0))); + +int +snprintf(char* str, size_t size, const char* format, ...) +__attribute__ ((format (printf, 3, 4))); + +int +fputc(int c, FILE* stream); + +int +fputs(const char* s, FILE* stream); + +int +puts(const char* s); + +int +putchar(int c); + +int +fgetc(FILE* stream); + +int +ungetc(int c, FILE* stream); + +size_t +flines(FILE* stream); + +int +ssx_io_error_set(FILE* stream, int code); + +/// Handle I/O errors including panic configurations +#define SSX_IO_ERROR_IF(stream, condition, code) \ + do { \ + if (condition) { \ + if (ssx_io_error_set(stream, code) && SSX_ERROR_PANIC) { \ + SSX_PANIC(code); \ + } else { \ + return -(code); \ + } \ + } \ + } while (0) + +#define SSX_IO_ERROR(stream, code) SSX_IO_ERROR_IF((stream), 1, (code)) + + +#endif /* __ASSEMBLER__ */ + +#endif /* !defined(_STDIO_H) && !defined(_UNISTD_H) */ + +#endif /* __SSX_IO_H__ */ diff --git a/import/chips/p9/common/pmlib/ppc405lib/stdlib.c b/import/chips/p9/common/pmlib/ppc405lib/stdlib.c new file mode 100644 index 00000000..3242cda4 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/stdlib.c @@ -0,0 +1,115 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/stdlib.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: stdlib.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/stdlib.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file stdlib.c +/// \brief Functions from <stdlib.h> +/// +/// \note The strtoX() APIs are defined in strtox.[ch] + +#include "ssx.h" +#include "ctype.h" +#include "libssx.h" +#include <stdlib.h> + + +/// Convert a string to a long integer - base 10 only +/// +/// atol(str) is defined here as strtol(str, 0, 10) in sympathy with the POSIX +/// standard. Note that by specification "atol() does not detect +/// errors", however here it will behave the same as the strtol() call just +/// mentioned. + +long +atol(const char* str) +{ + return strtol(str, 0, 10); +} + + +/// Convert a string to an integer - base 10 only +/// +/// atoi(str) is defined here as strtol(str, 0, 10) in sympathy with the POSIX +/// standard. Note that by specification "atoi() does not detect errors", +/// however in this implementation the long integer returned by the strtol() +/// call just mentioned is simply converted to an int. + +int +atoi(const char* str) +{ + return strtol(str, 0, 10); +} + + +/// 'Exit' an application +/// +/// An SSX application can not really 'exit'. By convention, exit(0) is the +/// same as ssx_halt(). Calling exit() with a non-zero code causes a kernel +/// panic - the exit code will be found in R3 on PowerPC. +/// +/// Note that to exit a thread, the thread can either return from the thread +/// entry routine or explicitly call ssx_complete(). exit() was implemented +/// to allow porting of the EEMBC benchmarks. + +void +exit(int status) +{ + if (status) + { + SSX_PANIC(ERROR_EXIT); + } + + ssx_halt(); +} + + +/// Compute the absolute value of the integer argument +int +abs(int i) +{ + return ((i < 0) ? -i : i); +} + + +/// Compute the absolute value of the long integer argument +long int +labs(long int i) +{ + return ((i < 0) ? -i : i); +} + + +/// Compute the absolute value of the long long integer argument +long long int +llabs(long long int i) +{ + return ((i < 0) ? -i : i); +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/strcasecmp.c b/import/chips/p9/common/pmlib/ppc405lib/strcasecmp.c new file mode 100644 index 00000000..59c94183 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/strcasecmp.c @@ -0,0 +1,102 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/strcasecmp.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: strcasecmp.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strcasecmp.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file strcasecmp.c +/// \brief Implementation of strcasecmp() and strncasecmp() +/// +/// These routines are rarely used, hence broken out into a separate file to +/// save code space for most applications. + +#include "ssx.h" +#include "string.h" + +/// Compare two strings ignoring case +/// +/// The strcasecmp() function compares the two strings \a s1 and \a s2, +/// ignoring the case of the characters. It returns an integer less than, +/// equal to, or greater than zero if \a s1 is found, respectively, to be less +/// than, to match, or be greater than \a s2. + +int +strcasecmp(const char* s1, const char* s2) +{ + int rc; + + if (s1 == s2) + { + rc = 0; + } + else + { + while(*s1 && (tolower(*s1) == tolower(*s2))) + { + s1++; + s2++; + } + + rc = *((unsigned char*)s1) - *((unsigned char*)s2); + } + + return rc; +} + + +/// Compare a portion of two strings ignoring case +/// +/// The strncmp() function compares at most the first \n characters of the two +/// strings \a s1 and \a s2, ignoring the case of the characters. It returns +/// an integer less than, equal to, or greater than zero if (the prefix of) \a +/// s1 is found, respectively, to be less than, to match, or be greater than +/// (the prefix of) \a s2. + +int +strncasecmp(const char* s1, const char* s2, size_t n) +{ + int rc; + + if ((s1 == s2) || (n == 0)) + { + rc = 0; + } + else + { + while(*s1 && (tolower(*s1) == tolower(*s2)) && n--) + { + s1++; + s2++; + } + + rc = *((unsigned char*)s1) - *((unsigned char*)s2); + } + + return rc; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/strdup.c b/import/chips/p9/common/pmlib/ppc405lib/strdup.c new file mode 100644 index 00000000..996c7c99 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/strdup.c @@ -0,0 +1,66 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/strdup.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: strdup.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strdup.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file strdup.c +/// \brief Functions from <string.h> that require malloc() +/// +/// These APIs are split from string.c for the benefit of applications like +/// OCC FW that don't use malloc(). + +#include <stdlib.h> +#include <string.h> + +/// Duplicate a string +/// +/// \param s The string to duplicate +/// +/// The strdup() function returns a pointer to a new string which is a +/// duplicate of the input string \a s. Memory for the new string is obtained +/// with malloc(), and can be freed with free(). +/// +/// \returns The strdup() function returns a pointer to the duplicated string, +/// or NULL (0) if insufficient memory was available. + +char* +strdup(const char* s) +{ + char* dup; + + dup = (char*)malloc(strlen(s) + 1); + + if (dup != 0) + { + strcpy(dup, s); + } + + return dup; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/string_stream.c b/import/chips/p9/common/pmlib/ppc405lib/string_stream.c new file mode 100644 index 00000000..6bbf9b43 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/string_stream.c @@ -0,0 +1,477 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/string_stream.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: string_stream.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/string_stream.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file string_stream.c +/// \brief Implementations of string streams. +/// +/// \bug Need to work out overwrite/multiple-write protection. + +#include "ssx.h" +#include "string_stream.h" + + +// 'Flush' a string stream by making it empty + +static int +string_stream_fflush(FILE* stream) +{ + StringStream* string = (StringStream*) stream; + + string->next_read = 0; + string->next_write = 0; + string->flags &= ~STRING_STREAM_FULL; + return 0; +} + + +// Read the remaining tail (if any) of the circular buffer, assuming the +// buffer is not empty. + +static size_t +read_tail(StringStream* string, void* buf, size_t size) +{ + size_t read, remainder; + + read = 0; + + if (string->next_read >= string->next_write) + { + + remainder = string->size - string->next_read; + read = MIN(size, remainder); + memcpy(buf, (void*)(&(string->data[string->next_read])), read); + + if (read != remainder) + { + string->next_read += read; + } + else + { + string->next_read = 0; + } + } + + return read; +} + + +// Read the area (if any) from the read pointer to the write pointer + +static size_t +read_head(StringStream* string, void* buf, size_t size) +{ + size_t read, remainder; + + read = 0; + + if (string->next_write > string->next_read) + { + + remainder = string->next_write - string->next_read; + read = MIN(size, remainder); + memcpy(buf, (void*)(&(string->data[string->next_read])), read); + string->next_read += read; + } + + return read; +} + + +// Read as much data as possible from a circular buffer. Return -EAGAIN if the +// buffer would underflow. + +static int +string_stream_sread(FILE* stream, void* buf, size_t size, size_t* read) +{ + StringStream* string = (StringStream*)stream; + size_t were_read; + int rc; + + if ((string->next_read == string->next_write) && + !(string->flags & STRING_STREAM_FULL)) + { + were_read = 0; + } + else + { + were_read = read_tail(string, buf, size); + + if (were_read != size) + { + were_read += read_head(string, buf + were_read, size - were_read); + } + } + + if (were_read != 0) + { + string->flags &= ~STRING_STREAM_FULL; + } + + *read = were_read; + + if (were_read < size) + { + rc = -EAGAIN; + } + else + { + rc = 0; + } + + return rc; +} + + + + +// Write the remaining tail (if any) of the circular buffer, assuming the +// buffer is not full. + +static size_t +write_tail(StringStream* string, const void* buf, size_t size) +{ + size_t written, remainder; + + written = 0; + + if (string->next_write >= string->next_read) + { + + remainder = string->size - string->next_write; // string->size is the size of the stream(our buffer) + written = MIN(size, remainder); + // memcpy(void *dest, const void *src, size_t n) from /lib/memcpy.c + memcpy((void*)(&(string->data[string->next_write])), buf, written); + + if (written != remainder) + { + string->next_write += written; + } + else + { + string->next_write = 0; + } + } + + return written; +} + +// Write the area (if any) from the write pointer to the read pointer + +static size_t +write_head(StringStream* string, const void* buf, size_t size) +{ + size_t written, remainder; + + written = 0; + + if (string->next_read > string->next_write) + { + + remainder = string->next_read - string->next_write; + written = MIN(size, remainder); + memcpy((void*)(&(string->data[string->next_write])), buf, written); + string->next_write += written; + } + + return written; +} + + +// Write as much data as possible to a circular buffer. Return -EAGAIN if the +// buffer would overflow. + +static int +circular_swrite(FILE* stream, const void* buf, size_t size, size_t* written) +{ + StringStream* string = (StringStream*)stream; + size_t wrote; + int rc; + + if (string->flags & STRING_STREAM_FULL) + { + wrote = 0; + } + else + { + wrote = write_tail(string, buf, size); + + if (wrote != size) + { + wrote += write_head(string, buf + wrote, size - wrote); + } + } + + if ((wrote != 0) && (string->next_read == string->next_write)) + { + string->flags |= STRING_STREAM_FULL; + } + + *written = wrote; + + if (wrote < size) + { + rc = -EAGAIN; + } + else + { + rc = 0; + } + + return rc; +} + + +// Effectively write all data to a circular buffer with wrapping semantics. + +static int +wrapping_swrite(FILE* stream, const void* buf, size_t size, size_t* written) +{ + StringStream* string = (StringStream*)stream; + size_t wrote; + int rc; + + if (size >= string->size) // If size of data >= size of buffer + { + + // If the amount of data will fill or overflow the entire buffer size + // then we effectively fill the buffer with the final bytes of data. + + string->next_read = 0; + string->next_write = 0; + string->flags |= STRING_STREAM_FULL; + memcpy((void*)string->data, buf + (size - string->size), size); + + } + else + { + + // If the string is not full, try to fill it with the + // circular_swrite(). + + if (string->flags & STRING_STREAM_FULL) + { + wrote = 0; + rc = -EAGAIN; + } + else + { + rc = circular_swrite(stream, buf, size, &wrote); + } + + if (rc) + { + + // The string is full and we need to overflow. We know that size + // is less than the buffer size, and the next_read == next_write. + // Mark the stream not full so a new circular write will work, and + // at the end reset the full condition. + + string->flags &= ~STRING_STREAM_FULL; + rc = circular_swrite(stream, buf + wrote, size - wrote, &wrote); + + if (rc) + { + SSX_PANIC(STRING_STREAM_BUG); + } + + string->next_read = string->next_write; + string->flags |= STRING_STREAM_FULL; + } + } + + *written = size; + return 0; +} + + +static int +linear_swrite(FILE* stream, const void* buf, size_t size, size_t* written) +{ + // buf and size correspond to the data we are passing to our own buffer + uint32_t bit_0_mask = 0x80000000; + StringStream* string = (StringStream*)stream; + size_t wrote = 0; // right aligned + // int rc; + uint32_t num_bytes_written; + // uint32_t register_contents; + + + //if (wrote != size) { + // register_contents = in32(PMC_PORE_SCRATCH_REG1); + // register_contents = register_contents & bit_0_mask; + + //if (!register_contents) { + // Before writing to SRAM, flush everything so it will write to the top + // of the buffer each time + string_stream_fflush(stream); + + // Write printk statement to SRAM + // wrote will contain the number of bytes written + + wrote += write_tail(string, buf + wrote, size - wrote); + // if wrote != size, tell Tcl to read the whole buffer, When Tcl is done loop back to write_tail + // buf= buf+wrote + // size= size - wrote + // continue loop until size = 0 + + // Sync + eieio(); + + // Store "wrote" to register + // Set bit 0 to 1 + // out32(addr, data) + num_bytes_written = (uint32_t)wrote | bit_0_mask; + out32( PMC_PORE_SCRATCH_REG1 , num_bytes_written ); + + // Sync + eieio(); + //} + //} + + // outside of loop, set *written = wrote (which is equal to size once all data has been copied to our buffer) + *written = wrote; + return 0; + +} + + +int +_string_stream_create(StringStream* stream, + void* buf, size_t size, int flags, + int (*swrite)(FILE* stream, + const void* buf, + size_t size, + size_t* written)) +{ + FILE* file = (FILE*)stream; + int rc; + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((stream == 0) || + ((buf == 0) && (size != 0)), + STRING_STREAM_INVALID_ARGUMENT); + } + + rc = FILE_create(file, flags); + + if (!rc) + { + file->swrite = swrite; + file->sread = string_stream_sread; + file->fflush = string_stream_fflush; + stream->data = buf; + stream->size = size; + stream->next_read = 0; + stream->next_write = 0; + stream->flags = 0; + } + + return rc; +} + + +int +circular_stream_create(CircularStream* stream, + void* buf, size_t size, int flags) +{ + return _string_stream_create(stream, buf, size, flags, circular_swrite); +} + + +int +wrapping_stream_create(CircularStream* stream, + void* buf, size_t size, int flags) +{ + return _string_stream_create(stream, buf, size, flags, wrapping_swrite); +} + + +int +linear_stream_create(CircularStream* stream, + void* buf, size_t size, int flags) +{ + FILE* file = (FILE*)stream; + int rc; + + rc = _string_stream_create(stream, buf, size, flags, linear_swrite); + + if (!rc) + { + + file->sread = NULL; + // Write to register where location of buffer is + out32( PMC_PORE_SCRATCH_REG1, (uint32_t)buf); + } + + return rc; +} + + +// InputStream uses string_stream_sread(), however returns EOF once all data +// has been read. + +static int +input_stream_sread(FILE* stream, void* buf, size_t size, size_t* read) +{ + int rc; + + rc = string_stream_sread(stream, buf, size, read); + + if (rc == -EAGAIN) + { + rc = EOF; + } + + return rc; +} + + +// For simplicity (and ease of maintainence) we create a normal string stream +// then overwrite a few key fields. + +int +input_stream_create(StringStream* stream, void* buf, size_t size, int flags) +{ + int rc; + + rc = _string_stream_create(stream, buf, size, flags, 0); + + if (!rc) + { + stream->stream.sread = input_stream_sread; + stream->stream.fflush = 0; + stream->flags = STRING_STREAM_FULL; + } + + return rc; +} diff --git a/import/chips/p9/common/pmlib/ppc405lib/string_stream.h b/import/chips/p9/common/pmlib/ppc405lib/string_stream.h new file mode 100644 index 00000000..07658153 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/string_stream.h @@ -0,0 +1,278 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/string_stream.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __STRING_STREAM_H__ +#define __STRING_STREAM_H__ + +// $Id: string_stream.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/string_stream.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file string_stream.h +/// \brief Implementations of string streams. + +#include "ssx_io.h" + +/// A string stream +/// +/// This structure is used for the public CircularStream and WrappingStream +/// types, as well as for the library-internal types used to implement +/// sprintf() and snprintf(). + +typedef struct +{ + + /// The base class + FILE stream; + + /// Data storage - provided by the creator + uint8_t* data; + + /// The size of the data storage + size_t size; + + /// The index of the next byte to write + size_t next_write; + + /// The index of the next byte to read + size_t next_read; + + /// Stream flags, see \ref string_stream_flags + int flags; + +} StringStream; + + +/// A StringStream with circular buffer semantics +/// +/// The swrite() method copies the input data to the stream buffer, which is +/// treated as a circular buffer. If the swrite() would overflow the buffer, +/// then as much data as possible is written and swrite returns -EAGAIN. In +/// all cases swrite() returns the number of bytes actually written to the +/// buffer. +/// +/// The sread() method copies data from the StringStream circular buffer to +/// the caller's buffer until either the caller's request is satisfied or all +/// of the immediately available data has been read from the buffer. If the +/// caller's request can not be immediately granted then as much data as +/// possible is copied and sread() returns -EAGAIN. In all cases sread() +/// returns the number of bytes actually read from the buffer. +/// +/// The fflush() method marks the buffer as empty, effectively losing any data +/// currently stored in the buffer. + +typedef StringStream CircularStream; + + +/// A StringStream with wrapping circular buffer semantics +/// +/// The swrite() method copies the input data to the stream buffer, which is +/// treated as a circular buffer. If the swrite() would overflow the buffer, +/// then unread data is overwritten with new data. If the size of the +/// swrite() exceeds the buffer length then the effect is simply to fill the +/// buffer with the final bytes of the caller's data. swrite() always returns +/// the number of bytes requested to be written. +/// +/// The sread() method copies data from the StringStream circular buffer to +/// the caller's buffer until either the caller's request is satisfied or all +/// of the immediately available data has been read from the buffer. If the +/// caller's request can not be immediately granted then as much data as +/// possible is copied and sread() returns -EAGAIN. In all cases sread() +/// returns the number of bytes actually read from the buffer. +/// +/// The fflush() method marks the buffer as empty, effectively losing any data +/// currently stored in the buffer. + +typedef StringStream WrappingStream; + + +/// Create a StringStream +/// +/// \param stream The StringStream to initialize +/// +/// \param buf The stream data buffer +/// +/// \param size The size of the data buffer in bytes +/// +/// \param flags Flags for FILE_create() +/// +/// \param swrite The function to be installed as the swrite() function for +/// the underlying FILE object. The sread() and fflush() functions are fixed. +/// +/// This API initializes a StringStream structure for use in I/O operations. +/// This API will typically only be used by the creation functions of specific +/// StringStream types. +/// +/// \retval 0 Success +/// +/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0) +/// or \a buf is NULL(0) and \a size is non-0. + +int +_string_stream_create(StringStream* stream, + void* buf, size_t size, int flags, + int (*swrite)(FILE* stream, + const void* buf, + size_t size, + size_t* written)); + +/// Create a CircularStream +/// +/// \param stream The CircularStream to initialize +/// +/// \param buf The stream data buffer +/// +/// \param size The size of the data buffer in bytes +/// +/// \param flags Flags for FILE_create() +/// +/// This API initializes a CircularStream structure for use in I/O +/// operations. Once created, the pointer to the CircularStream stream can be +/// cast to a FILE* and used for sread(), swrite(), fflush() and fprintf() +/// operations. +/// +/// \retval 0 Success +/// +/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0) +/// or \a buf is NULL(0) and \a size is non-0. + +int +circular_stream_create(CircularStream* stream, + void* buf, size_t size, int flags); + + +/// Create a WrappingStream +/// +/// \param stream The WrappingStream to initialize +/// +/// \param buf The stream data buffer +/// +/// \param size The size of the data buffer in bytes +/// +/// \param flags Flags for FILE_create() +/// +/// This API initializes a WrappingStream structure for use in I/O +/// operations. Once created, the pointer to the WrappingStream stream can be +/// cast to a FILE* and used for sread(), swrite(), fflush() and fprintf() +/// operations. +/// +/// \retval 0 Success +/// +/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0) +/// or \a buf is NULL(0) and \a size is non-0. + +int +wrapping_stream_create(CircularStream* stream, + void* buf, size_t size, int flags); + + +/// Create a LinearStream +/// +/// \param stream The LinearStream to initialize +/// +/// \param buf The stream data buffer +/// +/// \param size The size of the data buffer in bytes +/// +/// \param flags Flags for FILE_create() +/// +/// This API initializes a LinearStream structure for use in I/O +/// operations. Once created, the pointer to the WrappingStream stream can be +/// cast to a FILE* and used for sread(), swrite(), fflush() and fprintf() +/// operations. +/// +/// \retval 0 Success +/// +/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0) +/// or \a buf is NULL(0) and \a size is non-0. + + +int +linear_stream_create(CircularStream* stream, + void* buf, size_t size, int flags); + + +/// A StringStream used as a read-only input stream +/// +/// This is a CircualarStream created with a full buffer and without a write +/// method. It uses a special read method that returns EOF once the buffer is +/// empty rather than -EAGAIN. + +typedef StringStream InputStream; + + +/// Create an InputStream +/// +/// \param stream The InputStream to initialize +/// +/// \param buf The stream data buffer. +/// +/// \param size The size of the readable portion of the data buffer in bytes +/// +/// \param flags Flags for FILE_create() +/// +/// This API initializes an InputStream structure for use in input operations. +/// The stream data buffer contains \a size bytes of data which can be read. +/// Once created, the pointer to the InputStream stream can be cast to a FILE* +/// and used for sread(), fgetc() and ungetc() operations. Neither fflush() +/// nor swrite() are supported on this class of stream. The read operations +/// will succeed until \a size bytes have been returned from the stream, at +/// which point the stream will return EOF on any subsequent reads. +/// +/// \retval 0 Success +/// +/// \retval -STRING_STREAM_INVALID_ARGUMENT Either \a stream is NULL (0) +/// or \a buf is NULL(0) and \a size is non-0. + +int +input_stream_create(InputStream* stream, + void* buf, size_t size, int flags); + + +/// \defgroup string_stream_flags StringStream Flags +/// +/// @{ + +/// The StringStream is full +#define STRING_STREAM_FULL 0x1 + +/// @} + + +/// \defgroup string_stream_codes StringStream Error/Panic Codes +/// +/// @{ + +/// A bug was detected in a StringStream function +#define STRING_STREAM_BUG 0x00787701 +#define STRING_STREAM_INVALID_ARGUMENT 0x00787702 + +/// @} + + +#endif // __STRING_STREAM_H__ diff --git a/import/chips/p9/common/pmlib/ppc405lib/strtox.c b/import/chips/p9/common/pmlib/ppc405lib/strtox.c new file mode 100644 index 00000000..507c913d --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/strtox.c @@ -0,0 +1,726 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/strtox.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: strtox.c,v 1.2 2014/02/03 01:30:25 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strtox.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file strtox.c +/// \brief Implementation of strtol(), strtoul(), strtoll() and strtoull() +/// +/// <b> Standard String Conversion Routines </b> +/// +/// This file contains implementaions of strtol(), strtoul(), strtoll() and +/// strtoull(). These APIs are all called as +/// +/// \code +/// strtoX(const char* str, char** endptr, int base) +/// \endcode +/// +/// where X is +/// +/// - l : Convert to a long integer +/// - ul : Convert to an unsigned long integer +/// - ll : Convert to a long long integer +/// - ull : Convert to an unsigned long long integer +/// +/// \param str The string to convert +/// +/// \param endptr If non-null, will be set to a pointer to the portion of the +/// string following the convertable portion. If no conversion is performed +/// then the original \a str is returned here. +/// +/// \param base Either 0 to indicate that the base should be derived from +/// radix markers in the string, or a number in the range 2 to 36 inclusive. +/// +/// The APIs convert the initial portion of the string pointed to by \a str to +/// an integer, which is either a long integer (strtol), an unsigned long +/// (strtoul()), a long long (strtoll), or an unsigned long long +/// (strtoull). First, the APIs decompose the input string into three parts: +/// +/// - An initial, possibly empty, sequence of white-space characters (as +/// specified by isspace()) +/// +/// - A subject sequence interpreted as an integer represented in some radix +/// determined by the value of \a base +/// +/// - A final string of one or more unrecognized characters, including the +/// terminating null byte of the input string. +/// +/// The APIs then attempt to convert the subject sequence to an integer of the +/// required type and returns the result. +/// +/// If the value of \a base is 0, the expected form of the subject sequence is +/// that of a decimal constant, octal constant, or hexadecimal constant, any +/// of which may be preceded by a '+' or '-' sign. A decimal constant begins +/// with a non-zero digit, and consists of a sequence of decimal digits. An +/// octal constant consists of the prefix '0' optionally followed by a +/// sequence of the digits '0' to '7' only. A hexadecimal constant consists of +/// the prefix 0x or 0X followed by a sequence of the decimal digits and +/// letters 'a' (or 'A' ) to 'f' (or 'F' ) with values 10 to 15 respectively. +/// +/// If the value of \a base is between 2 and 36, the expected form of the +/// subject sequence is a sequence of letters and digits representing an +/// integer with the radix specified by base, optionally preceded by a '+' or +/// '-' sign. The letters from 'a' (or 'A' ) to 'z' (or 'Z' ) inclusive are +/// ascribed the values 10 to 35; only letters whose ascribed values are less +/// than that of base are permitted. If the value of base is 16, the +/// characters 0x or 0X may optionally precede the sequence of letters and +/// digits, following the sign if present. +/// +/// The subject sequence is defined as the longest initial subsequence of the +/// input string, starting with the first non-white-space character that is of +/// the expected form. The subject sequence contains no characters if the +/// input string is empty or consists entirely of white-space characters, or if +/// the first non-white-space character is other than a sign or a permissible +/// letter or digit. +/// +/// If the subject sequence has the expected form and the value of base is 0, +/// the sequence of characters starting with the first digit will be +/// interpreted as an integer constant. If the subject sequence has the +/// expected form and the value of base is between 2 and 36, it will be used +/// as the base for conversion, ascribing to each letter its value as given +/// above. If the subject sequence begins with a minus sign, the value +/// resulting from the conversion will be negated. A pointer to the final +/// string will be stored in the object pointed to by \a endptr, provided that +/// \a endptr is not a null pointer. +/// +/// If the subject sequence is empty or does not have the expected form, no +/// conversion is performed; the value of \a str is stored in the object +/// pointed to by \a endptr, provided that \a endptr is not a null pointer. +/// +/// Note that the unsigned APIs silently convert signed representations into +/// the equivalent unsigned number. +/// +/// Since 0, (L)LONG_MIN and (U)(L)LONG_MAX are returned on error and are +/// also valid returns on success, there is no way for an SSX application to +/// determine whether the conversion succeeded or failed (since SSX does not +/// support \a errno). For this reason it is recommended that SSX-only +/// applications use the underlying APIs _strtol(), _strtoul(), _strtoll() and +/// _strtoull(), or even better the extended APIs strtoi32(), strtou32(), +/// strtoi64() or strtou64() discussed further below. +/// +/// Upon successful completion, strtoX() returns the converted +/// value, if any. If no conversion could be performed or there was an error +/// in the base specification, 0 is returned. +/// +/// If the correct value is outside the range of representable values, +/// (L)LONG_MIN or (U)(L)LONG_MAX will be returned (according to the sign +/// and type of the value). +/// +/// Note: This specification is adapted from IEEE Std. 10003.1, 2003 Edition +/// +/// +/// <b> Underlying APIs </b> +/// +/// The APIs underlying the standard APIs are all called as +/// +/// \code +/// int _strtoX(const char* str, char** endptr, int radix, <type>* value) +/// \endcode +/// +/// where X is +/// +/// - l : Convert to a long integer +/// - ul : Convert to an unsigned long integer +/// - ll : Convert to a long long integer +/// - ull : Convert to an unsigned long long integer +/// +/// \param str The string to convert +/// +/// \param endptr If non-null, will be set to a pointer to the portion of the +/// string following the convertable portion. If no conversion is performed +/// then the original \a str is returned here. +/// +/// \param base Either 0 to indicate that the base should be derived from +/// radix markers in the string, or a number in the range 2 to 36 inclusive. +/// +/// \param value The converted value, returned as the return value of the +/// standard API. +/// +/// The return value of the underlying APIs is one of the following +/// +/// \retval 0 Success +/// +/// \retval -STRTOX_NO_CONVERSION_EMPTY No conversion was performed because the +/// string was effectively empty. +/// +/// \retval -STRTOX_NO_CONVERSION_PARSE No conversion was performed because the +/// string did not parse as an integer. +/// +/// \retval -STRTOX_INVALID_ARGUMENT No conversion was performed because the +/// \a base specification was not valid. +/// +/// \retval -STRTOX_UNDERFLOW_STRTOL1 Conversion resulted in underflow +/// +/// \retval -STRTOX_UNDERFLOW_STRTOL2 Conversion resulted in underflow +/// +/// \retval -STRTOX_UNDERFLOW_STRTOLL1 Conversion resulted in underflow +/// +/// \retval -STRTOX_UNDERFLOW_STRTOLL2 Conversion resulted in underflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOL1 Conversion resulted in overflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOL2 Conversion resulted in overflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOLL1 Conversion resulted in overflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOLL2 Conversion resulted in overflow +/// +/// +/// <b> Extended APIs </b> +/// +/// The extended APIs are the preferred way to do portable integer +/// conversion. These APIs are all called as +/// +/// \code +/// int strtoX(const char* str, char** endptr, int radix, <type>* value) +/// \endcode +/// +/// where X is +/// +/// - i32 : Convert to an int32_t +/// - u32 : Convert to a uint32_t +/// - i64 : Convert to an int64_t +/// - u64 : Convert to a uint64_t +/// +/// \param str The string to convert +/// +/// \param endptr If non-null, will be set to a pointer to the portion of the +/// string following the convertable portion. If no conversion is performed +/// then the original \a str is returned here. +/// +/// \param base Either 0 to indicate that the base should be derived from +/// radix markers in the string, or a number in the range 2 to 36 inclusive. +/// +/// \param value The converted value +/// +/// The return value of the underlying APIs is one of the following +/// +/// \retval 0 Success +/// +/// \retval -STRTOX_NO_CONVERSION_EMPTY No conversion was performed because the +/// string was effectively empty. +/// +/// \retval -STRTOX_NO_CONVERSION_PARSE No conversion was performed because the +/// string did not parse as an integer. +/// +/// \retval -STRTOX_INVALID_ARGUMENT No conversion was performed because the +/// \a base specification was not valid. +/// +/// \retval -STRTOX_UNDERFLOW_STRTOL1 Conversion resulted in underflow +/// +/// \retval -STRTOX_UNDERFLOW_STRTOL2 Conversion resulted in underflow +/// +/// \retval -STRTOX_UNDERFLOW_STRTOLL1 Conversion resulted in underflow +/// +/// \retval -STRTOX_UNDERFLOW_STRTOLL2 Conversion resulted in underflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOL1 Conversion resulted in overflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOL2 Conversion resulted in overflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOLL1 Conversion resulted in overflow +/// +/// \retval -STRTOX_OVERFLOW_STRTOLL2 Conversion resulted in overflow +/// + +#include "ssx.h" +#include "ctype.h" +#include "libssx.h" +#include "strtox.h" + + +// Skip whitespace + +static const char* +skip_whitespace(const char* s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +// Pick up a +/- sign. This is a predicate returning 1 if the value is +// negated. + +static int +sign(const char** s) +{ + if (**s == '+') + { + (*s)++; + return 0; + } + else if (**s == '-') + { + (*s)++; + return 1; + } + else + { + return 0; + } +} + + +// Look for a radix mark (0, 0[xX]). The string pointer is advanced if it is a +// hex mark (0[xX]), but not for a simple '0' which could be either the start +// of an octal constant or simply the number 0. The return value is either 8, +// 10 or 16. + +static int +radix_mark(const char** s) +{ + const char* p = *s; + + if (p[0] == '0') + { + if ((p[1] == 'x') || (p[1] == 'X')) + { + *s += 2; + return 16; + } + else + { + return 8; + } + } + else + { + return 10; + } +} + + +// Parse a character as a radix-base digit. Return the value of the digit or +// -1 if it is not a legal digit for the radix. + +static int +parse_digit(char c, int radix) +{ + if (isdigit(c)) + { + if ((c - '0') < radix) + { + return c - '0'; + } + else + { + return -1; + } + } + else if (radix <= 10) + { + return -1; + } + else + { + if (islower(c)) + { + if ((c - 'a') < (radix - 10)) + { + return c - 'a' + 10; + } + else + { + return -1; + } + } + else if (isupper(c)) + { + if ((c - 'A') < (radix - 10)) + { + return c - 'A' + 10; + } + else + { + return -1; + } + } + else + { + return -1; + } + } +} + + +// The most basic API is strtox(), which converts a string to an unsigned long +// long. All of the base APIs are written in terms of this. This is legal due +// to the fact that conversion is defined to continue even in the event of +// overflow. This API may return the codes STRTOX_NO_CONVERSION_EMPTY, +// STRTOX_NO_CONVERSION_PARSE or STRTOX_INVALID_ARGUMENT, +// which the standard APIs always convert to a 0 +// return value. Otherwise the flags 'overflow' and 'negative' are used by +// the base APIs to determine how to handle special cases. + +static int +strtox(const char* str, char** endptr, int base, + unsigned long long* value, int* negative, int* overflow) +{ + const char* s; + unsigned long long new; + int rc, radix, digit; + + + do + { + + s = str; + *value = 0; + *negative = 0; + *overflow = 0; + + // Initial error checks + + if ((base != 0) && ((base < 2) || (base > 36))) + { + rc = STRTOX_INVALID_ARGUMENT; + break; + } + + // Skip whitespace + + s = skip_whitespace(s); + + if (*s == '\0') + { + rc = STRTOX_NO_CONVERSION_EMPTY; + break; + } + + // Process a +/- sign. Only one is allowed. + + *negative = sign(&s); + + // Look for a radix mark. Note that if base == 16 this will cause the + // skip of a leading 0 in the string not followed by [xX], but that's + // OK because it doesn't change the result of the conversion. + + if (base == 0) + { + radix = radix_mark(&s); + } + else + { + radix = base; + + if (radix == 16) + { + radix_mark(&s); + } + } + + // Parse. Note that once overflow is detected we continue to parse + // (but ignore the data). + + rc = STRTOX_NO_CONVERSION_PARSE; + + while ((digit = parse_digit(*s, radix)) >= 0) + { + s++; + + if (!*overflow) + { + rc = 0; + new = (*value * radix) + digit; + + if (new < *value) + { + *overflow = 1; + } + else + { + *value = new; + } + } + } + } + while(0); + + if (endptr) + { + if (rc == 0) + { + *endptr = (char*)s; + } + else + { + *endptr = (char*)str; + } + } + + return rc; +} + + +/// See documentation for the file strtox.c +int +_strtol(const char* str, char** endptr, int base, long* value) +{ + int rc, negative, overflow; + unsigned long long value_ull; + + rc = strtox(str, endptr, base, &value_ull, &negative, &overflow); + + if (rc) + { + *value = 0; + } + else + { + if (overflow || (value_ull != (unsigned long)value_ull)) + { + if (negative) + { + rc = STRTOX_UNDERFLOW_STRTOL1; + *value = LONG_MIN; + } + else + { + rc = STRTOX_OVERFLOW_STRTOL1; + *value = LONG_MAX; + } + } + else if (negative) + { + if (value_ull > ((unsigned long long)LONG_MAX + 1ull)) + { + rc = STRTOX_UNDERFLOW_STRTOL2; + *value = LONG_MIN; + } + else + { + *value = ~value_ull + 1; + } + } + else if (value_ull > (unsigned long long)LONG_MAX) + { + rc = STRTOX_OVERFLOW_STRTOL2; + *value = LONG_MAX; + } + else + { + *value = value_ull; + } + } + + return rc; +} + + +/// See documentation for the file strtox.c +int +_strtoll(const char* str, char** endptr, int base, long long* value) +{ + int rc, negative, overflow; + unsigned long long value_ull; + + rc = strtox(str, endptr, base, &value_ull, &negative, &overflow); + + if (rc) + { + *value = 0; + } + else + { + if (overflow) + { + if (negative) + { + rc = STRTOX_UNDERFLOW_STRTOLL1; + *value = LLONG_MIN; + } + else + { + rc = STRTOX_OVERFLOW_STRTOLL1; + *value = LLONG_MAX; + } + } + else if (negative) + { + if (value_ull > ((unsigned long long)LLONG_MAX + 1ull)) + { + rc = STRTOX_UNDERFLOW_STRTOLL2; + *value = LLONG_MIN; + } + else + { + *value = ~value_ull + 1; + } + } + else if (value_ull > (unsigned long long)LLONG_MAX) + { + rc = STRTOX_OVERFLOW_STRTOLL2; + *value = LLONG_MAX; + } + else + { + *value = value_ull; + } + } + + return rc; +} + + +/// See documentation for the file strtox.c +int +_strtoul(const char* str, char** endptr, int base, unsigned long* value) +{ + int rc, negative, overflow; + unsigned long long value_ull; + + rc = strtox(str, endptr, base, &value_ull, &negative, &overflow); + + if (rc) + { + *value = 0; + } + else + { + if (overflow || (value_ull != (unsigned long)value_ull)) + { + rc = STRTOX_OVERFLOW_STRTOUL; + *value = ULONG_MAX; + } + else + { + *value = value_ull; + + if (negative) + { + *value = ~*value + 1; + } + } + } + + return rc; +} + +/// See documentation for the file strtox.c +int +_strtoull(const char* str, char** endptr, int base, unsigned long long* value) +{ + int rc, negative, overflow; + + rc = strtox(str, endptr, base, value, &negative, &overflow); + + if (rc) + { + *value = 0; + } + else + { + if (overflow) + { + rc = STRTOX_OVERFLOW_STRTOULL; + *value = ULLONG_MAX; + } + else + { + if (negative) + { + *value = ~*value + 1; + } + } + } + + return rc; +} + + +/// See documentation for the file strtox.c +long int +strtol(const char* str, char** endptr, int base) +{ + long int value; + + _strtol(str, endptr, base, &value); + return value; +} + + +/// See documentation for the file strtox.c +long long int +strtoll(const char* str, char** endptr, int base) +{ + long long int value; + + _strtoll(str, endptr, base, &value); + return value; +} + + +/// See documentation for the file strtox.c +unsigned long int +strtoul(const char* str, char** endptr, int base) +{ + unsigned long int value; + + _strtoul(str, endptr, base, &value); + return value; +} + + +/// See documentation for the file strtox.c +unsigned long long int +strtoull(const char* str, char** endptr, int base) +{ + unsigned long long int value; + + _strtoull(str, endptr, base, &value); + return value; +} + + +#if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 1)) + +/// Internal version of strtol() +/// +/// ppcnf-mcp5 (GCC 4.1) requires that the entry point __strtol_internal() be +/// present at certain optimization levels. This is equivalent to strtol() +/// except that it takes an extra argument that must be == 0. The \a group +/// parameter is supposed to control locale-specific thousands grouping. + +long int +__strtol_internal(const char* str, char** endptr, int base, int group) +{ + if (group != 0) + { + SSX_PANIC(STRTOX_INVALID_ARGUMENT_STRTOL); + } + + return strtol(str, endptr, base); +} + +#endif diff --git a/import/chips/p9/common/pmlib/ppc405lib/strtox.h b/import/chips/p9/common/pmlib/ppc405lib/strtox.h new file mode 100644 index 00000000..fd154813 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/strtox.h @@ -0,0 +1,151 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/strtox.h $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __STRTOX_H__ +#define __STRTOX_H__ + +// $Id: strtox.h,v 1.2 2014/02/03 01:30:25 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/strtox.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file strtox.h +/// \brief Underlying and extended APIs that support strtoX macros +/// +/// See the Doxygen comments of the file strtox.c for descriptions of the +/// facilities provided by this header. + +#ifndef __ASSEMBLER__ + +#include <limits.h> + +// Error codes + +#define STRTOX_NO_CONVERSION_EMPTY 0x00787901 +#define STRTOX_NO_CONVERSION_PARSE 0x00787902 +#define STRTOX_INVALID_ARGUMENT 0x00787903 +#define STRTOX_INVALID_ARGUMENT_STRTOL 0x00787904 +#define STRTOX_UNDERFLOW_STRTOL1 0x00787905 +#define STRTOX_UNDERFLOW_STRTOL2 0x00787906 +#define STRTOX_UNDERFLOW_STRTOLL1 0x00787907 +#define STRTOX_UNDERFLOW_STRTOLL2 0x00787908 +#define STRTOX_OVERFLOW_STRTOL1 0x00787909 +#define STRTOX_OVERFLOW_STRTOL2 0x0078790a +#define STRTOX_OVERFLOW_STRTOLL1 0x0078790b +#define STRTOX_OVERFLOW_STRTOLL2 0x0078790c +#define STRTOX_OVERFLOW_STRTOUL 0x0078790d +#define STRTOX_OVERFLOW_STRTOULL 0x0078790e + +// Earlier GCC configurations (ppcnf-mcp5-gcc) are not configured to define +// these standard constants, which exist in the include tree under various +// switches and configuration settings (from <limits.h>). They are defined by +// default in later standard cross builds however (GCC 4.5, 4.6). However we +// always assume that (long long) is a 64-bit type. It's likely that this is +// the only place these constant will be used (as they are defined as the +// values for under/overflow of strtoX() conversions), however it may be +// necessary in the future to move these #defines somewhere else. + +#ifndef LLONG_MIN + #define LLONG_MIN (0x8000000000000000ll) +#endif + +#ifndef LLONG_MAX + #define LLONG_MAX (0x7fffffffffffffffll) +#endif + +#ifndef ULLONG_MAX + #define ULLONG_MAX (0xffffffffffffffffull) +#endif + +int +_strtol(const char* str, char** endptr, int base, long* value); + +int +_strtoul(const char* str, char** endptr, int base, unsigned long* value); + +int +_strtoll(const char* str, char** endptr, int base, long long* value); + +int +_strtoull(const char* str, char** endptr, int base, unsigned long long* value); + + +// The way the sizeof(long) is discovered by default depends on which version +// of gcc/cpp we're using as these macros are predefined by cpp. + +#if (__SIZEOF_LONG__ == 4) || (__LONG_MAX__ == 2147483647L) + +/// See documentation for the file strtox.c +static inline int +strtoi32(const char* str, char** endptr, int base, int32_t* value) +{ + long int value_l; + int rc; + + rc = _strtol(str, endptr, base, &value_l); + *value = value_l; + return rc; +} + +/// See documentation for the file strtox.c +static inline int +strtou32(const char* str, char** endptr, int base, uint32_t* value) +{ + unsigned long int value_ul; + int rc; + + rc = _strtoul(str, endptr, base, &value_ul); + *value = value_ul; + return rc; +} + +#else + +#error "No port of strtox.h yet for systems with sizeof(long) != 4" + +#endif + +// It is assumed that long long is always 64 bits; There is no standard macro +// for this size constant + +/// See documentation for the file strtox.c +static inline int +strtoi64(const char* str, char** endptr, int base, int64_t* value) +{ + return _strtoll(str, endptr, base, value); +} + +/// See documentation for the file strtox.c +static inline int +strtou64(const char* str, char** endptr, int base, uint64_t* value) +{ + return _strtoull(str, endptr, base, value); +} + +#endif // __ASSEMBLER__ + +#endif // __STRTOX_H__ diff --git a/import/chips/p9/common/pmlib/ppc405lib/time.c b/import/chips/p9/common/pmlib/ppc405lib/time.c new file mode 100644 index 00000000..4ff2cca3 --- /dev/null +++ b/import/chips/p9/common/pmlib/ppc405lib/time.c @@ -0,0 +1,85 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: import/chips/p9/common/pmlib/ppc405lib/time.c $ */ +/* */ +/* OpenPOWER HCODE Project */ +/* */ +/* COPYRIGHT 2015,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: time.c,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/time.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file time.c +/// \brief Implementation of functions from <time.h> +/// +/// The following standard APIs are currently supported: +/// +/// - clock_gettime() with the single clock id CLOCK_REALTIME +/// +/// Since SSX does not currently have any per-thread CPU time statistics, we +/// can not implement process-CPU-time-based APIs like the simple clock() or +/// clock_gettime() with CLOCK_REALTIME. + +#include "ssx.h" +#include <errno.h> +#include <time.h> + +/// Get time from a timer +/// +/// \param clock_id This must be the constant CLOCK_REALTIME defined in +/// <time.h>. +/// +/// \param tp A pointer to a struct timespec populated by this API. +/// +/// Although the Posix standard requires that clock_gettime() support +/// CLOCK_REALTIME, CLOCK_REALTIME measures standard Unix time (seconds since +/// the epoch) which is not available to SSX. SSX currently only supports +/// CLOCK_MONOTONIC, which is derived from the SSX timebase. +/// +/// \returns Either 0 for success, or -EINVAL in the event of an invalid +/// argument (unrecognized \a clock_id, NULL \a tp pointer). + +int +clock_gettime(clockid_t clock_id, struct timespec* tp) +{ + int rc; + SsxTimebase now; + + if ((clock_id != CLOCK_MONOTONIC) || (tp == 0)) + { + rc = -EINVAL; + } + else + { + + now = ssx_timebase_get(); + tp->tv_sec = now / SSX_TIMEBASE_FREQUENCY_HZ; + tp->tv_nsec = + ((now % SSX_TIMEBASE_FREQUENCY_HZ) * 1000000000) / + SSX_TIMEBASE_FREQUENCY_HZ; + rc = 0; + } + + return rc; +} |

