From 79de05d54cea65eeee48dae82fc2e7d421a8cc4b Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Wed, 15 Apr 2009 14:11:45 +0000 Subject: [PATCH] Initial version Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@448 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/bsp/examples/crc32.c | 54 +++ lib/CPUs/MIPS/bsp/examples/crc32.h | 13 + lib/CPUs/MIPS/bsp/examples/dbg.c | 343 +++++++++++++++ lib/CPUs/MIPS/bsp/examples/gunzip.c | 190 ++++++++ lib/CPUs/MIPS/bsp/examples/inflate.c | 499 +++++++++++++++++++++ lib/CPUs/MIPS/bsp/examples/inflate.h | 15 + lib/CPUs/MIPS/bsp/examples/life.c | 249 +++++++++++ lib/CPUs/MIPS/bsp/examples/mipsdis.c | 625 +++++++++++++++++++++++++++ lib/CPUs/MIPS/bsp/examples/mipsdis.h | 450 +++++++++++++++++++ lib/CPUs/MIPS/bsp/examples/r3.c | 466 ++++++++++++++++++++ 10 files changed, 2904 insertions(+) create mode 100644 lib/CPUs/MIPS/bsp/examples/crc32.c create mode 100644 lib/CPUs/MIPS/bsp/examples/crc32.h create mode 100644 lib/CPUs/MIPS/bsp/examples/dbg.c create mode 100644 lib/CPUs/MIPS/bsp/examples/gunzip.c create mode 100644 lib/CPUs/MIPS/bsp/examples/inflate.c create mode 100644 lib/CPUs/MIPS/bsp/examples/inflate.h create mode 100644 lib/CPUs/MIPS/bsp/examples/life.c create mode 100644 lib/CPUs/MIPS/bsp/examples/mipsdis.c create mode 100644 lib/CPUs/MIPS/bsp/examples/mipsdis.h create mode 100644 lib/CPUs/MIPS/bsp/examples/r3.c diff --git a/lib/CPUs/MIPS/bsp/examples/crc32.c b/lib/CPUs/MIPS/bsp/examples/crc32.c new file mode 100644 index 0000000..6f63429 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/crc32.c @@ -0,0 +1,54 @@ +#include + +unsigned long MakeCRC32(char *data, unsigned int len, unsigned int CRC) +{ + /* ======================================================================== + * Table of CRC-32's of all single-byte values (made by makecrc.c) + */ + unsigned long crc_32_tab[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL + }; + + if (data == NULL) + return 0; + + CRC = ~CRC; + while (len --) + { + CRC = crc_32_tab[((unsigned char) CRC ^ *data) & 0xFF] ^ (CRC >> 8); + data ++; + } + + return ~CRC; +} diff --git a/lib/CPUs/MIPS/bsp/examples/crc32.h b/lib/CPUs/MIPS/bsp/examples/crc32.h new file mode 100644 index 0000000..04687b0 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/crc32.h @@ -0,0 +1,13 @@ +// CRC32 function +// To create a CRC from a new buffer, use this: +// crc = MakeCRC32(mydata, data_len, 0); +// If you need to continue the CRC (e.g. your data is in multiple buffers), +// continue like this: +// crc = MakeCRC32(moredata, more_len, crc); +// +// Your desired CRC should be the complement of the CRC generated by +// MakeCRC32: +// desired = crc +// desired - crc = 0 + +unsigned long MakeCRC32(char *data, unsigned int len, unsigned long CRC); diff --git a/lib/CPUs/MIPS/bsp/examples/dbg.c b/lib/CPUs/MIPS/bsp/examples/dbg.c new file mode 100644 index 0000000..b63dbd1 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/dbg.c @@ -0,0 +1,343 @@ +#include +#include +#include +#include "irq.h" +#include "libsys.h" +#include "mipsdis.h" + +#define MAX_USER_BP 16 +#define BP_MASK_ID 0x00FFF +#define BP_MASK_TYPE 0xFF000 + +#define BP_GET_ID(bp) ((bp >> 6) & 0xFFF) + +#define BP_USER_BASE 0x10000 +#define BP_USER(id) (((BP_USER_BASE + id) << 6) | 0x0D) + +#define BP_MGMT_BASE_SS 0x20000 +#define BP_MGMT_SS(id) (((BP_MGMT_BASE_SS + id) << 6) | 0x0D) + +#define BP_MGMT_BASE_RU 0x30000 +#define BP_MGMT_RU(id) (((BP_MGMT_BASE_RU + id) << 6) | 0x0D) + +static char g_buf[80]; + +typedef struct _sbp_t +{ + UINT32 *pAddr; + UINT32 instr; +} bp_t; + +static bp_t user_bp[MAX_USER_BP]; +static bp_t mgmt_bp_ss[2]; +static bp_t mgmt_bp_ru[2]; +static int g_is_ss; +static int g_bp_index; + +int IsBreak(UINT32 instr) +{ + return ((instr & 0xFC00003F) == 0x0000000D); +} + +UINT32 BreakGetType(UINT32 instr) +{ + return (instr >> 6) & BP_MASK_TYPE; +} + +void dbg_handler(struct xcptcontext * xcp) +{ + + UINT32 bp_addr, bp_index = 0, branch_addr, reg, result, bp_type; + int junk, i, leave_isr, is_branch_shadow, is_user_bp; + UINT32 volatile *pBtn = (UINT32*)sys_gpio0; + UINT32 volatile *pTim_stat = (UINT32*)sys_itim_stat; + UINT32 volatile *pTim_cnt = (UINT32*)sys_itim_cnt; + UINT32 volatile *pTim_cmp = (UINT32*)sys_itim_cmp; + UINT32 *pInstr, *pAddr_curr, *pAddr_prev, *pAddr_next; + + sputs("\n"); + PRINT_REG(" Status : ", xcp->sr); + PRINT_REG(" Cause : ", xcp->cr); + PRINT_REG(" EPC : ", xcp->epc); + PRINT_REG("BadAddr : ", xcp->baddr); + sputs("\n"); + PRINT_REG(" MDLO : ", xcp->mdlo); + PRINT_REG(" MDHI : ", xcp->mdhi); + + sputs("\n"); + + sputs("Registers:\n"); + PRINT_REG(" 0 (ze) : ", xcp->regs[0]); + PRINT_REG(" 1 (at) : ", xcp->regs[1]); + PRINT_REG(" 2 (v0) : ", xcp->regs[2]); + PRINT_REG(" 3 (v1) : ", xcp->regs[3]); + sputs("\n"); + PRINT_REG(" 4 (a0) : ", xcp->regs[4]); + PRINT_REG(" 5 (a1) : ", xcp->regs[5]); + PRINT_REG(" 6 (a2) : ", xcp->regs[6]); + PRINT_REG(" 7 (a3) : ", xcp->regs[7]); + sputs("\n"); + PRINT_REG(" 8 (t0) : ", xcp->regs[8]); + PRINT_REG(" 9 (t1) : ", xcp->regs[9]); + PRINT_REG("10 (t2) : ", xcp->regs[10]); + PRINT_REG("11 (t3) : ", xcp->regs[11]); + sputs("\n"); + PRINT_REG("12 (t4) : ", xcp->regs[12]); + PRINT_REG("13 (t5) : ", xcp->regs[13]); + PRINT_REG("14 (t6) : ", xcp->regs[14]); + PRINT_REG("15 (t7) : ", xcp->regs[15]); + sputs("\n"); + PRINT_REG("16 (s0) : ", xcp->regs[16]); + PRINT_REG("17 (s1) : ", xcp->regs[17]); + PRINT_REG("18 (s2) : ", xcp->regs[18]); + PRINT_REG("19 (s3) : ", xcp->regs[19]); + sputs("\n"); + PRINT_REG("20 (s4) : ", xcp->regs[20]); + PRINT_REG("21 (s5) : ", xcp->regs[21]); + PRINT_REG("22 (s6) : ", xcp->regs[22]); + PRINT_REG("23 (s7) : ", xcp->regs[23]); + sputs("\n"); + PRINT_REG("24 (t8) : ", xcp->regs[24]); + PRINT_REG("25 (t9) : ", xcp->regs[25]); + PRINT_REG("26 (k0) : ", xcp->regs[26]); + PRINT_REG("27 (k1) : ", xcp->regs[27]); + sputs("\n"); + PRINT_REG("28 (gp) : ", xcp->regs[28]); + PRINT_REG("29 (sp) : ", xcp->regs[29]); + PRINT_REG("30 (fp) : ", xcp->regs[30]); + PRINT_REG("31 (ra) : ", xcp->regs[31]); + sputs("\n"); + sputs("\n"); + + is_user_bp = 0; + pAddr_curr = (UINT32*)xcp->epc; + is_branch_shadow = ((xcp->cr & 0x80000000) == 0x80000000); + if (is_branch_shadow) + pAddr_curr++; + + pAddr_prev = pAddr_curr - 1; + pAddr_next = pAddr_curr + 1; + + if (IsBreak(*pAddr_curr)) + { + bp_type = BreakGetType(*pAddr_curr); + + switch (bp_type) + { + case BP_MGMT_BASE_SS: + + // Restore original instructions after single-step + sputs("1. Restore after single-step at ");print_word((long)mgmt_bp_ss[0].pAddr);sputs("\n"); + *(mgmt_bp_ss[0].pAddr) = mgmt_bp_ss[0].instr; + ICACHE_invalidate_at(mgmt_bp_ss[0].pAddr); + if (mgmt_bp_ss[1].pAddr) + { + sputs("2. Restore after single-step at ");print_word((long)mgmt_bp_ss[1].pAddr);sputs("\n"); + *(mgmt_bp_ss[1].pAddr) = mgmt_bp_ss[1].instr; + ICACHE_invalidate_at(mgmt_bp_ss[1].pAddr); + } + + break; + + case BP_MGMT_BASE_RU: + + bp_index = BP_GET_ID(*pAddr_curr); + sputs("Restore user break at ");print_word((long)user_bp[bp_index].pAddr);sputs("\n"); + + *(user_bp[bp_index].pAddr) = BP_USER(bp_index); + ICACHE_invalidate_at(user_bp[bp_index].pAddr); + + *(mgmt_bp_ru[0].pAddr) = mgmt_bp_ru[0].instr; + ICACHE_invalidate_at(mgmt_bp_ru[0].pAddr); + sputs("1. Restore after RU at ");print_word((long)mgmt_bp_ru[0].pAddr);sputs("\n"); + if (mgmt_bp_ru[1].pAddr) + { + *(mgmt_bp_ru[1].pAddr) = mgmt_bp_ru[1].instr; + ICACHE_invalidate_at(mgmt_bp_ru[1].pAddr); + sputs("2. Restore after RU at ");print_word((long)mgmt_bp_ru[1].pAddr);sputs("\n"); + } + if (!g_is_ss) + return; + + break; + + case BP_USER_BASE: + + is_user_bp = 1; + bp_index = BP_GET_ID(*pAddr_curr); + sputs("Restore instruction at ");print_word((long)user_bp[bp_index].pAddr);sputs("\n"); + *(user_bp[bp_index].pAddr) = user_bp[bp_index].instr; + ICACHE_invalidate_at(user_bp[bp_index].pAddr); + break; + + default: + break; + + } + } + + pInstr = pAddr_prev; + // Disassemble instructions + for (i=0; i < 3; i++) + { + print_word((long)pInstr); + if (IsBreak(*pInstr) && (BreakGetType(*pInstr) == BP_USER_BASE)) + { + tdisasm(g_buf, (long)user_bp[BP_GET_ID(*pInstr)].pAddr, user_bp[BP_GET_ID(*pInstr)].instr, 0, &junk, &junk, &junk); + sputs(": b "); + } + else + { + tdisasm(g_buf, (long)pInstr, *pInstr, 0, &junk, &junk, &junk); + if (pInstr == pAddr_curr) + if (is_user_bp == 1) + sputs(": b-> "); + else + sputs(": -> "); + else + sputs(": "); + } + sputs(g_buf); + sputs("\n"); + pInstr++; + } + + if (is_user_bp) + { + // Save original instruction + mgmt_bp_ru[0].pAddr = pAddr_next; + mgmt_bp_ru[0].instr = *(mgmt_bp_ru[0].pAddr); + // Replace instruction with managment breakpoint + *(mgmt_bp_ru[0].pAddr) = BP_MGMT_RU(bp_index); + ICACHE_invalidate_at(mgmt_bp_ru[0].pAddr); + mgmt_bp_ru[1].pAddr = NULL; + mgmt_bp_ru[1].pAddr = 0; + sputs("1. Insert RU-break at ");print_word((long)mgmt_bp_ru[0].pAddr);sputs("\n"); + + // We have two possible management breaks, if previous instruction was branch or jump + if (is_branch_shadow) + { + result = tdisasm(g_buf, (long)pAddr_prev, *pAddr_prev, 0, &junk, &branch_addr, ®); + // Is jump target stored in register + if (result == 3) + { + branch_addr = xcp->regs[reg&0x1F]; + } + // Save original instruction + mgmt_bp_ru[1].pAddr = (UINT32*)branch_addr; + mgmt_bp_ru[1].instr = *(mgmt_bp_ru[1].pAddr); + // Replace instruction with managment breakpoint + *(mgmt_bp_ru[1].pAddr) = BP_MGMT_RU(bp_index); + ICACHE_invalidate_at(mgmt_bp_ru[1].pAddr); + sputs("2. Insert RU-break at ");print_word((long)mgmt_bp_ru[1].pAddr);sputs("\n"); + } + } + + do + { + leave_isr = 0; + switch(readchar()) + { + case 'g': + leave_isr = 1; + g_is_ss = 0; + break; + + case 'b': + printf("Enter breakpoint: "); + scanf("%x", &bp_addr); + printf("Insert breakpoint at %.8X\n", bp_addr); + user_bp[g_bp_index].pAddr = (UINT32*)bp_addr; + user_bp[g_bp_index].instr = *(user_bp[g_bp_index].pAddr); + *(user_bp[g_bp_index].pAddr) = BP_USER(g_bp_index); + + tdisasm(g_buf, (long)user_bp[g_bp_index].pAddr, user_bp[g_bp_index].instr, 0, &junk, &junk, &junk); + print_word((long)user_bp[g_bp_index].pAddr);sputs(": b ");sputs(g_buf);sputs("\n"); + g_bp_index++; + break; + + case 's': + g_is_ss = 1; + leave_isr = 1; + // Don't overwrite RU breaks + if (is_user_bp) + break; + // Don't overwrite user breaks + if (IsBreak(*pInstr) && (BreakGetType(*pInstr) == BP_USER_BASE)) + break; + + // Save original instruction + mgmt_bp_ss[0].pAddr = pAddr_next; + mgmt_bp_ss[0].instr = *(mgmt_bp_ss[0].pAddr); + // Replace instruction with managment breakpoint + *(mgmt_bp_ss[0].pAddr) = BP_MGMT_SS(1); + ICACHE_invalidate_at(mgmt_bp_ss[0].pAddr); + mgmt_bp_ss[1].pAddr = NULL; + mgmt_bp_ss[1].pAddr = 0; + // We have two possible management breaks, if previous instruction was branch or jump + if (is_branch_shadow) + { + result = tdisasm(g_buf, (long)pAddr_prev, *pAddr_prev, 0, &junk, &branch_addr, ®); + // Is jump target stored in register + if (result == 3) + { + branch_addr = xcp->regs[reg&0x1F]; + } + // Save original instruction + mgmt_bp_ss[1].pAddr = (UINT32*)branch_addr; + mgmt_bp_ss[1].instr = *(mgmt_bp_ss[1].pAddr); + // Replace instruction with managment breakpoint + *(mgmt_bp_ss[1].pAddr) = BP_MGMT_SS(2); + ICACHE_invalidate_at(mgmt_bp_ss[1].pAddr); + } + break; + + case 'P': + g_is_ss = 1; + leave_isr = 1; + // Don't overwrite RU breaks + if (is_user_bp) + break; + // Don't overwrite user breaks + if (IsBreak(*pInstr) && (BreakGetType(*pInstr) == BP_USER_BASE)) + break; + + // Save original instruction + mgmt_bp_ss[0].pAddr = (UINT32*)xcp->regs[0x1F]; + mgmt_bp_ss[0].instr = *(mgmt_bp_ss[0].pAddr); + // Replace instruction with managment breakpoint + *(mgmt_bp_ss[0].pAddr) = BP_MGMT_SS(1); + ICACHE_invalidate_at(mgmt_bp_ss[0].pAddr); + mgmt_bp_ss[1].pAddr = NULL; + mgmt_bp_ss[1].pAddr = 0; + break; + + default: + break; + } + } while (!leave_isr); + +} + +void debug_int(struct xcptcontext * xcp) +{ + dbg_handler(xcp); + +} + +int debug_break(struct xcptcontext * xcp) +{ + dbg_handler(xcp); + return 0; + +} + +void dbg_init(void) +{ + + interrupt_register(2, debug_int); + interrupt_enable(2); + + xcpt_register(Bp, debug_break); +} + diff --git a/lib/CPUs/MIPS/bsp/examples/gunzip.c b/lib/CPUs/MIPS/bsp/examples/gunzip.c new file mode 100644 index 0000000..20340da --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/gunzip.c @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include +#include +#include "crc32.h" +#include "inflate.h" +#include "libsys.h" + +char buffer[1024*1024]; +char * volatile pPtr_r; +char * volatile pPtr_w; +volatile int timeout_cnt; +volatile int file_len; + +void handler3(void) +{ + volatile UINT32 *pUART_stat = (UINT32*)sys_uart_stat; + volatile UINT32 *pUART_data = (UINT32*)sys_uart_data; + + while((0x10 & *pUART_stat)) + { +// sputs("w: "); print_word((int)pPtr_w); sputs("\n"); + if (pPtr_w == &buffer[sizeof(buffer)-1]) + pPtr_w = buffer; + *(pPtr_w++) = *pUART_data; + timeout_cnt = 100; + file_len++; + } + +} + +int READBYTE(z_stream *zs) { + if (zs->avail_in <= 0) + return -1; + + zs->avail_in --; + return *(zs->next_in ++); +} + +#define MAX_BUFOUT 16*1024*1024 +int main(int argc, char **argv) +{ + unsigned char outData[MAX_BUFOUT]; + FILE *infp; + int i, gpflags, tmp[4]; + unsigned long size, crc; + unsigned char *fileData; + unsigned long bytes, InflatedSize, InflatedCRC, speed_count; + z_stream zs; + time_t start_time, work_time; + + sputs("Reading gzipped stream..\n"); + + pPtr_r = buffer; + pPtr_w = buffer; + interrupt_register(3, handler3); + interrupt_enable(3); + + file_len = 0; + timeout_cnt = 1000000; + while(timeout_cnt--) + { + sleep(1); + } + + bytes = file_len; + fileData = pPtr_r; + + zs.next_in = fileData; + zs.avail_in = (unsigned int) bytes; + zs.next_out = outData; + zs.avail_out = MAX_BUFOUT; + + tmp[0] = READBYTE(&zs); + if (tmp[0] == -1) + { + // error reading from file + sputs("error reading data from file\n"); + return 0; + } + tmp[1] = READBYTE(&zs); + + if (tmp[0] != 0x1f || tmp[1] != 0x8b) { +// fprintf(stderr, "Magic number mismatch 0x%02x%02x\n", +// tmp[0], tmp[1]); + return 20; + } + + tmp[0] = READBYTE(&zs); + if(tmp[0] != 8) { +// fprintf(stderr, "Unknown compression method: 0x%02x\n", tmp[0]); + return 20; + } + + gpflags = READBYTE(&zs); + if ((gpflags & ~0x1f)) { + sputs("Unknown flags set!\n"); + } + + /* Skip file modification time (4 bytes) */ + READBYTE(&zs); + READBYTE(&zs); + READBYTE(&zs); + READBYTE(&zs); + /* Skip extra flags and operating system fields (2 bytes) */ + READBYTE(&zs); + READBYTE(&zs); + + if ((gpflags & 4)) { + /* Skip extra field */ + tmp[0] = READBYTE(&zs); + tmp[1] = READBYTE(&zs); + i = tmp[0] + 256*tmp[1]; + while (i--) + { + READBYTE(&zs); + } + } + if((gpflags & 8)) { + while((READBYTE(&zs))) { + } + } + if((gpflags & 16)) { + while((READBYTE(&zs))) { + } + } + if((gpflags & 2)) { + /* Skip CRC16 */ + READBYTE(&zs); + READBYTE(&zs); + } + + sputs("Go\n"); + // normal test + start_time = clock(); + if (InflateData(&zs)) + { + sputs("Problem during decompression!\n"); + return 0; + } + work_time = clock() - start_time; + + +/* + // speed test + fprintf(stdout, "SPEED TEST!\n"); + speed_count = 0; + while (time(NULL) - start_time < 20) + { + zs_speed.next_in = zs.next_in; + zs_speed.next_out = zs.next_out; + zs_speed.avail_in = zs.avail_in; + zs_speed.avail_out = zs.avail_out; + if (InflateData(&zs_speed)) + { + fprintf(stdout, "Problem during decompression!\n"); + return 0; + } + speed_count ++; + } + fprintf(stdout, "speed count %ld\n", speed_count); + zs.next_in = zs_speed.next_in; + zs.next_out = zs_speed.next_out; + zs.avail_in = zs_speed.avail_in; + zs.avail_out = zs_speed.avail_out; +*/ + + crc = READBYTE(&zs); + crc |= (READBYTE(&zs)<<8); + crc |= (READBYTE(&zs)<<16); + crc |= (READBYTE(&zs)<<24); + + size = READBYTE(&zs); + size |= (READBYTE(&zs)<<8); + size |= (READBYTE(&zs)<<16); + size |= (READBYTE(&zs)<<24); + + InflatedSize = MAX_BUFOUT - zs.avail_out; + InflatedCRC = MakeCRC32(outData, InflatedSize, 0); + +// write(1, outData, InflatedSize); + fprintf(stdout, "CRC: %08lx %08lx %s\n", crc, InflatedCRC, (crc != InflatedCRC)?"**error**":""); + fprintf(stdout, "Size: %08lx %08lx %s\n", size, InflatedSize, (size != InflatedSize)?"**error**":""); + fprintf(stdout, "Time for decompression was %.2f seconds\n", (float)work_time/1000); + fprintf(stdout, "Throughput is %d kByte/s\n", InflatedSize/work_time); + + return 0; +} diff --git a/lib/CPUs/MIPS/bsp/examples/inflate.c b/lib/CPUs/MIPS/bsp/examples/inflate.c new file mode 100644 index 0000000..d8e29e5 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/inflate.c @@ -0,0 +1,499 @@ +/* inflate routines for Palm OS (to inflate a deflated stream) + * + * Based heavily upon gunzip.c by Pasi Ojala + * http://www.cs.tut.fi/~albert/Dev/gunzip/ + * Many, many thanks for that code! + * + * Changes: + * 2002-12-30 - Added #defines to use zlib's struct instead of mine, just + * in case you want to compile it that way. + * 2002-12-29 - Found out that this is VERY slow. ZLib is 3x faster. + * Worked on speeding it up. Partially successful. Profiled + * code and marked critical areas. 1932 bytes added to a + * Palm program by linking in the .o file. Schweet! + * 2002-12-21 - Finished surgery. Only one function to inflate dynamic and + * fixed data. Rewrote table generation to be iterative. + * Hacked and slashed my way through unnecessary code. + * The size is now down to 3512 bytes. + * 2002-12-20 - Started major surgery + * 2002-12-19 - Looked at the code a bit more + * 2002-12-17 - Continued work. Down to about 6k for the .o file + * 2002-12-09 - Continued work, added z_stream_fid instead of globals + * 2002-12-08 - Started work so that it decompresses up to 64k (one memory + * chunk on the Palm. + * 2002-12-07 - Removed bit reverse table. Removed unzip code. + */ +#include "inflate.h" +#ifdef VERBOSE +#include // Just in case you put a printf() function back in +#endif + +void Status(char *, int); + +typedef struct HufNode_struct { + // b0 and b1 are either values in the tree array to jump to (branches) + // or are literal values. + // if (bX & 0x8000) + // value = bX ^ 0x8000; + // else + // link_to_array_element = bX; + unsigned int b0; // Bigger than 1 byte (2 is ideal) + unsigned int b1; // Bigger than 1 byte (2 is ideal) +} HufNode; + + +// Not that rhobust anymore -- If out of data, this will +// return a whole lot of 1 bits. +// +// This function consumes a large percentage of time (#1) +char READBIT(z_stream *zs) +{ + char carry; + + if (zs->reserved == 1) + { + if (zs->avail_in == 0) + return 1; + zs->reserved = *(zs->next_in ++) | 0x0100; + zs->avail_in --; + } + + carry = zs->reserved & 1; + zs->reserved >>= 1; + + return carry; +} + + +// Make sure that [a] is <= 16 +// If there are endian problems, force [a] to be <= 8 +// Might be faster if all (up to [a] bits) of zs->reserved was read into res +// right away. +// +// This function consumes a large percentage of time (#4) +int READBITS(z_stream *zs, int a) +{ + int res = 0, pos = 0; + + while (a --) + { + if (zs->reserved == 1) + { + if (zs->avail_in == 0) + return 1; + zs->reserved = *(zs->next_in ++) | 0x0100; + zs->avail_in --; + } + + res += (zs->reserved & 1) << pos; + zs->reserved >>= 1; + pos ++; + } + + return res; +} + + +// Huffman tree structures, variables and related routines +// +// These routines are one-bit-at-a-time decode routines. They +// are not as fast as multi-bit routines, but maybe a bit easier +// to understand and use a lot less memory. +// +// The tree is created in an array +// +// currentTree = where to put the tree (in an array) +// numval = Number of elements in the lengths array +// lengths = array of lengths +// +// +// This function consumes a large percentage of time (#5) +int CreateTree(HufNode *currentTree, int numval, unsigned char *lengths) { + int i, j, len; // basically scratch values + int BlankNode; // Where is the next blank array index + int this_code, mask, *bitData; // used in tree generation + int bl_count[16] = { 0, }; // Counter of code lengths + int next_code[16] = { 0, }; // Code for a specific length + // 16 = (15 is max length of a code when inflating) + (1 for zero) + + // Step 1: Count the code lengths + for (i = 0; i < numval; i ++) + { + j = lengths[i]; + if (j > 15) + return 1; + bl_count[j] ++; + } + + // Step 2: Find numerical value of the smallest code of each length + // Also note that I've inserted some weak validation code here. I'm + // not 100% sure that it is up to RFC specs, but it seems to work fine + // in my tests + // + // The validation theory is that at the root node, you have 2 branches or + // values possible. If you branch, you get 2 more potentials. If you + // get a value, you lose one potential. So, if the root node has one of + // each, the number of potentials at the next level is still two. If that + // node just has branches, the number of potentials is four. If both of + // the nodes on the following level just have values, the number of + // potentials is 0, leaving us with a complete tree. + // + // If I don't validate and if an invalid tree gets generated, an + // infinite loop is possible + bl_count[0] = 0; + j = 0; + len = 2; + for (i = 1; i < 16; i ++) + { + len -= bl_count[i]; + len *= 2; + j = (j + bl_count[i - 1]) << 1; + next_code[i] = j; + } + if (len) + return 1; + + + // Step 3: Assign numerical values to all codes + BlankNode = 1; + currentTree[0].b0 = 0x0000; + currentTree[0].b1 = 0x0000; + for (i = 0; i < numval; i ++) + { + len = lengths[i]; + if (len != 0) + { + this_code = next_code[len]; + next_code[len] ++; + mask = 1 << (len - 1); + j = 0; + while (mask > 1) + { + if (this_code & mask) + bitData = &(currentTree[j].b1); + else + bitData = &(currentTree[j].b0); + + if (*bitData == 0x0000) + { + *bitData = BlankNode; + j = BlankNode; + BlankNode ++; + currentTree[j].b0 = 0x0000; + currentTree[j].b1 = 0x0000; + } + else + j = *bitData; + + mask >>= 1; + } + if (this_code & 0x01) + currentTree[j].b1 = 0x8000 | i; + else + currentTree[j].b0 = 0x8000 | i; + } + } + +#ifdef VERBOSE + fprintf(stderr, "%d table entries used\n", + BlankNode); + if (numval < 20) { + for (i = 0; i < BlankNode; i ++) + { + fprintf(stderr, "0x%03x - ", i); + if (currentTree[i].b0 & 0x8000) + fprintf(stderr, "value: 0x%03x ", currentTree[i].b0 ^ 0x8000); + else + fprintf(stderr, " link: 0x%03x ", currentTree[i].b0); + + if (currentTree[i].b1 & 0x8000) + fprintf(stderr, "value: 0x%03x\n", currentTree[i].b1 ^ 0x8000); + else + fprintf(stderr, " link: 0x%03x\n", currentTree[i].b1); + } + } +#endif + + return 0; +} + + +// Using the tree passed in, read bits from the data stream until we arrive +// at the proper value +// +// This function consumes a large percentage of time (#2) +int DecodeValue(z_stream *zs, HufNode *currentTree) +{ + unsigned int i = 0; + + // decode one symbol of the data per iteration + // Infinite loop detection code could go here. Maximum + // bits to read is 15. + while (i < 0x8000) + { + if (READBIT(zs)) + i = currentTree[i].b1; + else + i = currentTree[i].b0; + } + return i & 0x7FFF; +} + + +int Decompress_Stored(z_stream *zs) +{ + int blockLen, cSum; + +#ifdef VERBOSE + fprintf(stderr, "Stored\n"); +#endif + + zs->reserved = 1;; + if (zs->avail_in < 4) + return -1; + + zs->avail_in -= 4; + blockLen = *(zs->next_in ++); + blockLen |= *(zs->next_in ++) << 8; + + cSum = *(zs->next_in ++); + cSum |= (*(zs->next_in ++) << 8); + + if ((blockLen + cSum) ^ 0xFFFF) + return 1; + if (zs->avail_in < blockLen || zs->avail_out < blockLen) + return -1; + zs->avail_in -= blockLen; + zs->avail_out -= blockLen; + + while (blockLen --) + { + *(zs->next_out) = *(zs->next_in); + zs->next_out ++; + zs->next_in ++; + } + + return 0; +} + + +int MakeTrees(z_stream *zs, char is_fixed, HufNode *literalTree, + HufNode *distanceTree) +{ + // Order of the bit length code lengths + static const unsigned border[] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + unsigned char ll[288+32]; + int i, j, n, l, literalCodes, distCodes; + + if (is_fixed) + { + literalCodes = 288; + + // Set a large range to 8 + for (i = 0; i < 288; i ++) + ll[i] = 8; + // In that range, set some to 9 and others to 7 + // (smaller code, but slightly slower table generation) + for (i = 144; i < 256; i ++) + ll[i] = 9; + for (; i < 280; i ++) + ll[i] = 7; + + distCodes = 32; + + for (i = 288; i < 320; i ++) + ll[i] = 5; + } + else + { + literalCodes = 257 + READBITS(zs, 5); + distCodes = 1 + READBITS(zs, 5); + l = 4 + READBITS(zs, 4); + + for (j = 0; j < 19; j ++) + ll[j] = 0; + + // Get the decode tree code lengths + // The decode tree is Huffman encoded + + for (j = 0; j < l; j++) + { + ll[border[j]] = READBITS(zs, 3); + } + + if (CreateTree(distanceTree, 19, ll)) + return 1; + + // read in literal and distance code lengths + n = literalCodes + distCodes; + i = 0; + while (i < n) + { + j = DecodeValue(zs, distanceTree); + if (j < 16) // length of code in bits (0..15) + ll[i++] = j; + else if (j == 16) + { // repeat last length 3 to 6 times + j = 3 + READBITS(zs, 2); + + if (i + j > n) + return 1; + + l = i ? ll[i-1] : 0; + while (j --) + ll[i++] = l; + } + else + { + if (j == 17) // 3 to 10 zero length codes + j = 3 + READBITS(zs, 3); + else // j == 18: 11 to 138 zero length codes + j = 11 + READBITS(zs, 7); + + if (i + j > n) + return 1; + + while (j --) + ll[i++] = 0; + } + } + } + + + // Can overwrite tree decode tree as it is not used anymore + if (CreateTree(literalTree, literalCodes, &ll[0])) + return 1; + + if(CreateTree(distanceTree, distCodes, &ll[literalCodes])) + return 1; + + return 0; +} + + +// This function consumes a large percentage of time (#3) +// Most output produced by gzip/zlib/etc is dynamic. +int Decompress_DynamicOrFixed(z_stream *zs, char is_fixed) +{ + // Copy lengths for literal codes 257..285 + static const unsigned short cplens[] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }; + // Extra bits for literal codes 257..285 + static const unsigned short cplext[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 }; // 99==invalid + // Copy offsets for distance codes 0..29 + static const unsigned short cpdist[] = { + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, + 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, + 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, + 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001 }; + // Extra bits for distance codes + static const unsigned short cpdext[] = { + 0, 0, 0, 0, 1, 1, 2, 2, + 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, + 11, 11, 12, 12, 13, 13 }; + HufNode literalTree[288]; + HufNode distanceTree[32]; + int j, l, dist; + +#ifdef VERBOSE + if (is_fixed) + fprintf(stderr, "Fixed Huffman codes\n"); + else + fprintf(stderr, "Dynamic Huffman codes\n"); +#endif + + if (MakeTrees(zs, is_fixed, literalTree, distanceTree)) + return 1; + + while (1) + { + j = DecodeValue(zs, literalTree); + if (j >= 256) + { + if (j == 256) // EOF + break; + + //printf("%04x ", j); + j -= 256 + 1; // bytes + EOF + + l = READBITS(zs, cplext[j]) + cplens[j]; + //printf("%04x ", l); + + j = DecodeValue(zs, distanceTree); + //printf("%02x ", j); + + dist = READBITS(zs, cpdext[j]) + cpdist[j]; + //printf("%04x ", dist); + + //printf("LZ77 len %d dist %d @%04x\n", l, dist, bIdx); + while(l--) + { + //printf("%02x ", c); + if (! zs->avail_out --) + return -1; + + *(zs->next_out ++) = *(zs->next_out - dist); + } + //printf("\n"); + } + else + { + //printf("%02x\n", j); + if (! zs->avail_out --) + return -1; + *(zs->next_out ++) = (unsigned char) j; + } + } + return 0; +} + + +// Returns 0 if success +int InflateData(z_stream *zs) { + int last, type; + + zs->reserved = 1;; + + do + { + last = READBIT(zs); +#ifdef VERBOSE + if (last) + fprintf(stderr, "Last Block: "); + else + fprintf(stderr, "Not Last Block: "); +#endif + + type = READBITS(zs, 2); + + if (type == 0) + { + if (Decompress_Stored(zs)) + return 1; + } + else if (type > 2) + { +#ifdef VERBOSE + if (type == 3) + fprintf(stderr, "Reserved block type!!\n"); + else // the "else" should never happen + fprintf(stderr, "Unexpected value %d!\n", type); +#endif + zs->reserved = 1;; + return 1; + } + else + { + if (Decompress_DynamicOrFixed(zs, type & 0x01)) + return 1; + } + } while(!last); + + zs->reserved = 1;; + return 0; +} diff --git a/lib/CPUs/MIPS/bsp/examples/inflate.h b/lib/CPUs/MIPS/bsp/examples/inflate.h new file mode 100644 index 0000000..1f6fd38 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/inflate.h @@ -0,0 +1,15 @@ +#ifdef USE_ZLIB_STRUCT +#include "SysZLib.h" // For PalmOS. Change to your liking. +#else +typedef struct z_stream_s +{ + unsigned char *next_in; // Next input byte (CHANGES) + unsigned int avail_in; // number of bytes left at next_in + unsigned char *next_out; // Next output byte goes here (CHANGES) + unsigned int avail_out; // number of bytes left at next_out + unsigned int reserved; // For the readbit() and readbits() functions + // Bigger than 1 byte +} z_stream; +#endif + +int InflateData(z_stream *zs); diff --git a/lib/CPUs/MIPS/bsp/examples/life.c b/lib/CPUs/MIPS/bsp/examples/life.c new file mode 100644 index 0000000..4da1708 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/life.c @@ -0,0 +1,249 @@ +/* life.c - demonstrator for later Mips+LCD game of life + * + * 23.03.06 - MACRO-based version + * 22.02.06 - new file + */ + +//#include "ks0108.h" + +#include +#include +#include +#include "libsys.h" + + +#define NX 200 // 70 // 128 // 48 // 128 +#define NY 150 // 31 // 64 // 27 // 64 + +#define SCREEN_X 800 +#define SCREEN_Y 600 + +#define SCALE_X (4) +#define SCALE_Y (4) +#define OFFSET_X ((SCREEN_X-(SCALE_X*NX))/2) +#define OFFSET_Y ((SCREEN_Y-(SCALE_Y*NY))/2) + +// OCCUPIED must be uneven, EMPTY even. +#define OCCUPIED 0x77771111 +#define EMPTY 0xeeee0000 + +#define MATRIX( row, col ) (*(matrix + (NX*col) + row )) +#define FUTURE( row, col ) (*(future + (NX*col) + row )) + +UINT32 *g_gx_buff; + +int clock_lfsr32() +{ + return rand(); +} + + +/* return a pseudo-random integer in the range 0..1023 */ +int random1023() { + int tmp; + + tmp = clock_lfsr32(); + return tmp & 0x000003ff; +} + +typedef struct _scolor_t +{ + UINT8 r, g, b, a; +} __attribute__ ((__packed__)) color_t; + + +void DrawPixel(UINT32 x, UINT32 y, color_t *pColor) +{ + int i, j; + for (i=0; i < SCALE_Y; i++) + for (j=0; j < SCALE_X; j++) + g_gx_buff[(OFFSET_X+SCALE_X*x+j) + SCREEN_X*(OFFSET_Y+SCALE_Y*y+i)] = *((UINT32*)pColor); +} + + +/* MSB/LSB in y-Richtung vertauscht */ +void displayBoard1( int* matrix ) +{ + int x, y; + int mask, accu; + UINT32 color; + + for( x=0; x < NX; x++ ) + { + mask = 0x80; + accu = 0x00; + for( y=0; y < NY; y++ ) + { + color = (UINT32)-(MATRIX(x,y) & 0x1); + DrawPixel(x, y, (color_t*)&color); +// if (MATRIX( x, y ) != OCCUPIED) +// { +// accu |= mask; +// } +// mask = mask >> 1; + +// color = 0; +// DrawPixel(x, (y>>3), (color_t*)&color); +// if (mask == 0) +// { +// color = accu; +// DrawPixel(x, (y>>3), (color_t*)&color); +// mask = 0x80; +// accu = 0x00; +// } + } +// color = accu; +// DrawPixel(x, (y>>3), (color_t*)&color); + + } +// *(matrix-15) = 0xdead0000; +// *(matrix-16) = *(matrix-16) + 1; +} + +void initializeBoard( int* matrix ) { + int x, y; + for( x=0; x < NX; x++ ) { + for( y=0; y < NY; y++ ) { + int d = random1023(); + if (d > 920) MATRIX( x, y ) = OCCUPIED; + else MATRIX( x, y ) = EMPTY; + } + } +} + + +int countNeighbors( int* matrix, int i, int j ) { + int im = i-1; + int ip = i+1; + + int jm = j-1; + int jp = j+1; + + int n = 0; + // wrap-around + if (ip >= NX) ip = 0; + if (jp >= NY) jp = 0; + + if (im < 0) im = NX-1; + if (jm < 0) jm = NY-1; + + // check eight neighbors + n += MATRIX(im, jm ) & 0x1; // nw + n += MATRIX(im, j ) & 0x1; // west + n += MATRIX(im, jp ) & 0x1; // sw + + n += MATRIX(i, jm ) & 0x1; // north + // n += MATRIX(i, j ) & 0x1; // center + n += MATRIX(i, jp ) & 0x1; // south + + n += MATRIX(ip, jm ) & 0x1; // ne + n += MATRIX(ip, j ) & 0x1; // east + n += MATRIX(ip, jp ) & 0x1; // se + + return n; +} + + +/** + * the actual game of life algorithm: cell is born when three neighbors, + * survives when exactly two live neighbors, dies otherwise. + */ +void nextGeneration( int* matrix, int* future ) { + int i, j; + int lifes = 0; + + for( i=0; i < NX; i++ ) { + for( j=0; j < NY; j++ ) { + // count neighbors + int n = countNeighbors( matrix, i, j ); + + //if ((n != 0) && (random1023() > 990)) { // some slight random offset + // if (random1023() > 500) FUTURE(i,j) = OCCUPIED; + // else FUTURE(i,j) = EMPTY; + //} + // else if (n == 3) FUTURE(i,j) = OCCUPIED; + + if (n == 3) FUTURE(i,j) = OCCUPIED; + else if ((n == 2) && (MATRIX(i,j) == OCCUPIED)) FUTURE(i,j) = OCCUPIED; + else FUTURE(i,j) = EMPTY; + + if (FUTURE(i,j) == OCCUPIED) lifes++; + } + } + // generation ++; + + // avoid extinction :-) + if (lifes < 10) { + // printf( "CREATING A NEW POPULATION\n\n\n" ); + initializeBoard( matrix ); + } + else { // swap buffers: C PROHIBITS ASSIGNING TO ARRAY TYPES + for( i=0; i < NX; i++ ) { + for( j=0; j < NY; j++ ) { + MATRIX(i,j) = FUTURE(i,j); + } + } + } +} + +void gx_init(void) +{ + volatile UINT32 *pVGA_mctrl = (UINT32*)sys_vga_mctrl; + volatile UINT32 *pVGA_moffs = (UINT32*)sys_vga_moffs; + + sleep(500); + + g_gx_buff = (UINT32*)malloc(SCREEN_X*SCREEN_Y*sizeof(UINT32)); + memset(g_gx_buff, 0, SCREEN_X*SCREEN_Y*sizeof(UINT32)); + printf("g_gx_buff : %8.8X\n", (UINT32)g_gx_buff); + + *pVGA_mctrl = 1; + *pVGA_moffs = (UINT32)g_gx_buff; + +} + +int main( int argc, char* argv[] ) { + + int* ptr, cnt = 0; + + int* matrix; + int* future; + volatile UINT32 *pBtn = (UINT32*)sys_gpio0; + + // lcdEnableDisplay( 1 ); + // lcdSetColor( 1 ); + // lcdSetPixel( 0, 0 ); + // lcdSetPixel( 3, 5 ); + + // if we have stdlib: + matrix = (void*) malloc( NX*NY*sizeof(int) ); + future = (void*) malloc( NX*NY*sizeof(int) ); + + + gx_init(); + +// matrix = (void *) 0x00004000; +// future = (void *) 0x00014000; + + // init_lfsr32( 0xcafebabe ); + // init_lfsr32( 0x13 ); + + srand(clock()); + initializeBoard( matrix ); + + while( 1 ) + { + + if (*pBtn) + { + srand(clock()); + initializeBoard( matrix ); + cnt = 0; + } + sputs("Generation #"); print_word(cnt++); sputs("\n"); + displayBoard1( matrix ); + nextGeneration( matrix, future ); + } + + // return 0 +} diff --git a/lib/CPUs/MIPS/bsp/examples/mipsdis.c b/lib/CPUs/MIPS/bsp/examples/mipsdis.c new file mode 100644 index 0000000..2dceda3 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/mipsdis.c @@ -0,0 +1,625 @@ +/* +----------------------------------------------------------------+ */ +/* | Copyright (c) 1994 Stanford University. | */ +/* | All Rights Reserved. | */ +/* | | */ +/* | This software is distributed with *ABSOLUTELY NO SUPPORT* | */ +/* | and *NO WARRANTY*. Use or reproduction of this code for | */ +/* | commerical gains is strictly prohibited. Otherwise, you | */ +/* | are given permission to use or modify this code as long | */ +/* | as you do not remove this notice. | */ +/* +----------------------------------------------------------------+ */ +/* --------------------------------------------------- */ +/* | Copyright (c) 1986 MIPS Computer Systems, Inc. | */ +/* | All Rights Reserved. | */ +/* --------------------------------------------------- */ + +/* + * Copyright 1985 by MIPS Computer Systems, Inc. + */ + +/* TORCH disassembler */ +/* derived from MIPS instruction dissassembler by PGL October 91 */ + +#include +#include +#include "mipsdis.h" + +#define false 0 +#define true 1 +typedef int boolean; +char *strcat(); + +#define ZERO 0 + +#define COMPILER_NAMES tdis_reg_names[0] +#define HARDWARE_NAMES tdis_reg_names[1] +#define ASSEMBLER_NAMES tdis_reg_names[2] +#define DIS_REG_NAMES(x) tdis_reg_names[x] + +union extension_byte { + unsigned char byte; + struct { /* extension byte bits in little-endian order */ +#if (defined __MIPSEB || defined _MIPSEB || defined MIPSEB) + unsigned reserved:1; + unsigned dyn_nop:1; + unsigned rs_boost:2; + unsigned rt_boost:2; + unsigned rd_boost:2; +#elif (defined __MIPSEL || defined _MIPSEL || defined MIPSEL) + unsigned rd_boost:2; + unsigned rt_boost:2; + unsigned rs_boost:2; + unsigned dyn_nop:1; + unsigned reserved:1; +#endif /*MIPSEB*/ + } e; +}; + +#define blez_op_T blez_op +#define blez_op_N (blez_op | 0x10) +#define bgtz_op_T bgtz_op +#define bgtz_op_N (bgtz_op | 0x10) +#define beq_op_T beq_op +#define beq_op_N (beq_op | 0x10) +#define bne_op_T bne_op +#define bne_op_N (bne_op | 0x10) +#define bc_op_T bc_op +#define bc_op_N (bc_op | 0x02) + +static char *op_name[64] = { +/* 0 */ "special", "regimm","j", "jal", "beq", "bne", "blez", "bgtz", +/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui", +/*16 */ "cop0", "cop1", "cop2", "cop3", "beql","bnel","blezl","bgtzl", +/*24 */ "op60", "op64", "op68", "op6c", "op70", "op74", "op78", "op7c", +/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "ld", +/*40 */ "sb", "sh", "swl", "sw", "opb0", "opb4", "swr", "sd", +/*48 */ "lwc0", "lwc1", "lwc2", "lwc3", "ldc0", "ldc1", "ldc2", "ldc3", +/*56 */ "swc0", "swc1", "swc2", "swc3", "sdc0", "sdc1", "sdc2", "sdc3" +}; + +static char *spec_name[64] = { +/* 0*/ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav", +/* 8*/ "jr", "jalr", "spec12","spec13","syscall","break","vcall","spec17", +/*16*/ "mfhi", "mthi", "mflo", "mtlo", "spec24","spec25","spec26","spec27", +/*24*/ "mult", "multu","div", "divu", "spec34","spec35","spec36","spec37", +/*32*/ "add", "addu", "sub", "subu", "and", "or", "xor", "nor", +/*40*/ "spec50","spec51","slt","sltu", "spec54","spec55","spec56","spec57", +/*48*/ "spec60","spec61","spec62","spec63","spec64","spec65","spec66","spec67", +/*56*/ "spec70","spec71","spec72","spec73","spec74","spec75","spec76","spec77" +}; + +static char *bcond_name[32] = { + "bltz", + "bgez", + "bltzl", + "bgezl", + "bcond04", + "bcond05", + "bcond06", + "bcond07", + "tgei", + "tgeiu", + "tlti", + "tltiu", + "teqi", + "bcond0d", + "tnei", + "bcond0f", + "bltzal", + "bgezal", + "bltzall", + "bgezall", + "bcond14", + "bcond15", + "bcond16", + "bcond17", + "bcond18", + "bcond19", + "bcond1a", + "bcond1b", + "bcond1c", + "bcond1d", + "bcond1e", + "bcond1f" +}; + +static char *cop1_name[64] = { +/* 0 */ "add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg", +/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f", +/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17", +/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f", +/*32 */ "cvt.s","cvt.d","cvt.e","fop23","cvt.w","fop25","fop26","fop27", +/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f", +/*48 */ "c.f", "c.un","c.eq","c.ueq","c.olt","c.ult","c.ole","c.ule", +/*56 */ "c.sf","c.ngle","c.seq","c.ngl","c.lt","c.nge","c.le","c.ngt" +}; + +static char *fmt_name[16] = { + "s", "d", "e", "q", + "w", "fmt5", "fmt6", "fmt7", + "fmt8", "fmt9", "fmta", "fmtb", + "fmtc", "fmtd", "fmte", "fmtf" +}; + +/* public */ +/* Three sets of commonly used register names */ +const char *tdis_reg_names[3][64] = { + { /* compiler names */ + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", + "zero.B","at.B","v0.B", "v1.B", "a0.B", "a1.B", "a2.B", "a3.B", + "t0.B", "t1.B", "t2.B", "t3.B", "t4.B", "t5.B", "t6.B", "t7.B", + "s0.B", "s1.B", "s2.B", "s3.B", "s4.B", "s5.B", "s6.B", "s7.B", + "t8.B", "t9.B", "k0.B", "k1.B", "gp.B", "sp.B", "s8.B", "ra.B" + }, + { /* hardware names */ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "gp", "sp", "r30", "r31", + "r0.B", "r1.B", "r2.B", "r3.B", "r4.B", "r5.B", "r6.B", "r7.B", + "r8.B", "r9.B", "r10.B","r11.B","r12.B","r13.B","r14.B","r15.B", + "r16.B","r17.B","r18.B","r19.B","r20.B","r21.B","r22.B","r23.B", + "r24.B","r25.B","r26.B","r27.B","gp.B", "sp.B", "r30.B","r31.B" + }, + { /* assembler names */ + "$0", "$at", "$2", "$3", "$4", "$5", "$6", "$7", + "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", + "$24", "$25", "$26", "$27", "$gp", "$sp", "$30", "$31", + "$0.B", "$at.B","$2.B", "$3.B", "$4.B", "$5.B", "$6.B", "$7.B", + "$8.B", "$9.B", "$10.B","$11.B","$12.B","$13.B","$14.B","$15.B", + "$16.B","$17.B","$18.B","$19.B","$20.B","$21.B","$22.B","$23.B", + "$24.B","$25.B","$26.B","$27.B","$gp.B","$sp.B","$30.B","$31.B" + } +}; + +static char *c0_opname[64] = { + "c0op0","tlbr","tlbwi","c0op3","c0op4","c0op5","tlbwr","c0op7", + "tlbp","c0op9","c0op10","c0op11","c0op12","c0op13","c0op14","c0op15", + "rfe","c0op17","c0op18","c0op19","c0op20","c0op21","c0op22","c0op23", + "c0op24","c0op25","c0op26","c0op27","c0op28","c0op29","c0op30","c0op31", + "c0op32","c0op33","c0op34","c0op35","c0op36","c0op37","c0op38","c0op39", + "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47", + "c0op48","c0op49","c0op50","c0op51","c0op52","c0op53","c0op54","c0op55", + "c0op56","c0op57","c0op58","c0op59","c0op60","c0op61","c0op62","c0op63" +}; + +static char *c0_reg[32] = { + "index","random","tlblo","c0r3","context","c0r5","c0r6","c0r7", + "badvaddr","c0r9","tlbhi","epcn","sr", "cause","epc", "c0r15", + "c0r16","c0r17","c0r18","c0r19","c0r20","c0r21","c0r22","c0r23", + "c0r24","c0r25","c0r26","c0r27","c0r28","c0r29","c0r30","c0r31" +}; + +/* Remember the options set by dis_init */ +//#define ADDR_DEFAULT "%#010x:\t" +#define ADDR_DEFAULT 0 +//#define VALUE_DEFAULT "%#010x\t" +#define VALUE_DEFAULT 0 +#define NAME_DEFAULT COMPILER_NAMES +static struct { + char *addr_format; + char *value_format; + const char **reg_names; + int print_jal_targets; +} save = { + ADDR_DEFAULT, + VALUE_DEFAULT, + NAME_DEFAULT, + true +}; + +/* Update regmask to reflect the use of this general-purpose (not fp) + register, and return its name */ +static const char * +register_name(ireg, boosted, regmask) +unsigned ireg, *regmask; +int boosted; +{ + if (!boosted) + *regmask |= (1 << ireg); + return save.reg_names[boosted ? ireg + 32 : ireg]; +} + +/* public -- see dissassembler.h */ +int +tdisasm(buffer, address, iword, ext, regmask, symbol_value, ls_register) +char *buffer; +unsigned char ext; /* extension byte */ +unsigned address, iword, *regmask, *symbol_value, *ls_register; +{ + int return_value = 0; + char *bufptr = buffer; + boolean do_b_displacement = false; + boolean do_loadstore = false; + union mips_instruction i; + union extension_byte e; + + *bufptr = 0; + i.word = iword; + e.byte = ext; + *regmask = *symbol_value = *ls_register = 0; + + /* Put out the address and hex value of the instruction, + leaving bufptr set at the end */ + if (save.addr_format) { + sprintf(bufptr, save.addr_format, address); + bufptr += strlen(bufptr); + } + if (save.value_format) { + sprintf(bufptr, save.value_format, iword); + bufptr += strlen(bufptr); + } + + /* check for dynamic NOP */ + if (e.e.dyn_nop) { + strcat(bufptr, "D."); + bufptr += 2; + } + + /* decode the instruction */ + switch (i.j_format.opcode) { + + case spec_op: + + if (i.word == 0x20) { + strcat(bufptr, "nop"); + if (e.e.rd_boost) + strcat(bufptr, ".B"); + bufptr += strlen(bufptr); + break; + } else if (i.r_format.func == addu_op && i.r_format.rt == ZERO) { + sprintf(bufptr, "move%s\t%s,%s", + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rd, e.e.rd_boost, regmask), + register_name(i.r_format.rs, e.e.rs_boost, regmask)); + bufptr += strlen(bufptr); + break; + } + strcat(bufptr, spec_name[i.r_format.func]); + if (e.e.rd_boost) + strcat(bufptr, ".B"); + bufptr += strlen(bufptr); + + switch (i.r_format.func) { + case sll_op: + case srl_op: + case sra_op: + sprintf(bufptr, "\t%s,%s,%d", + register_name(i.r_format.rd, e.e.rd_boost, regmask), + register_name(i.r_format.rt, e.e.rt_boost, regmask), + i.r_format.re); + break; + case sllv_op: + case srlv_op: + case srav_op: + sprintf(bufptr, "\t%s,%s,%s", + register_name(i.r_format.rd, e.e.rd_boost, regmask), + register_name(i.r_format.rt, e.e.rt_boost, regmask), + register_name(i.r_format.rs, e.e.rs_boost, regmask)); + break; + case mfhi_op: + case mflo_op: + sprintf(bufptr, "\t%s", + register_name(i.r_format.rd, e.e.rd_boost, regmask)); + break; + case jalr_op: + return_value = 3; + sprintf(bufptr, "\t%s,%s", + register_name(i.r_format.rd, e.e.rd_boost, regmask), + register_name(i.r_format.rs, e.e.rs_boost, regmask)); + *ls_register = i.r_format.rs; + break; + case jr_op: + return_value = 3; + *ls_register = i.r_format.rs; + /* fall through */ + case mtlo_op: + case mthi_op: + sprintf(bufptr, "\t%s", + register_name(i.r_format.rs, e.e.rs_boost, regmask)); + break; + case mult_op: + case multu_op: + case div_op: + case divu_op: + sprintf(bufptr, "\t%s,%s", + register_name(i.r_format.rs, e.e.rs_boost, regmask), + register_name(i.r_format.rt, e.e.rt_boost, regmask)); + break; + case syscall_op: + break; + case break_op: + case vcall_op: + { + char *format = "\t%d"; + unsigned op2 = i.r_format.rd * 32 + i.r_format.re; + + if (op2) + format = "\t%d,%d"; + sprintf(bufptr, format, i.r_format.rs*32+i.r_format.rt, + op2); + } + break; + default: + sprintf(bufptr, "\t%s,%s,%s", + register_name(i.r_format.rd, e.e.rd_boost, regmask), + register_name(i.r_format.rs, e.e.rs_boost, regmask), + register_name(i.r_format.rt, e.e.rt_boost, regmask)); + break; + }; + break; + + case bcond_op: + sprintf(bufptr, "%s%s\t%s,", + bcond_name[i.i_format.rt], + e.e.rd_boost ? ".B" : "", + register_name(i.i_format.rs, e.e.rs_boost, regmask)); + do_b_displacement = true; + break; + + case blez_op_T: + case bgtz_op_T: + case blez_op_N: + case bgtz_op_N: + sprintf(bufptr, "%s%s\t%s,", op_name[i.i_format.opcode], + e.e.rd_boost ? ".B" : "", + register_name(i.i_format.rs, e.e.rs_boost, regmask)); + do_b_displacement = true; + break; + case beq_op_T: + case beq_op_N: + if (i.i_format.rs == ZERO && i.i_format.rt == ZERO) { + strcat(bufptr, "b"); + if (i.j_format.opcode == beq_op_T) + strcat(bufptr, ".T"); + else + strcat(bufptr, ".N"); + if (e.e.rd_boost) + strcat(bufptr, ".B\t"); + else + strcat(bufptr, "\t"); + do_b_displacement = true; + break; + } + /* fall through */ + case bne_op_T: + case bne_op_N: + sprintf(bufptr, "%s%s\t%s,%s,", op_name[i.i_format.opcode], + e.e.rd_boost ? ".B" : "", + register_name(i.i_format.rs, e.e.rs_boost, regmask), + register_name(i.i_format.rt, e.e.rt_boost, regmask)); + do_b_displacement = true; + break; + + case cop0_op: + case cop1_op: + case cop2_op: + case cop3_op: + { + unsigned which_cop = i.j_format.opcode - cop0_op; + char *f_or_r = "rf"; + + switch (i.r_format.rs) { + case bc_op_T: + sprintf(bufptr, "bc%d%c.T%s\t", which_cop, + "ft"[i.r_format.rt], + e.e.rd_boost ? ".B" : ""); + do_b_displacement = true; + break; + case bc_op_N: + sprintf(bufptr, "bc%d%c.N%s\t", which_cop, + "ft"[i.r_format.rt], + e.e.rd_boost ? ".B" : ""); + do_b_displacement = true; + break; + case mtc_op: + if (which_cop == 0) + sprintf(bufptr, "mtc%d%s\t%s,%s", which_cop, + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rt, e.e.rt_boost,regmask), + c0_reg[i.f_format.rd]); + else + sprintf(bufptr, "mtc%d%s\t%s,%c%d", which_cop, + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rt, e.e.rt_boost,regmask), + f_or_r[(which_cop == 1)], + i.f_format.rd); + break; + case mfc_op: + if (which_cop == 0) + sprintf(bufptr, "mfc%d%s\t%s,%s", which_cop, + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rt, e.e.rt_boost,regmask), + c0_reg[i.f_format.rd]); + else + sprintf(bufptr, "mfc%d%s\t%s,%c%d", which_cop, + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rt, e.e.rt_boost,regmask), + f_or_r[(which_cop == 1)], + i.f_format.rd); + break; + case cfc_op: + sprintf(bufptr, "cfc%d%s\t%s,%c%d", which_cop, + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rt, e.e.rt_boost, regmask), + f_or_r[(which_cop == 1)], + i.f_format.rd); + break; + case ctc_op: + sprintf(bufptr, "ctc%d%s\t%s,%c%d", which_cop, + e.e.rd_boost ? ".B" : "", + register_name(i.r_format.rt, e.e.rt_boost, regmask), + f_or_r[(which_cop == 1)], + i.f_format.rd); + break; + default: + if (which_cop != 1) + sprintf(bufptr, "c0%s\t%s", e.e.rd_boost ? ".B" : "", + c0_opname[i.f_format.func]); + else + { + sprintf(bufptr, "%s.%s%s\t", + cop1_name[i.f_format.func], + fmt_name[i.f_format.fmt], + e.e.rd_boost ? ".B" : ""); + bufptr += strlen(bufptr); + switch (i.f_format.func) { + case fsqrt_op: + case fabs_op: + case fmov_op: + case fcvts_op: + case fcvtd_op: + case fcvte_op: + case fcvtw_op: + sprintf(bufptr, "f%d,f%d", + i.f_format.re, + i.f_format.rd); + break; + case fcmp_op+0x0: + case fcmp_op+0x1: + case fcmp_op+0x2: + case fcmp_op+0x3: + case fcmp_op+0x4: + case fcmp_op+0x5: + case fcmp_op+0x6: + case fcmp_op+0x7: + case fcmp_op+0x8: + case fcmp_op+0x9: + case fcmp_op+0xa: + case fcmp_op+0xb: + case fcmp_op+0xc: + case fcmp_op+0xd: + case fcmp_op+0xe: + case fcmp_op+0xf: + sprintf(bufptr, "f%d,f%d", + i.f_format.rd, + i.f_format.rt); + break; + default: + sprintf(bufptr, "f%d,f%d,f%d", + i.f_format.re, + i.f_format.rd, + i.f_format.rt); + break; + } /* switch on func */ + } + break; /* End of default */ + } /* switch on rs */ + } + break; /* End of cop0, cop1, cop2, cop3 */ + + case jal_op: + case j_op: + sprintf(bufptr, "%s%s\t", op_name[i.j_format.opcode], + e.e.rd_boost ? ".B" : ""); + *symbol_value = (address & 0xF0000000) | i.j_format.target << 2; + if (save.print_jal_targets) + { + bufptr += strlen(bufptr); + sprintf(bufptr, "%#x", *symbol_value); + } + return_value = 1; + break; + + case swc1_op: + case sdc1_op: + case lwc1_op: + case ldc1_op: + sprintf(bufptr, "%s%s\tf%d,", op_name[i.i_format.opcode], + e.e.rd_boost ? ".B" : "", + i.i_format.rt); + do_loadstore = true; + break; + + case lb_op: + case lh_op: + case lw_op: + case ld_op: + case lbu_op: + case lhu_op: + case sb_op: + case sh_op: + case sw_op: + case sd_op: + case lwl_op: + case lwr_op: + sprintf(bufptr, "%s%s\t%s,", op_name[i.i_format.opcode], + e.e.rd_boost ? ".B" : "", + register_name(i.i_format.rt, e.e.rt_boost, regmask)); + do_loadstore = true; + break; + + case ori_op: + case xori_op: + if (i.u_format.rs == ZERO) { + sprintf(bufptr, "li%s\t%s,%d", + e.e.rd_boost ? ".B" : "", + register_name(i.u_format.rt, e.e.rt_boost, regmask), + i.u_format.uimmediate); + break; + } + /* fall through */ + case andi_op: + sprintf(bufptr, "%s%s\t%s,%s,%#x", op_name[i.u_format.opcode], + e.e.rd_boost ? ".B" : "", + register_name(i.u_format.rt, e.e.rt_boost, regmask), + register_name(i.u_format.rs, e.e.rs_boost, regmask), + i.u_format.uimmediate); + break; + case lui_op: + sprintf(bufptr, "%s%s\t%s,%#x", op_name[i.u_format.opcode], + e.e.rd_boost ? ".B" : "", + register_name(i.u_format.rt, e.e.rt_boost, regmask), + i.u_format.uimmediate); + break; + case addi_op: + case addiu_op: + if (i.i_format.rs == ZERO) { + short sign_extender = i.i_format.simmediate; + sprintf(bufptr, "li%s\t%s,%d", + e.e.rd_boost ? ".B" : "", + register_name(i.i_format.rt, e.e.rt_boost, regmask), + sign_extender); + break; + } + /* fall through */ + default: + { + short sign_extender = i.i_format.simmediate; + sprintf(bufptr, "%s%s\t%s,%s,%d", op_name[i.i_format.opcode], + e.e.rd_boost ? ".B" : "", + register_name(i.i_format.rt, e.e.rt_boost, regmask), + register_name(i.i_format.rs, e.e.rs_boost, regmask), + sign_extender); + } + break; + } + + /* Some instructions require more than just registers */ + + if (do_loadstore) + { + short sign_extender = i.i_format.simmediate; + *symbol_value = sign_extender; + *ls_register = i.i_format.rs; + bufptr += strlen(bufptr); + sprintf(bufptr, "%d(%s)", sign_extender, + register_name(i.i_format.rs, e.e.rs_boost, regmask)); + return_value = -1; + } + else if (do_b_displacement) + { + short sign_extender = i.i_format.simmediate; + bufptr += strlen(bufptr); + *symbol_value = 4 + address + ((((long)sign_extender & 0xFFFD0000) | (0x3FFFF & (sign_extender << 2)))); + sprintf(bufptr, "%#x", *symbol_value); + return_value = 2; + } + + return return_value; +} + diff --git a/lib/CPUs/MIPS/bsp/examples/mipsdis.h b/lib/CPUs/MIPS/bsp/examples/mipsdis.h new file mode 100644 index 0000000..2e9aca4 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/mipsdis.h @@ -0,0 +1,450 @@ +/* ------------------------------------------------------------------ */ +/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */ +/* | Reserved. This software contains proprietary and confidential | */ +/* | information of MIPS and its suppliers. Use, disclosure or | */ +/* | reproduction is prohibited without the prior express written | */ +/* | consent of MIPS. | */ +/* ------------------------------------------------------------------ */ +/* inst.h 4.2 */ +/* + * inst.h -- instruction format defines + */ + +/** + ** UPDATE - 19 Sept 89 by Michael Smith + ** + ** Removed signed type to remove obnoxious C++ warning message. + **/ + +#ifdef LANGUAGE_C +#ifdef MIPSEB +union mips_instruction { + unsigned word; + unsigned char byte[4]; + struct { + unsigned opcode : 6; + unsigned target : 26; + } j_format; + struct { + unsigned opcode : 6; + unsigned rs : 5; + unsigned rt : 5; + unsigned simmediate : 16; + } i_format; + struct { + unsigned opcode : 6; + unsigned rs : 5; + unsigned rt : 5; + unsigned uimmediate : 16; + } u_format; + struct { + unsigned opcode : 6; + unsigned rs : 5; + unsigned rt : 5; + unsigned rd : 5; + unsigned re : 5; + unsigned func : 6; + } r_format; + struct { + unsigned opcode : 6; + unsigned : 1; + unsigned fmt : 4; + unsigned rt : 5; + unsigned rd : 5; + unsigned re : 5; + unsigned func : 6; + } f_format; +}; +#endif + +#ifdef MIPSEL +union mips_instruction { + unsigned word; + unsigned char byte[4]; + struct { + unsigned target : 26; + unsigned opcode : 6; + } j_format; + struct { + unsigned simmediate : 16; + unsigned rt : 5; + unsigned rs : 5; + unsigned opcode : 6; + } i_format; + struct { + unsigned uimmediate : 16; + unsigned rt : 5; + unsigned rs : 5; + unsigned opcode : 6; + } u_format; + struct { + unsigned func : 6; + unsigned re : 5; + unsigned rd : 5; + unsigned rt : 5; + unsigned rs : 5; + unsigned opcode : 6; + } r_format; + struct { + unsigned func : 6; + unsigned re : 5; + unsigned rd : 5; + unsigned rt : 5; + unsigned fmt : 4; + unsigned : 1; + unsigned opcode : 6; + } f_format; +}; +#endif + +#define spec_op 0x00 +#define bcond_op 0x01 +#define j_op 0x02 +#define jal_op 0x03 + +#define beq_op 0x04 +#define bne_op 0x05 +#define blez_op 0x06 +#define bgtz_op 0x07 + +#define addi_op 0x08 +#define addiu_op 0x09 +#define slti_op 0x0A +#define sltiu_op 0x0B + +#define andi_op 0x0C +#define ori_op 0x0D +#define xori_op 0x0E +#define lui_op 0x0F + +#define lb_op 0x20 +#define lh_op 0x21 +#define lw_op 0x23 +#define lbu_op 0x24 +#define lhu_op 0x25 +#define ld_op 0x27 +#define sb_op 0x28 +#define sh_op 0x29 +#define sw_op 0x2B +#define sd_op 0x2F +#define lwl_op 0x22 +#define lwr_op 0x26 +#define swl_op 0x2a +#define swr_op 0x2e + +/* Co-processor sub-opcodes */ +#define bc_op 0x08 +#define mfc_op 0x00 +#define cfc_op 0x02 +#define mtc_op 0x04 +#define ctc_op 0x06 + +/* Co-processor 0 opcodes */ +#define cop0_op 0x10 +#define lwc0_op 0x30 +#define ldc0_op 0x34 +#define swc0_op 0x38 +#define sdc0_op 0x3c + +/* Co-processor 0 sub-opcodes */ +#define tlbr_op 0x1 +#define tlbwi_op 0x2 +#define tlbwr_op 0x6 +#define tlbp_op 0x8 +#define rfe_op 0x10 + +/* Co-processor 1 opcodes */ +#define cop1_op 0x11 +#define lwc1_op 0x31 +#define ldc1_op 0x35 +#define swc1_op 0x39 +#define sdc1_op 0x3D + +/* Co-processor 1 sub-opcodes */ +#define fadd_op 0x00 +#define fsub_op 0x01 +#define fmpy_op 0x02 +#define fdiv_op 0x03 +#define fsqrt_op 0x04 +#define fabs_op 0x05 +#define fmov_op 0x06 +#define fneg_op 0x07 +#define fcvts_op 0x20 +#define fcvtd_op 0x21 +#define fcvte_op 0x22 +#define fcvtw_op 0x24 +#define fcmp_op 0x30 +#define s_fmt 0 +#define d_fmt 1 +#define e_fmt 2 +#define w_fmt 4 + +/* Other coprocessor opcodes */ +#define cop2_op 0x12 +#define lwc2_op 0x32 +#define ldc2_op 0x36 +#define swc2_op 0x3a +#define sdc2_op 0x3e + +#define cop3_op 0x13 +#define lwc3_op 0x33 +#define ldc3_op 0x37 +#define swc3_op 0x3b +#define sdc3_op 0x3f + + +/* bcond subopcodes */ +#define bltz_op 0x00 +#define bgez_op 0x01 +#define bltzal_op 0x10 +#define bgezal_op 0x11 + +/* special subopcodes */ +#define sll_op 0x00 +#define srl_op 0x02 +#define sra_op 0x03 +#define sllv_op 0x04 +#define srlv_op 0x06 +#define srav_op 0x07 +#define jr_op 0x08 +#define jalr_op 0x09 +#define syscall_op 0x0C +#define break_op 0x0D +#define vcall_op 0x0E + +#define mfhi_op 0x10 +#define mthi_op 0x11 +#define mflo_op 0x12 +#define mtlo_op 0x13 +#define mult_op 0x18 +#define multu_op 0x19 +#define div_op 0x1A +#define divu_op 0x1B + +#define add_op 0x20 +#define addu_op 0x21 +#define and_op 0x24 +#define or_op 0x25 +#define xor_op 0x26 +#define nor_op 0x27 +#define sub_op 0x22 +#define subu_op 0x23 +#define slt_op 0x2A +#define sltu_op 0x2B + +#endif /* LANGUAGE_C */ + +#ifdef LANGUAGE_PASCAL + +#ifdef MIPSEB +type + mips_instruction = + packed record + case cardinal of + 0: ( + word: cardinal; + ); + 1: ( + byte: packed array[0..3] of 0..255; + ); + 2: ( + opcode: 0..63; + target: 0..67108863; + ); + 3: ( + opcode3: 0..63; + rs: 0..31; + rt: 0..31; + simmediate: -32768..32767; + ); + 4: ( + opcode4: 0..63; + rs4: 0..63; + rt4: 0..63; + uimmediate: 0..65535; + ); + 5: ( + opcode5: 0..63; + rs5: 0..63; + rt5: 0..63; + rd5: 0..63; + re5: 0..63; + func: 0..63; + ); + end {record}; +#endif + +#ifdef MIPSEL +type + mips_instruction = + packed record + case cardinal of + 0: ( + word: cardinal; + ); + 1: ( + byte: packed array[0..3] of 0..255; + ); + 2: ( + target: 0..67108863; + opcode: 0..63; + ); + 3: ( + simmediate: -32768..32767; + rt: 0..31; + rs: 0..31; + opcode3: 0..63; + ); + 4: ( + uimmediate: 0..65535; + rt4: 0..63; + rs4: 0..63; + opcode4: 0..63; + ); + 5: ( + func: 0..63; + re5: 0..63; + rd5: 0..63; + rt5: 0..63; + rs5: 0..63; + opcode5: 0..63; + ); + end {record}; +#endif + +#define spec_op 16#00 +#define bcond_op 16#01 +#define j_op 16#02 +#define jal_op 16#03 + +#define beq_op 16#04 +#define bne_op 16#05 +#define blez_op 16#06 +#define bgtz_op 16#07 + +#define addi_op 16#08 +#define addiu_op 16#09 +#define slti_op 16#0A +#define sltiu_op 16#0B + +#define andi_op 16#0C +#define ori_op 16#0D +#define xori_op 16#0E +#define lui_op 16#0F + +#define lb_op 16#20 +#define lh_op 16#21 +#define lw_op 16#23 +#define lbu_op 16#24 +#define lhu_op 16#25 +#define ld_op 16#27 +#define sb_op 16#28 +#define sh_op 16#29 +#define sw_op 16#2B +#define sd_op 16#2F +#define lwl_op 16#22 +#define lwr_op 16#26 +#define swl_op 16#2a +#define swr_op 16#2e + +/* Co-processor sub-opcodes */ +#define bc_op 16#08 +#define mfc_op 16#00 +#define cfc_op 16#02 +#define mtc_op 16#04 +#define ctc_op 16#06 + +/* Co-processor 0 opcodes */ +#define cop0_op 16#10 +#define lwc0_op 16#30 +#define ldc0_op 16#34 +#define swc0_op 16#38 +#define sdc0_op 16#3c + +/* Co-processor 0 sub-opcodes */ +#define tlbr_op 16#1 +#define tlbwi_op 16#2 +#define tlbwr_op 16#6 +#define tlbp_op 16#8 +#define rfe_op 16#10 + +/* Co-processor 1 opcodes */ +#define cop1_op 16#11 +#define lwc1_op 16#31 +#define ldc1_op 16#35 +#define swc1_op 16#39 +#define sdc1_op 16#3D + +/* Co-processor 1 sub-opcodes */ +#define fadd_op 16#00 +#define fsub_op 16#01 +#define fmpy_op 16#02 +#define fdiv_op 16#03 +#define fsqrt_op 16#04 +#define fabs_op 16#05 +#define fmov_op 16#06 +#define fneg_op 16#07 +#define fcvts_op 16#20 +#define fcvtd_op 16#21 +#define fcvte_op 16#22 +#define fcvtw_op 16#24 +#define fcmp_op 16#30 +#define s_fmt 0 +#define d_fmt 1 +#define e_fmt 2 +#define w_fmt 4 + +/* Other coprocessor opcodes */ +#define cop2_op 16#12 +#define lwc2_op 16#32 +#define ldc2_op 16#36 +#define swc2_op 16#3a +#define sdc2_op 16#3e + +#define cop3_op 16#13 +#define lwc3_op 16#33 +#define ldc3_op 16#37 +#define swc3_op 16#3b +#define sdc3_op 16#3f + + +/* bcond subopcodes */ +#define bltz_op 16#00 +#define bgez_op 16#01 +#define bltzal_op 16#10 +#define bgezal_op 16#11 + +/* special subopcodes */ +#define sll_op 16#00 +#define srl_op 16#02 +#define sra_op 16#03 +#define sllv_op 16#04 +#define srlv_op 16#06 +#define srav_op 16#07 +#define jr_op 16#08 +#define jalr_op 16#09 +#define syscall_op 16#0C +#define break_op 16#0D +#define vcall_op 16#0E + +#define mfhi_op 16#10 +#define mthi_op 16#11 +#define mflo_op 16#12 +#define mtlo_op 16#13 +#define mult_op 16#18 +#define multu_op 16#19 +#define div_op 16#1A +#define divu_op 16#1B + +#define add_op 16#20 +#define addu_op 16#21 +#define and_op 16#24 +#define or_op 16#25 +#define xor_op 16#26 +#define nor_op 16#27 +#define sub_op 16#22 +#define subu_op 16#23 +#define slt_op 16#2A +#define sltu_op 16#2B + +#endif /* LANGUAGE_PASCAL */ diff --git a/lib/CPUs/MIPS/bsp/examples/r3.c b/lib/CPUs/MIPS/bsp/examples/r3.c new file mode 100644 index 0000000..77eb757 --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/r3.c @@ -0,0 +1,466 @@ +/* + * IOCCC Raytracer by Anders Gavare. + * + * The raytracer was one of the winners of the 17th IOCCC. + * + * NOTE: This is the UNOBFUSCATED version of the raytracer I used + * during development, not the actual entry sent to the contest. + * + * + * How to build: + * cc r3.c -o r3 (plus optimization flags) + * + * How to run: + * ./r3 > ray.ppm + * or + * ./r3 | xv - + */ +#include "libsys.h" +UINT32 *pP; + +xsize = 800; +ysize = 600; +An = 3; + +camera_X = 0; +camera_Y = -10; +camera_Z = -7; + +scale = 1296; +RootOfScale = 36; +maxcolor = 255; + +MaxDepth=9; +_=1<<15; + +/* +double sphere_x[44] = { + -15,-15,-15,-15, // I + -8,-8,-10,-6,-10,-6, // O + -1,-1, 1,1, // C + 6, 6, 8,8, // C + 13,13,15,15, // C + -11,-11,-11,-11,-9,-9,-7,-7, // r + 0,0,-2,-2,-2,2,2,2, // a + 7,7,9,9,11,11, // y + }; +double sphere_z[44] = { + 3,0,-3,-6, // I + -6, 3,0,0,-3,-3, // O + 0,-3,-6, 3, // C + 0,-3,-6, 3, // C + 0,-3,-6, 3, // C + -11,-13,-15,-17,-11,-15,-13,-17, // r + -11,-15,-13,-15,-17,-13,-15,-17, // a + -11,-13,-15,-17,-11,-13, // y + }; +*/ + +/* Common return variable: */ +return_var; +return_var2; +return_var3; +return_var4; + + +get_sphere_coordinates(b) +{ + return_var = "1111886:6:??AAFFHHMMOO55557799@@>>>BBBGGIIKK"[b]-64; + return_var3 = "C@=::C@@==@=:C@=:C@=:C531/513/5131/31/531/53"[b]-64; + +/* return_var = sphere_x[b]; */ + return_var2 = b<22? 9 : 0; +/* return_var3 = sphere_z[b]; */ + return_var4 = 2; +} + + +/* sqroot(x) returns the square root of x in return_var */ +sqroot_sub(x, mask, guess) +{ + mask? + ( + guess ^= mask, + guess*guess > x ? + ( guess ^= mask ) + : + 0, + sqroot_sub(x, mask/2, guess) + ) + : + ( return_var = guess ); +} + + +sqroot(x) +{ + sqroot_sub(x, _, 0); +} + + +/* + * hit_sphere(): + * + * returns where on a sphere we hit + * Returns distance in hit_sphere_q. (Negative return + * value if we didn't hit anything.) + */ +hit_sphere_q; +hit_sphere(objnr, x, y, z, + dx, dy, dz, + a, b) +{ + get_sphere_coordinates(objnr); + x -= return_var*scale; + y -= return_var2*scale; + z -= return_var3*scale; + + /* + * Solve the following equation: + * + * q^2 (dx^2+dy^2+dz^2) + q * 2(x*dx+y*dy+z*dz) + * + x^2+y^2+z^2 - r^2 = 0 + * + * We assume that |dx,dy,dz| is 1. + * + * q^2 + a q + b = 0 + * + * The solution is (of course) + * + * q = -a/2 +- sqrt(a^2/4 - b) + */ + + b = x*x/scale+y*y/scale+z*z/scale-return_var4*return_var4*scale; + + /* a = 2*(...), and then divide by -2 */ + a = -x*dx/scale-y*dy/scale-z*dz/scale; + + hit_sphere_q = + ( + (b = a*a/scale - b) >= 0 ? + ( +/* b = scale*sqrt((double)b/(double)scale), */ +/* sqroot(b*scale), */ + +/* sqroot_sub(b, _, 0), + b = return_var * RootOfScale, +*/ + sqroot_sub(b*scale, _, 0), + b = return_var, + + /* + * Return the lowest q (a+b or a-b) which is more + * than 0. Return negative if neither + * a+b or a-b is more than 0. + */ + + a + (a>b? -b : b) + ) + : + -1.0 + ); +} + + +/* + * find_closest(): + * + * find_closest() scans objects and returns an index + * to the object which was closest (has the lowest 'q'). + * x,y,z,dx,dy,dz are scaled. + * find_closest_i is the index number of the found object, + * -1 if none was found. find_closest_q is the distance + * (scaled). + */ +find_closest_i; /* index ("sphere number") */ +find_closest_q; /* distance (scaled) */ +find_closest(objnr, x, y, z, + dx, dy, dz, notindex) +{ + /* Initialize find_closest_i on first call: */ + find_closest_i = + !objnr ? -1 : find_closest_i; + + objnr < 44 ? + ( + hit_sphere(objnr, x,y,z, dx,dy,dz, 0,0), + (hit_sphere_q > 0 && objnr!=notindex && + (hit_sphere_q0 && find_closest_i >= 0? + ( + /* find_closest_i and _q are the object + number and distance of the object we + hit. */ + + orig_x += dir_x*find_closest_q/scale, + orig_y += dir_y*find_closest_q/scale, + orig_z += dir_z*find_closest_q/scale, + + /* + * Calculate color (diffuse light): + * (Note: use nZ as a temp variable while + * calculating nY) + */ + get_sphere_coordinates(find_closest_i), + nX = orig_x - return_var*scale, + nY = orig_y - return_var2*scale, + nZ = orig_z - return_var3*scale, + + tmpcol = (-2*nX -2*nY + nZ) / 3, /* sqrt(9), */ + /* Set return_var to the length of the normal + vector (in this case the sphere radius) */ +/* return_var = sqrt(nX*nX + nY*nY +nZ*nZ), */ + sqroot(nX*nX + nY*nY +nZ*nZ), +// return_var = return_var4*scale, + /* divide by return_var to get the color */ +// tmpcol = return_var!=0? tmpcol*scale/return_var : 0, + tmpcol /= return_var4, + + /* color is now -1..1 */ + tmpcol *= tmpcol, /* square the color 1..-1 => 1..1 */ + tmpcol *= 200, + tmpcol /= (scale*scale), +/* tmpcol += 5, */ + + closest_i_saved = find_closest_i, + + /* Mirror: out = in - 2*(-normal)*cos v + where v is the angle between in and + -normal */ + + /* -normal: (normalized to len=1.0) */ +/* return_var = sqrt(nX*nX + nY*nY + nZ*nZ), */ + return_var!=0? + ( + nX = -nX * scale / return_var, + nY = -nY * scale / return_var, + nZ = -nZ * scale / return_var + ) : 0, + + /* use return_var as a temp variable, + calculate cosinus between the vectors */ + return_var = (dir_x*nX + dir_y*nY + dir_z*nZ)/scale, +/* + dir_x -= 2 * nX * return_var / scale, + dir_y -= 2 * nY * return_var / scale, + dir_z -= 2 * nZ * return_var / scale, +*/ + dir_x -= nX * return_var / (scale/2), + dir_y -= nY * return_var / (scale/2), + dir_z -= nZ * return_var / (scale/2), + + trace_ray(orig_x, orig_y, orig_z, + dir_x, dir_y, dir_z, + depth-1, find_closest_i, 0,0), + + trace_ray_R /= 2, + trace_ray_G /= 2, + trace_ray_B /= 2, +/* + closest_i_saved &= 7, + !closest_i_saved? (closest_i_saved++) : 0, +*/ +/* + closest_i_saved = closest_i_saved<4? closest_i_saved+1 : 7, +*/ +/* + tvinga gråskalor: closest_i_saved = 7, +*/ +closest_i_saved = closest_i_saved<22? 7 : + ( + closest_i_saved<30 ? 1 : + ( + closest_i_saved<38 ? 2 : + ( + closest_i_saved<44 ? 4 : + ( + closest_i_saved == 44 ? 6 : + 3 + ) + ) + ) + ), + + trace_ray_R += closest_i_saved & 1 ? tmpcol : 0, + trace_ray_G += closest_i_saved & 2 ? tmpcol : 0, + trace_ray_B += closest_i_saved & 4 ? tmpcol : 0 + ) + : + ( + /* If we didn't hit anything, set the color anyway: */ + + depth==MaxDepth? /* True if this is a ray originating + from the camera */ + ( + orig_z += 2, + dir_z = orig_z > 0? orig_z / 8 : orig_z / 20 + ) + : 0, + + /* + * Colors according to Horizon_1 in gimp: + * At top of sky: 13,92,146 (light blue) + * At bottom sky: 255,255,255 (white) + * Top of ground: 213,168,111 (light brown) + * Bottom of ground: 103, 55, 26 (brown) + */ + + dir_z > 0? + ( + trace_ray_B = dir_z * dir_z / scale, + trace_ray_R = 255 - 250 * trace_ray_B / scale, + trace_ray_G = 255 - 150 * trace_ray_B / scale, + trace_ray_B = 255 - 100 * trace_ray_B / scale + ) + : + ( + trace_ray_B = dir_z * dir_z / scale, + trace_ray_B < scale/5? + ( + trace_ray_R = 255 - 210 * trace_ray_B / scale, + trace_ray_G = 255 - 435 * trace_ray_B / scale, + trace_ray_B = 255 - 720 * trace_ray_B / scale + ) + : + ( + trace_ray_B -= scale/5, + trace_ray_R = 213 - 110 * trace_ray_B / scale, + trace_ray_G = 168 - 113 * trace_ray_B / scale, + trace_ray_B = 111 - 85 * trace_ray_B / scale + ) + ), + + depth!=MaxDepth? + ( + trace_ray_R /= 2, + trace_ray_G /= 2, + trace_ray_B /= 2 + ) + : 0 + ); + + trace_ray_R = trace_ray_R<0? 0 : trace_ray_R>maxcolor? maxcolor: trace_ray_R; + trace_ray_G = trace_ray_G<0? 0 : trace_ray_G>maxcolor? maxcolor : trace_ray_G; + trace_ray_B = trace_ray_B<0? 0 : trace_ray_B>maxcolor? maxcolor : trace_ray_B; +} + + +/* + * do_pixels_in_line(): + * + * the horizontal "for loop" + */ +R; G; B; +dpil_helper(x,y, a,b) +{ + trace_ray( + scale*camera_X + scale*40*(An*x+a)/xsize/An - scale*20, + scale*camera_Y, + scale*camera_Z - scale*30*(An*y+b)/ysize/An + scale*15, + 0, scale, 0, MaxDepth, -1, 0,0); + + R += trace_ray_R; + G += trace_ray_G; + B += trace_ray_B; + + ++a