test-z80:
$(MAKE) inter-port-clean test-port PORT=z80
+# Helper rule for testing the mcs51 small model port only
+test-mcs51:
+ $(MAKE) inter-port-clean test-port PORT=mcs51
+
# Helper rule for testing the host cc only
test-host:
$(MAKE) inter-port-clean clean test-port PORT=host
include $(PORTS_DIR)/$(PORT)/spec.mk
endif
-SDCCFLAGS += -Ifwk/include
+SDCCFLAGS += -Ifwk/include -Itests
# List of intermediate files to keep. Pretty much keep everything as
# disk space is free.
extern int __numTests;
void __fail(const char *szMsg, const char *szCond, const char *szFile, int line);
-void __printf(const char *szFormat, ...);
+void __printf(const char *szFormat, ...) REENTRANT;
#define ASSERT(_a) (__numTests++, (_a) ? (void)0 : __fail("Assertion failed", #_a, __FILE__, __LINE__))
#define LOG(_a) __printf _a
#define BROKEN_DIV_MOD 1
void _putchar(char c);
+void _exitEmu(void);
#if BROKEN_DIV_MOD
int __div(int num, int denom)
_putchar('0' + rem);
}
-void __printf(const char *szFormat, ...)
+void __printf(const char *szFormat, ...) REENTRANT
{
va_list ap;
va_start(ap, szFormat);
if (*szFormat == '%') {
switch (*++szFormat) {
case 's': {
- const char *sz = va_arg(ap, const char *);
+ char GENERIC *sz = va_arg(ap, char GENERIC *);
while (*sz) {
_putchar(*sz++);
}
__numFailures, __numTests, numCases
);
- return __numFailures;
+ _exitEmu();
}
RRZ80 = $(SDCC_EXTRA_DIR)/emu/rrz80/rrz80
-SDCCFLAGS += --lesspedantic --profile
+SDCCFLAGS += --lesspedantic --profile -DREENTRANT= -DGENERIC= --dumpall
EXEEXT = .bin
%$(OBJEXT): %.s
../../bin/as-z80 -plosgff $@ $<
+%$(OBJEXT): %.c
+ $(SDCC) $(SDCCFLAGS) -c $<
+
# PENDING: Path to sdcc-extra
%.out: %$(EXEEXT)
mkdir -p `dirname $@`
.area _CODE
.globl _putchar
+ .globl _exit
__putchar::
jp _putchar
+
+__exitEmu::
+ jp _exit
--- /dev/null
+/* Demonstrates the aliasing problem with the z80 port when loop
+ induction is turned on. Run_Index and Int_2_Loc get joined into
+ the same spill location.
+
+ Stripped down version of dhry.c
+ */
+
+#include <testfwk.h>
+
+#define NOENUM 1
+#define NOSTRUCTASSIGN 1
+#define REG
+
+#define Ident_2 1
+
+typedef int Enumeration;
+
+typedef int One_Fifty;
+typedef char Capital_Letter;
+
+char Ch_2_Glob;
+
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
+
+void
+testDhry(void)
+{
+ One_Fifty Int_1_Loc;
+ REG One_Fifty Int_2_Loc;
+ One_Fifty Int_3_Loc;
+ REG Capital_Letter Ch_Index;
+ Enumeration Enum_Loc;
+ REG int Run_Index;
+ REG int Number_Of_Runs;
+
+ /* Must be more than 13... */
+ Number_Of_Runs = 50;
+
+ /* Main test loop */
+ for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
+ Int_1_Loc = 2;
+ Int_2_Loc = 3;
+ Enum_Loc = Ident_2;
+
+ /* Removing this section removes the problem. */
+ while (Int_1_Loc < Int_2_Loc)
+ {
+ Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
+ Int_1_Loc += 1;
+ }
+
+ /* Removing this section removes the problem. */
+ for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
+ {
+ if (Enum_Loc == Func_1 (Ch_Index, 'C'))
+ {
+ Int_2_Loc = Run_Index;
+ }
+ }
+
+ /* Removing any one of the following lines removes the problem. */
+ Int_2_Loc = Int_2_Loc * Int_1_Loc;
+ Int_1_Loc = Int_2_Loc / Int_3_Loc;
+ Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
+ }
+}
+
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
+{
+ UNUSED(Ch_1_Par_Val);
+ UNUSED(Ch_2_Par_Val);
+}
--- /dev/null
+/* Test the types of switch statement.
+
+ type: char, int, long
+ sign: signed, unsigned
+ storage: static,
+ attr: volatile
+ */
+#include <testfwk.h>
+
+{sign} {type}
+sparseSwitch({sign} {type} val)
+{
+ {sign} {type} ret;
+ {storage} {attr} {sign} {type} local;
+
+ local = val;
+
+ switch (local) {
+ case 1:
+ ret = 7;
+ break;
+ case 4:
+ ret = 12;
+ break;
+ case 6:
+ ret = 13;
+ /* Fall through */
+ case 12:
+ ret = 14;
+ break;
+ case 13:
+ case 14:
+ case 15:
+ ret = 19;
+ break;
+ default:
+ ret = 30;
+ }
+
+ return ret;
+}
+
+void
+testSparseSwitch(void)
+{
+ ASSERT(sparseSwitch(1) == 7);
+ ASSERT(sparseSwitch(4) == 12);
+ ASSERT(sparseSwitch(6) == 14);
+ ASSERT(sparseSwitch(12) == 14);
+ ASSERT(sparseSwitch(13) == 19);
+ ASSERT(sparseSwitch(14) == 19);
+ ASSERT(sparseSwitch(15) == 19);
+ ASSERT(sparseSwitch(19) == 30);
+ ASSERT(sparseSwitch(0) == 30);
+}
+
+{sign} {type}
+denseSwitch({sign} {type} val)
+{
+ {sign} {type} ret;
+ {storage} {attr} {sign} {type} local;
+
+ local = val;
+ ret = 12;
+
+ switch (local) {
+ case 0:
+ ret = 1;
+ break;
+ case 1:
+ ret = 14;
+ break;
+ case 2:
+ ret = 15;
+ break;
+ case 3:
+ ret = 34;
+ break;
+ case 4:
+ ret = 17;
+ break;
+ /* No default */
+ }
+
+ return ret;
+}
+
+void
+testDenseSwitch(void)
+{
+ ASSERT(denseSwitch(0) == 1);
+ ASSERT(denseSwitch(1) == 14);
+ ASSERT(denseSwitch(2) == 15);
+ ASSERT(denseSwitch(3) == 34);
+ ASSERT(denseSwitch(4) == 17);
+ ASSERT(denseSwitch(5) == 12);
+ ASSERT(denseSwitch(100) == 12);
+}
+
+void
+testDenseIntSwitch(void)
+{
+ volatile int val = 1000;
+ volatile int ret = 0;
+
+ switch (val) {
+ case 999:
+ ret = 5;
+ break;
+ case 1000:
+ ret = 6;
+ break;
+ case 1001:
+ ret = 7;
+ break;
+ case 1002:
+ ret = 12;
+ break;
+ case 1003:
+ ret = 14;
+ break;
+ }
+
+ ASSERT(ret == 6);
+
+ val = 129;
+
+ switch (val) {
+ case 126:
+ ret = 5;
+ break;
+ case 127:
+ ret = 6;
+ break;
+ case 128:
+ ret = 7;
+ break;
+ case 129:
+ ret = 8;
+ break;
+ default:
+ ret = 9;
+ }
+
+ ASSERT(ret == 8);
+}