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
This commit is contained in:
2009-04-15 14:11:45 +00:00
parent be038f16ba
commit 79de05d54c
10 changed files with 2904 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
#include <stdio.h>
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;
}
+13
View File
@@ -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);
+343
View File
@@ -0,0 +1,343 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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, &reg);
// 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, &reg);
// 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);
}
+190
View File
@@ -0,0 +1,190 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#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;
}
+499
View File
@@ -0,0 +1,499 @@
/* inflate routines for Palm OS (to inflate a deflated stream)
*
* Based heavily upon gunzip.c by Pasi Ojala <albert@cs.tut.fi>
* 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 <stdio.h> // 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;
}
+15
View File
@@ -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);
+249
View File
@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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
}
+625
View File
@@ -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 <stdio.h>
#include <string.h>
#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;
}
+450
View File
@@ -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 */
+466
View File
@@ -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_q<find_closest_q || find_closest_i<0)) ?
(
find_closest_q = hit_sphere_q,
find_closest_i = objnr
) : 0,
find_closest(objnr+1, x,y,z,dx,dy,dz, notindex)
)
: 0;
}
/*
* trace_ray():
*
* Traces one ray. orig_xyz and dir_xyz are scaled.
* Return value in trace_ray_R, G, and B.
*/
trace_ray_R;
trace_ray_G;
trace_ray_B;
nX;
nY;
nZ; /* tmp normal, and tmp
sphere_light calculation */
trace_ray(orig_x, orig_y, orig_z,
dir_x, dir_y, dir_z,
depth, notindex,
tmpcol, closest_i_saved)
{
/*
* "Scan" through the list of all objects
* to see which one is closest:
*/
find_closest(0, orig_x, orig_y, orig_z,
dir_x, dir_y, dir_z, notindex);
depth>0 && 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<An?
dpil_helper(x,y,a,b)
: (
++b<An?
dpil_helper(x,y,0,b)
: 0
);
}
do_pixels_in_line(x, y)
{
R = G = B = 0;
dpil_helper(x,y,0,0);
x < xsize ?
(
/* output the pixel to stdout, */
#ifndef JMIPS_VGA
printf("%c%c%c", R/An/An, G/An/An, B/An/An),
#else
pP[x+800*y] = (R/An/An & 0xFF) | ((G/An/An & 0xFF) << 8) | ((B/An/An & 0xFF) << 16),
#endif
/* and then do the next pixel in this line: */
do_pixels_in_line(x+1, y)
) : 0;
}
/*
* do_line():
*
* the vertical "for loop"
*/
do_line(y)
{
/* Do all lines: */
do_pixels_in_line(0, --y? do_line(y),y:y);
}
main()
{
#ifdef JMIPS_VGA
volatile UINT32 *pVGA_mctrl = (UINT32*)sys_vga_mctrl;
volatile UINT32 *pVGA_moffs = (UINT32*)sys_vga_moffs;
UINT64 *pPixelBuf;
pPixelBuf = (UINT64*)malloc(800*600*sizeof(UINT32));
pP = (UINT32*)pPixelBuf;
printf("pPixelBuf : %8.8X\n", (UINT32)pPixelBuf);
*pVGA_moffs = (UINT32)pPixelBuf;
*pVGA_mctrl = 1;
memset(pPixelBuf, 0, 800*600*sizeof(UINT32));
#else
/* Output PPM file header ... */
printf("P6\n%i %i\n255\n", xsize, ysize);
#endif
/* and do all lines: */
do_line(ysize);
}