diff --git a/Source/TestSuite/ASM/Makefile b/Source/TestSuite/ASM/Makefile new file mode 100644 index 0000000000..5fe87d1d8f --- /dev/null +++ b/Source/TestSuite/ASM/Makefile @@ -0,0 +1,135 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) +CXXFLAGS = $(CFLAGS) + +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lwiiuse -lbte -lfat -logc -lm + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + wiiload $(TARGET).dol + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .jpg extension +#--------------------------------------------------------------------------------- +%.jpg.o : %.jpg +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + $(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/Source/TestSuite/ASM/source/Defines.h b/Source/TestSuite/ASM/source/Defines.h new file mode 100644 index 0000000000..1a0e065243 --- /dev/null +++ b/Source/TestSuite/ASM/source/Defines.h @@ -0,0 +1,8 @@ +#include + +#define u32 unsigned int +#define u16 unsigned short +#define u8 unsigned char +#define s8 signed char +#define s16 signed short +#define s32 signed int \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/Helpers.cpp b/Source/TestSuite/ASM/source/Helpers.cpp new file mode 100644 index 0000000000..423ba296ee --- /dev/null +++ b/Source/TestSuite/ASM/source/Helpers.cpp @@ -0,0 +1,59 @@ + +#include "Defines.h" + +u32 GetCR0() +{ + u32 var; + asm( + "mfcr %0" + : "=&r"(var) + ); + return var; +} + +u32 GetCR(u32 num) +{ + u32 var; + if(num == 0) // wtf, silly people + return GetCR0(); + else { + // TODO: Ugly switch is ugly, was failing otherwise + switch (num) { + case 1: + asm("mcrf 0, 1"); + break; + case 2: + asm("mcrf 0, 2"); + break; + case 3: + asm("mcrf 0, 3"); + break; + case 4: + asm("mcrf 0, 4"); + break; + case 5: + asm("mcrf 0, 5"); + break; + case 6: + asm("mcrf 0, 6"); + break; + case 7: + asm("mcrf 0, 7"); + break; + default: + printf("Can this be more than 7?\n"); + break; + } + return GetCR0(); + } +} + +u32 GetXER() +{ + u32 var; + asm( + "mfxer %0" + : "=&r"(var) + ); + return var; +} \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/Helpers.h b/Source/TestSuite/ASM/source/Helpers.h new file mode 100644 index 0000000000..bd7f9830fe --- /dev/null +++ b/Source/TestSuite/ASM/source/Helpers.h @@ -0,0 +1,5 @@ +#include "Defines.h" + +u32 GetCR0(); +u32 GetCR(u32 num); +u32 GetXER(); \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/Init.cpp b/Source/TestSuite/ASM/source/Init.cpp new file mode 100644 index 0000000000..cd2ab852b1 --- /dev/null +++ b/Source/TestSuite/ASM/source/Init.cpp @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Init.h" + +static void *xfb = NULL; +static GXRModeObj *rmode = NULL; +void die(char *msg) { + if (f!=NULL) fclose(f); + printf(msg); + sleep(5); + fatUnmount("sd"); + __io_wiisd.shutdown(); + exit(0); +} + +void initialise_fat() { + __io_wiisd.startup(); + if (!fatInitDefault()) + die("Unable to initialise FAT subsystem, exiting.\n"); + fatMountSimple("sd", &__io_wiisd); + DIR_ITER *root = diropen("/"); + if (!root) + die("Cannot open root dir, exiting.\n"); + dirclose(root); + if (chdir("/")) + die("Could not change to root directory, exiting.\n"); +} + +void init_crap() { + VIDEO_Init(); + WPAD_Init(); + PAD_Init(); + + // Obtain the preferred video mode from the system + // This will correspond to the settings in the Wii menu + rmode = VIDEO_GetPreferredMode(NULL); + + // Allocate memory for the display in the uncached region + xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + + // Initialise the console, required for printf + console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); + + // Set up the video registers with the chosen mode + VIDEO_Configure(rmode); + + // Tell the video hardware where our display memory is + VIDEO_SetNextFramebuffer(xfb); + + // Make the display visible + VIDEO_SetBlack(FALSE); + + // Flush the video register changes to the hardware + VIDEO_Flush(); + + // Wait for Video setup to complete + VIDEO_WaitVSync(); + if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); +} + +void end() { + int columns = 0, rows = 0; + CON_GetMetrics(&columns, &rows); + printf("\x1b[%i;0H",rows); + printf("File written... press Home/Start to exit."); + while(1) { + WPAD_ScanPads(); PAD_ScanPads(); + if ((WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) || (PAD_ButtonsDown(0) & PAD_BUTTON_START)) + exit(0); + VIDEO_WaitVSync(); + } +} diff --git a/Source/TestSuite/ASM/source/Init.h b/Source/TestSuite/ASM/source/Init.h new file mode 100644 index 0000000000..a242bb0ed5 --- /dev/null +++ b/Source/TestSuite/ASM/source/Init.h @@ -0,0 +1,10 @@ +extern FILE *f; + + +void die(char *msg); + +void initialise_fat(); + +void init_crap(); + +void end(); \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/Instructions.h b/Source/TestSuite/ASM/source/Instructions.h new file mode 100644 index 0000000000..7ff5c52b81 --- /dev/null +++ b/Source/TestSuite/ASM/source/Instructions.h @@ -0,0 +1,18 @@ + +// Integer + +void subfc(u32 *a, u32 *b, u32 *c, u32 *d); +void subfcRC(u32 *a, u32 *b, u32 *c, u32 *d); + +void divw(u32 *a, u32 *b, u32 *c, u32 *d); +void divwRC(u32 *a, u32 *b, u32 *c, u32 *d); + +void divwo(u32 *a, u32 *b, u32 *c, u32 *d); +void divwoRC(u32 *a, u32 *b, u32 *c, u32 *d); + + +// Float + +void fsqrt(float *a, float *b, float *c, float *d); + +void fsqrtRC(float *a, float *b, float *c, float *d); \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/asm_float.cpp b/Source/TestSuite/ASM/source/asm_float.cpp new file mode 100644 index 0000000000..c38a0dad97 --- /dev/null +++ b/Source/TestSuite/ASM/source/asm_float.cpp @@ -0,0 +1,16 @@ + +#include "Defines.h" +void fsqrt(float *a, float *b, float *c, float *d) +{ + /*asm( + "fsqrt fr0,%0" + : "=&r"(*a) + );*/ +} +void fsqrtRC(float *a, float *b, float *c, float *d) +{ + /*asm( + "fsqrt. fr0,%0" + : "=&r"(*a) + );*/ +} \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/asm_integer.cpp b/Source/TestSuite/ASM/source/asm_integer.cpp new file mode 100644 index 0000000000..2f7891c40b --- /dev/null +++ b/Source/TestSuite/ASM/source/asm_integer.cpp @@ -0,0 +1,55 @@ +#include "asm_tables.h" +#include "Defines.h" +void subfc(u32 *a, u32 *b, u32 *c, u32 *d) +{ + asm( + "subfc %0,%1,%2" + : "=r"(*a) + : "r"(*b), "r"(*c) + ); +} +void subfcRC(u32 *a, u32 *b, u32 *c, u32 *d) +{ + asm( + "subfc. %0,%1,%2" + : "=r"(*a) + : "r"(*b), "r"(*c) + : "cc" + ); +} + +void divw(u32 *a, u32 *b, u32 *c, u32 *d) +{ + asm( + "divw %0,%1,%2" + : "=r"(*a) + : "r"(*b), "r"(*c) + ); +} +void divwRC(u32 *a, u32 *b, u32 *c, u32 *d) +{ + asm( + "divw. %0,%1,%2" + : "=r"(*a) + : "r"(*b), "r"(*c) + : "cc" + ); +} + +void divwo(u32 *a, u32 *b, u32 *c, u32 *d) +{ + asm( + "divwo %0,%1,%2" + : "=r"(*a) + : "r"(*b), "r"(*c) + ); +} +void divwoRC(u32 *a, u32 *b, u32 *c, u32 *d) +{ + asm( + "divwo. %0,%1,%2" + : "=r"(*a) + : "r"(*b), "r"(*c) + : "cc" + ); +} \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/asm_tables.cpp b/Source/TestSuite/ASM/source/asm_tables.cpp new file mode 100644 index 0000000000..150256f831 --- /dev/null +++ b/Source/TestSuite/ASM/source/asm_tables.cpp @@ -0,0 +1,177 @@ +#include "asm_tables.h" +#include "Init.h" +#include "Helpers.h" + +// Limited Test, Later have a test that will pass all possible variables +u32 inval_table[][2] = { + {0,0}, + {1,1}, + {300,0}, + {1,0}, + {0xffff,0}, + {0xffffffff,0}, + {0x80000000,0}, + {0x80000000,1}, + {0x80000000,2}, + {0x7fffffff,0}, + {0x7fffffff,1}, + {0x7fffffff,2}, + {0,1}, + {0,0xffff}, + {0,0xffffffff}, + {0,0x80000000}, + {1,0x80000000}, + {2,0x80000000}, + {0,0x7fffffff}, + {1,0x7fffffff}, + {2,0x7fffffff}, + {654321,0}, + {4653321,0}, + {0,300}, + {1024,8}, + {8,1024}, + {0xffff,0xffff}, + {0xffffffff,0xffffffff} +}; +void Print(const char* text) +{ + printf(text); + fprintf(f, text); +} +void ShowModifies(u32 inst) +{ + u32 mod = instructions[inst].Modifies; + if(mod == 0) + { + Print("NONE"); + return; + } + if(mod & MOD_CR0) + Print("CR0 "); + if(mod & MOD_CR1) + Print("CR1 "); + if(mod & MOD_SR) + Print("SR "); + if(mod & MOD_XER) + Print("XER "); +} +void RunInstruction(u32 inst) +{ + u32 inval1, inval2, inval3; + + u32 outval = 0; + + // CR0 + u32 cr1 = 0, cr2 = 0; + + //CR1 + u32 cr11 = 0, cr12 = 0; + + //XER + u32 xer1 = 0, xer2 = 0; + + bool modCR0 = instructions[inst].Modifies & MOD_CR0; + bool modCR1 = instructions[inst].Modifies & MOD_CR1; + bool modXER = instructions[inst].Modifies & MOD_XER; + + if(instructions[inst].numInput != 3) + { + Print("Don't support Input not 3 yet~!\n"); + fclose(f); + return; + } + if(instructions[inst].type != TYPE_INTEGER) + { + Print("Types other than TYPE_INTEGER not supported yet!\n"); + fclose(f); + return; + } + char temp[32]; + sprintf(temp, "logs/%s.dolphin.jit.log", instructions[inst].name); + f = fopen(temp, "wb"); + if (!f) + printf("unable to open output file\n"); + + printf("%s: InputNum: %d Modifies(flags): ", instructions[inst].name, instructions[inst].numInput); + fprintf(f, "%s: InputNum: %d Modifies(flags): ", instructions[inst].name, instructions[inst].numInput); + ShowModifies(inst); + Print("\n"); + + for (unsigned int i = 0; i < sizeof(inval_table)/(sizeof(int)*2); i++) + { + inval1 = inval_table[i][0]; + inval2 = inval_table[i][1]; + + // Show our input values and where we are at on the array + printf("\x1b[%i;0H", i); + printf("%07i: %08x,%08x",i, inval1,inval2); + + // Get flags before + if(modCR0) + cr1 = GetCR0(); + if(modCR1) + cr11 = GetCR(1); + if(modXER) + xer1 = GetXER(); + + //Actually call instruction + instructions[inst].Call(&outval, &inval1, &inval2, 0); + + // Get flags after + if(modCR0) + cr2 = GetCR0(); + if(modCR1) + cr12 = GetCR(1); + if(modXER) + xer2 = GetXER(); + + // Print out value + printf(":o=%08x\n\t", outval); + + // show off flag changes + if(modCR0) + printf("CR0:(%08x ~ %08x)", cr1,cr2); + if(modCR1) + printf("CR1:(%08x ~ %08x)", cr11,cr12); + if(modXER) + printf("XER:(%08x ~ %08x)", xer1, xer2); + + + // same in the file + fprintf(f, ":i=%08x, %08x:o=%08x\n\t", inval1,inval2, outval); + if(modCR0) + fprintf(f, "CR0:(%08x ~ %08x)", cr1,cr2); + if(modCR1) + fprintf(f, "CR1:(%08x ~ %08x)", cr11,cr12); + if(modXER) + fprintf(f, "XER:(%08x ~ %08x)", xer1, xer2); + + // see the difference in flags if any + if(modCR0) + { + u32 cr_diff = cr2&~cr1; + if (cr_diff) { + printf(" CR0D:%08x",cr_diff); + fprintf(f, " CR0D:%08x",cr_diff); + } + } + if(modCR1) + { + u32 cr1_diff = cr12&~cr11; + if (cr1_diff) { + printf(" CR1D:%08x",cr1_diff); + fprintf(f, " CR1D:%08x",cr1_diff); + } + } + if(modXER) + { + u32 xer_diff = xer2&~xer1; + if (xer_diff) { + printf(" XERD:%08x",xer_diff); + fprintf(f, " XERD:%08x",xer_diff); + } + } + fprintf(f,"\n"); + } + fclose(f); +} \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/asm_tables.h b/Source/TestSuite/ASM/source/asm_tables.h new file mode 100644 index 0000000000..abe854f205 --- /dev/null +++ b/Source/TestSuite/ASM/source/asm_tables.h @@ -0,0 +1,50 @@ + +#include "Defines.h" +#include "Instructions.h" + +enum Modify +{ + MOD_CR0 = (1 << 0), + MOD_CR1 = (1 << 1), + MOD_SR = (1 << 2), + MOD_XER = (1 << 3), + MOD_FPSCR = (1 << 4) +}; +enum IOput +{ + IO_ARG1 = (1 << 0), + IO_ARG2 = (1 << 1), + IO_ARG3 = (1 << 2), +}; +enum inst_type +{ + TYPE_INTEGER, + TYPE_FLOAT +}; + +struct inst +{ + char name[16]; + u32 Modifies; // Flag modification + u8 numInput; + u32 Input; + u32 Ouput; + inst_type type; + void (*Call)(u32*, u32*, u32*, u32*); + void (*CallFP)(float*, float*, float*, float*); + +}; + +static inst instructions[] = { + { "subfc", NULL, 3, IO_ARG1 | IO_ARG2 | IO_ARG3, IO_ARG1,TYPE_INTEGER, subfc}, + { "subfc.", MOD_CR0, 3, IO_ARG1 | IO_ARG2 | IO_ARG3, IO_ARG1,TYPE_INTEGER, subfcRC}, + { "divw", NULL, 3, IO_ARG1 | IO_ARG2 | IO_ARG3, IO_ARG1, TYPE_INTEGER, divw}, + { "divw.", MOD_CR0, 3, IO_ARG1 | IO_ARG2 | IO_ARG3, IO_ARG1,TYPE_INTEGER, divwRC}, + { "divwo", MOD_XER, 3, IO_ARG1 | IO_ARG2 | IO_ARG3, IO_ARG1,TYPE_INTEGER, divwo}, + { "divwo.", MOD_CR0 | MOD_XER, 3, IO_ARG1 | IO_ARG2 | IO_ARG3, IO_ARG1, TYPE_INTEGER, divwoRC}, + //{ "fsqrt", MOD_FPSCR, 2, IO_ARG1 | IO_ARG2, IO_ARG1,TYPE_FLOAT, NULL, fsqrt}, + //{ "fsqrt.", MOD_CR1 | MOD_FPSCR, 2, IO_ARG1 | IO_ARG2, IO_ARG1,TYPE_FLOAT, NULL, fsqrtRC} +}; + + +void RunInstruction(u32 inst); \ No newline at end of file diff --git a/Source/TestSuite/ASM/source/dolphintest_asm.cpp b/Source/TestSuite/ASM/source/dolphintest_asm.cpp new file mode 100644 index 0000000000..9c008067ef --- /dev/null +++ b/Source/TestSuite/ASM/source/dolphintest_asm.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include +#include +#include + +#include "Defines.h" +#include "Init.h" +#include "asm_tables.h" +#include "Helpers.h" + + +FILE *f = NULL; +int main(int argc, char **argv) { + init_crap(); + initialise_fat(); + + for(int a = 0; a < sizeof(instructions) / sizeof(inst); ++a) + { + RunInstruction(a); + } + + end(); + + return 0; +} diff --git a/Source/TestSuite/ASM/source/makefile b/Source/TestSuite/ASM/source/makefile new file mode 100644 index 0000000000..ddd5e6df5f --- /dev/null +++ b/Source/TestSuite/ASM/source/makefile @@ -0,0 +1,3 @@ +all: + g++ -S -arch ppc Instructions/asm_float.cpp + g++ -g -arch ppc dolphintest_asm.cpp asm_tables.cpp Helpers.cpp Instructions/asm_integer.cpp Instructions/asm_float.cpp OSX/Init.cpp -o Test \ No newline at end of file