1 /*-------------------------------------------------------------------
2 -- TITLE: Plasma CPU in software. Executes MIPS(tm) opcodes.
3 -- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 -- DATE CREATED: 1/31/01
6 -- PROJECT: Plasma CPU core
7 -- COPYRIGHT: Software placed into the public domain by the author.
8 -- Software 'as is' without warranty. Author liable for nothing.
10 -- Plasma CPU simulator in C code.
11 -- This file served as the starting point for the VHDL code.
12 -- Assumes running on a little endian PC.
13 --------------------------------------------------------------------*/
20 //#define ENABLE_CACHE
23 #define MEM_SIZE (1024*1024*2)
24 #define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
25 #define htons(A) ntohs(A)
26 #define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
27 #define htonl(A) ntohl(A)
35 void Sleep(unsigned int value)
42 struct termios oldt, newt;
46 tcgetattr(STDIN_FILENO, &oldt);
48 newt.c_lflag &= ~(ICANON | ECHO);
49 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
54 if(select(1, &read_fd, NULL, NULL, &tv) == -1)
56 //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
57 if(FD_ISSET(0,&read_fd))
64 struct termios oldt, newt;
67 tcgetattr(STDIN_FILENO, &oldt);
69 newt.c_lflag &= ~(ICANON | ECHO);
70 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
72 //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
78 extern void __stdcall Sleep(unsigned long value);
81 #define UART_WRITE 0x20000000
82 #define UART_READ 0x20000000
83 #define IRQ_MASK 0x20000010
84 #define IRQ_STATUS 0x20000020
85 #define CONFIG_REG 0x20000070
86 #define MMU_PROCESS_ID 0x20000080
87 #define MMU_FAULT_ADDR 0x20000090
88 #define MMU_TLB 0x200000a0
90 #define IRQ_UART_READ_AVAILABLE 0x001
91 #define IRQ_UART_WRITE_AVAILABLE 0x002
92 #define IRQ_COUNTER18_NOT 0x004
93 #define IRQ_COUNTER18 0x008
97 #define MMU_MASK (1024*4-1)
101 unsigned int virtualAddress;
102 unsigned int physicalAddress;
107 int pc, pc_next, epc;
120 MmuEntry mmuEntry[MMU_ENTRIES];
123 static char *opcode_string[]={
124 "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
125 "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
126 "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
127 "?","?","?","?","?","?","?","?",
128 "LB","LH","LWL","LW","LBU","LHU","LWR","?",
129 "SB","SH","SWL","SW","?","?","SWR","CACHE",
130 "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
131 "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
134 static char *special_string[]={
135 "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
136 "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
137 "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
138 "MULT","MULTU","DIV","DIVU","?","?","?","?",
139 "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
140 "?","?","SLT","SLTU","?","DADDU","?","?",
141 "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
142 "?","?","?","?","?","?","?","?"
145 static char *regimm_string[]={
146 "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
147 "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
148 "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
149 "?","?","?","?","?","?","?","?"
152 static unsigned int HWMemory[8];
155 static int mem_read(State *s, int size, unsigned int address)
157 unsigned int value=0, ptr;
159 s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
164 HWMemory[0] = getch();
165 s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
174 s->irqStatus |= IRQ_UART_READ_AVAILABLE;
182 ptr = (unsigned int)s->mem + (address % MEM_SIZE);
184 if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
191 printf("Unaligned access PC=0x%x address=0x%x\n", (int)s->pc, (int)address);
192 assert((address & 3) == 0);
195 value = ntohl(value);
198 assert((address & 1) == 0);
199 value = *(unsigned short*)ptr;
201 value = ntohs((unsigned short)value);
204 value = *(unsigned char*)ptr;
212 static void mem_write(State *s, int size, int unsigned address, unsigned int value)
226 s->irqStatus = value;
231 //printf("processId=%d\n", value);
232 s->processId = value;
236 if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
238 //printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
239 ptr = (unsigned int)s->mmuEntry + address - MMU_TLB;
241 s->irqStatus &= ~IRQ_MMU;
245 ptr = (unsigned int)s->mem + (address % MEM_SIZE);
247 if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
253 assert((address & 3) == 0);
255 value = htonl(value);
259 assert((address & 1) == 0);
261 value = htons((unsigned short)value);
262 *(short*)ptr = (unsigned short)value;
265 *(char*)ptr = (unsigned char)value;
273 /************* Optional MMU and cache implementation *************/
274 /* TAG = VirtualAddress | ProcessId | WriteableBit */
275 unsigned int mmu_lookup(State *s, unsigned int processId,
276 unsigned int address, int write)
279 unsigned int compare, tag;
281 if(processId == 0 || s->userMode == 0)
283 //if(address < 0x30000000)
285 compare = (address & ~MMU_MASK) | (processId << 1);
286 for(i = 0; i < MMU_ENTRIES; ++i)
288 tag = s->mmuEntry[i].virtualAddress;
289 if((tag & ~1) == compare && (write == 0 || (tag & 1)))
290 return s->mmuEntry[i].physicalAddress | (address & MMU_MASK);
292 //printf("\nMMUTlbMiss 0x%x PC=0x%x w=%d pid=%d user=%d\n",
293 // address, s->pc, write, processId, s->userMode);
296 s->faultAddr = address & ~MMU_MASK;
297 s->irqStatus |= IRQ_MMU;
302 #define CACHE_SET_ASSOC_LN2 0
303 #define CACHE_SET_ASSOC (1 << CACHE_SET_ASSOC_LN2)
304 #define CACHE_SIZE_LN2 (13 - CACHE_SET_ASSOC_LN2) //8 KB
305 #define CACHE_SIZE (1 << CACHE_SIZE_LN2)
306 #define CACHE_LINE_SIZE_LN2 2 //4 bytes
307 #define CACHE_LINE_SIZE (1 << CACHE_LINE_SIZE_LN2)
309 static int cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(int)];
310 static int cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
311 static int cacheSetNext;
312 static int cacheMiss, cacheWriteBack, cacheCount;
314 static void cache_init(void)
317 for(set = 0; set < CACHE_SET_ASSOC; ++set)
319 for(i = 0; i < CACHE_SIZE/CACHE_LINE_SIZE; ++i)
320 cacheAddr[set][i] = 0xffff0000;
324 /* Write-back cache memory tagged by virtual address and processId */
325 /* TAG = virtualAddress | processId | dirtyBit */
326 static int cache_load(State *s, unsigned int address, int write)
328 int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
329 unsigned int addrTagMatch, addrPrevMatch=0;
330 unsigned int addrPrev;
331 unsigned int addressPhysical, tag;
334 addrTagMatch = address & ~(CACHE_SIZE-1);
335 offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
339 for(set = 0; set < CACHE_SET_ASSOC; ++set)
341 addrPrevMatch = cacheAddr[set][offsetAddr] & ~(CACHE_SIZE-1);
342 if(addrPrevMatch == addrTagMatch)
354 cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
356 //else if(write || (address >> 28) != 0x1)
358 // tag = cacheAddr[set][offsetAddr];
359 // pid = (tag & (CACHE_SIZE-1)) >> 1;
360 // if(pid != s->processId)
366 offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
368 /* Cache line dirty? */
369 if(cacheAddr[set][offsetAddr] & 1)
371 /* Write back cache line */
372 tag = cacheAddr[set][offsetAddr];
373 addrPrev = tag & ~(CACHE_SIZE-1);
374 addrPrev |= address & (CACHE_SIZE-1);
375 pid = (tag & (CACHE_SIZE-1)) >> 1;
376 addressPhysical = mmu_lookup(s, pid, addrPrev, 1); //virtual->physical
379 offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
380 for(i = 0; i < CACHE_LINE_SIZE; i += 4)
381 mem_write(s, 4, offsetMem + i, cacheData[set][(offsetData + i) >> 2]);
385 /* Read cache line */
386 addressPhysical = mmu_lookup(s, s->processId, address, write); //virtual->physical
389 offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
390 cacheAddr[set][offsetAddr] = addrTagMatch;
391 for(i = 0; i < CACHE_LINE_SIZE; i += 4)
392 cacheData[set][(offsetData + i) >> 2] = mem_read(s, 4, offsetMem + i);
394 cacheAddr[set][offsetAddr] |= write;
398 static int cache_read(State *s, int size, unsigned int address)
403 if((address & 0xfe000000) != 0x10000000)
404 return mem_read(s, size, address);
406 set = cache_load(s, address, 0);
409 offset = (address & (CACHE_SIZE-1)) >> 2;
410 value = cacheData[set][offset];
416 value = (value >> ((address & 2) << 3)) & 0xffff;
419 value = (value >> ((address & 3) << 3)) & 0xff;
425 static void cache_write(State *s, int size, int unsigned address, unsigned int value)
430 if((address >> 28) != 0x1) // && (s->processId == 0 || s->userMode == 0))
432 mem_write(s, size, address, value);
436 set = cache_load(s, address, 1);
439 offset = (address & (CACHE_SIZE-1)) >> 2;
446 value |= value << 16;
447 mask = 0xffff << ((address & 2) << 3);
451 value |= (value << 8) | (value << 16) | (value << 24);
452 mask = 0xff << ((address & 3) << 3);
459 cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
462 #define mem_read cache_read
463 #define mem_write cache_write
466 static void cache_init(void) {}
472 //Write through direct mapped 4KB cache
473 #define CACHE_MISS 0x1ff
474 static unsigned int cacheData[1024];
475 static unsigned int cacheAddr[1024]; //9-bit addresses
476 static int cacheTry, cacheMiss, cacheInit;
478 static int cache_read(State *s, int size, unsigned int address)
481 unsigned int value, value2, address2=address;
486 for(offset = 0; offset < 1024; ++offset)
487 cacheAddr[offset] = CACHE_MISS;
490 offset = address >> 20;
491 if(offset != 0x100 && offset != 0x101)
492 return mem_read(s, size, address);
495 offset = (address >> 2) & 0x3ff;
496 if(cacheAddr[offset] != (address >> 12) || cacheAddr[offset] == CACHE_MISS)
499 cacheAddr[offset] = address >> 12;
500 cacheData[offset] = mem_read(s, 4, address & ~3);
502 value = cacheData[offset];
508 value = (value >> ((address & 2) << 3)) & 0xffff;
511 value = (value >> ((address & 3) << 3)) & 0xff;
516 value2 = mem_read(s, size, address2);
518 printf("miss match\n");
519 //if((cacheTry & 0xffff) == 0) printf("\n***cache(%d,%d)\n ", cacheMiss, cacheTry);
523 static void cache_write(State *s, int size, int unsigned address, unsigned int value)
527 mem_write(s, size, address, value);
529 offset = address >> 20;
530 if(offset != 0x100 && offset != 0x101)
533 offset = (address >> 2) & 0x3ff;
536 cacheAddr[offset] = CACHE_MISS;
539 cacheAddr[offset] = address >> 12;
540 cacheData[offset] = value;
543 #define mem_read cache_read
544 #define mem_write cache_write
545 #endif //SIMPLE_CACHE
546 /************* End optional cache implementation *************/
549 void mult_big(unsigned int a,
554 unsigned int ahi, alo, bhi, blo;
555 unsigned int c0, c1, c2;
556 unsigned int c1_a, c1_b;
568 c2 += (c1_a >> 16) + (c1_b >> 16);
569 c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
571 c0 = (c1 << 16) + (c0 & 0xffff);
576 void mult_big_signed(int a,
581 unsigned int ahi, alo, bhi, blo;
582 unsigned int c0, c1, c2;
595 c2 += (c1_a >> 16) + (c1_b >> 16);
596 c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
598 c0 = (c1 << 16) + (c0 & 0xffff);
603 //execute one cycle of a Plasma CPU
604 void cycle(State *s, int show_mode)
607 unsigned int op, rs, rt, rd, re, func, imm, target;
608 int imm_shift, branch=0, lbranch=2, skip2=0;
610 unsigned int *u=(unsigned int*)s->r;
611 unsigned int ptr, epc, rSave;
613 opcode = mem_read(s, 4, s->pc);
614 op = (opcode >> 26) & 0x3f;
615 rs = (opcode >> 21) & 0x1f;
616 rt = (opcode >> 16) & 0x1f;
617 rd = (opcode >> 11) & 0x1f;
618 re = (opcode >> 6) & 0x1f;
619 func = opcode & 0x3f;
620 imm = opcode & 0xffff;
621 imm_shift = (((int)(short)imm) << 2) - 4;
622 target = (opcode << 6) >> 4;
623 ptr = (short)imm + r[rs];
627 printf("%8.8x %8.8x ", s->pc, opcode);
629 printf("%8s ", special_string[func]);
631 printf("%8s ", regimm_string[rt]);
633 printf("%8s ", opcode_string[op]);
634 printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
635 printf("%4.4x", imm);
637 printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
643 if(s->pc_next != s->pc + 4)
644 epc |= 2; //branch delay slot
646 s->pc_next = s->pc_next + 4;
655 case 0x00:/*SPECIAL*/
658 case 0x00:/*SLL*/ r[rd]=r[rt]<<re; break;
659 case 0x02:/*SRL*/ r[rd]=u[rt]>>re; break;
660 case 0x03:/*SRA*/ r[rd]=r[rt]>>re; break;
661 case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs]; break;
662 case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs]; break;
663 case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs]; break;
664 case 0x08:/*JR*/ s->pc_next=r[rs]; break;
665 case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
666 case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs]; break; /*IV*/
667 case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs]; break; /*IV*/
668 case 0x0c:/*SYSCALL*/ epc|=1; s->exceptionId=1; break;
669 case 0x0d:/*BREAK*/ epc|=1; s->exceptionId=1; break;
670 case 0x0f:/*SYNC*/ s->wakeup=1; break;
671 case 0x10:/*MFHI*/ r[rd]=s->hi; break;
672 case 0x11:/*FTHI*/ s->hi=r[rs]; break;
673 case 0x12:/*MFLO*/ r[rd]=s->lo; break;
674 case 0x13:/*MTLO*/ s->lo=r[rs]; break;
675 case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
676 case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
677 case 0x1a:/*DIV*/ s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
678 case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
679 case 0x20:/*ADD*/ r[rd]=r[rs]+r[rt]; break;
680 case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt]; break;
681 case 0x22:/*SUB*/ r[rd]=r[rs]-r[rt]; break;
682 case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt]; break;
683 case 0x24:/*AND*/ r[rd]=r[rs]&r[rt]; break;
684 case 0x25:/*OR*/ r[rd]=r[rs]|r[rt]; break;
685 case 0x26:/*XOR*/ r[rd]=r[rs]^r[rt]; break;
686 case 0x27:/*NOR*/ r[rd]=~(r[rs]|r[rt]); break;
687 case 0x2a:/*SLT*/ r[rd]=r[rs]<r[rt]; break;
688 case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt]; break;
689 case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt]; break;
690 case 0x31:/*TGEU*/ break;
691 case 0x32:/*TLT*/ break;
692 case 0x33:/*TLTU*/ break;
693 case 0x34:/*TEQ*/ break;
694 case 0x36:/*TNE*/ break;
695 default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
701 case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
702 case 0x00:/*BLTZ*/ branch=r[rs]<0; break;
703 case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
704 case 0x01:/*BGEZ*/ branch=r[rs]>=0; break;
705 case 0x12:/*BLTZALL*/r[31]=s->pc_next;
706 case 0x02:/*BLTZL*/ lbranch=r[rs]<0; break;
707 case 0x13:/*BGEZALL*/r[31]=s->pc_next;
708 case 0x03:/*BGEZL*/ lbranch=r[rs]>=0; break;
709 default: printf("ERROR1\n"); s->wakeup=1;
712 case 0x03:/*JAL*/ r[31]=s->pc_next;
713 case 0x02:/*J*/ s->pc_next=(s->pc&0xf0000000)|target; break;
714 case 0x04:/*BEQ*/ branch=r[rs]==r[rt]; break;
715 case 0x05:/*BNE*/ branch=r[rs]!=r[rt]; break;
716 case 0x06:/*BLEZ*/ branch=r[rs]<=0; break;
717 case 0x07:/*BGTZ*/ branch=r[rs]>0; break;
718 case 0x08:/*ADDI*/ r[rt]=r[rs]+(short)imm; break;
719 case 0x09:/*ADDIU*/ u[rt]=u[rs]+(short)imm; break;
720 case 0x0a:/*SLTI*/ r[rt]=r[rs]<(short)imm; break;
721 case 0x0b:/*SLTIU*/ u[rt]=u[rs]<(unsigned int)(short)imm; break;
722 case 0x0c:/*ANDI*/ r[rt]=r[rs]&imm; break;
723 case 0x0d:/*ORI*/ r[rt]=r[rs]|imm; break;
724 case 0x0e:/*XORI*/ r[rt]=r[rs]^imm; break;
725 case 0x0f:/*LUI*/ r[rt]=(imm<<16); break;
727 if((opcode & (1<<23)) == 0) //move from CP0
737 if(s->processId && (r[rt]&2))
739 s->userMode|=r[rt]&2;
740 //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
742 //printf("pc=0x%x\n", epc);
746 // case 0x11:/*COP1*/ break;
747 // case 0x12:/*COP2*/ break;
748 // case 0x13:/*COP3*/ break;
749 case 0x14:/*BEQL*/ lbranch=r[rs]==r[rt]; break;
750 case 0x15:/*BNEL*/ lbranch=r[rs]!=r[rt]; break;
751 case 0x16:/*BLEZL*/ lbranch=r[rs]<=0; break;
752 case 0x17:/*BGTZL*/ lbranch=r[rs]>0; break;
753 // case 0x1c:/*MAD*/ break; /*IV*/
754 case 0x20:/*LB*/ r[rt]=(signed char)mem_read(s,1,ptr); break;
755 case 0x21:/*LH*/ r[rt]=(signed short)mem_read(s,2,ptr); break;
758 //r[rt]=(r[rt]&~(0xffffffff<<target))|
759 // (mem_read(s,4,ptr&~3)<<target); break;
760 case 0x23:/*LW*/ r[rt]=mem_read(s,4,ptr); break;
761 case 0x24:/*LBU*/ r[rt]=(unsigned char)mem_read(s,1,ptr); break;
762 case 0x25:/*LHU*/ r[rt]=(unsigned short)mem_read(s,2,ptr); break;
764 //target=32-8*(ptr&3);
765 //r[rt]=(r[rt]&~((unsigned int)0xffffffff>>target))|
766 //((unsigned int)mem_read(s,4,ptr&~3)>>target);
768 case 0x28:/*SB*/ mem_write(s,1,ptr,r[rt]); break;
769 case 0x29:/*SH*/ mem_write(s,2,ptr,r[rt]); break;
771 //mem_write(s,1,ptr,r[rt]>>24);
772 //mem_write(s,1,ptr+1,r[rt]>>16);
773 //mem_write(s,1,ptr+2,r[rt]>>8);
774 //mem_write(s,1,ptr+3,r[rt]); break;
775 case 0x2b:/*SW*/ mem_write(s,4,ptr,r[rt]); break;
776 case 0x2e:/*SWR*/ break; //fixme
777 case 0x2f:/*CACHE*/break;
778 case 0x30:/*LL*/ r[rt]=mem_read(s,4,ptr); break;
779 // case 0x31:/*LWC1*/ break;
780 // case 0x32:/*LWC2*/ break;
781 // case 0x33:/*LWC3*/ break;
782 // case 0x35:/*LDC1*/ break;
783 // case 0x36:/*LDC2*/ break;
784 // case 0x37:/*LDC3*/ break;
785 // case 0x38:/*SC*/ *(int*)ptr=r[rt]; r[rt]=1; break;
786 case 0x38:/*SC*/ mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
787 // case 0x39:/*SWC1*/ break;
788 // case 0x3a:/*SWC2*/ break;
789 // case 0x3b:/*SWC3*/ break;
790 // case 0x3d:/*SDC1*/ break;
791 // case 0x3e:/*SDC2*/ break;
792 // case 0x3f:/*SDC3*/ break;
793 default: printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode);
796 s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
798 s->skip = (lbranch == 0) | skip2;
813 void show_state(State *s)
816 printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
817 for(i = 0; i < 4; ++i)
819 printf("%2.2d ", i * 8);
820 for(j = 0; j < 8; ++j)
822 printf("%8.8x ", s->r[i*8+j]);
826 //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
828 for(i = -4; i <= 8; ++i)
830 printf("%c", i==0 ? '*' : ' ');
837 void do_debug(State *s)
840 int i, j=0, watch=0, addr;
841 s->pc_next = s->pc + 4;
851 printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch));
852 printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
853 printf("7=Watch 8=Jump 9=Quit> ");
860 case '1': case 'd': case ' ':
861 cycle(s, 0); show_state(s); break;
865 cycle(s, 0); printf("*"); cycle(s, 10); break;
869 for(i = 0; i < j; ++i)
876 printf("break point=0x%x\n", j);
881 while(s->wakeup == 0)
892 while(s->wakeup == 0)
903 for(i = 0; i < 8; ++i)
905 printf("%8.8x ", mem_read(s, 4, j+i*4));
917 s->pc_next = addr + 4;
925 /************************************************************/
927 int main(int argc,char *argv[])
929 State state, *s=&state;
932 printf("Plasma emulator\n");
933 memset(s, 0, sizeof(State));
935 s->mem = (unsigned char*)malloc(MEM_SIZE);
936 memset(s->mem, 0, MEM_SIZE);
939 printf(" Usage: mlite file.exe\n");
940 printf(" mlite file.exe B {for big_endian}\n");
941 printf(" mlite file.exe L {for little_endian}\n");
942 printf(" mlite file.exe BD {disassemble big_endian}\n");
943 printf(" mlite file.exe LD {disassemble little_endian}\n");
947 in = fopen(argv[1], "rb");
950 printf("Can't open file %s!\n",argv[1]);
954 bytes = fread(s->mem, 1, MEM_SIZE, in);
956 memcpy(s->mem + 1024*1024, s->mem, 1024*1024); //internal 8KB SRAM
957 printf("Read %d bytes.\n", bytes);
959 if(argc == 3 && argv[2][0] == 'B')
961 printf("Big Endian\n");
964 if(argc == 3 && argv[2][0] == 'L')
966 printf("Big Endian\n");
970 if(argc == 3 && argv[2][0] == 'S')
971 { /*make big endian*/
972 printf("Big Endian\n");
973 for(index = 0; index < bytes+3; index += 4)
975 *(unsigned int*)&s->mem[index] = htonl(*(unsigned int*)&s->mem[index]);
977 in = fopen("big.exe", "wb");
978 fwrite(s->mem, bytes, 1, in);
982 if(argc == 3 && argv[2][1] == 'D')
984 for(index = 0; index < bytes; index += 4) {
992 index = mem_read(s, 4, 0);
993 if((index & 0xffffff00) == 0x3c1c1000)