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:
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
@@ -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, ®);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 */
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user