📄 main.cpp
字号:
#include "app.h"
static FILE *AsmFile=NULL;
static int CycloneVer=0x0086; // Version number of library
int *CyJump=NULL; // Jump table
int ms=USE_MS_SYNTAX; // If non-zero, output in Microsoft ARMASM format
char *Narm[4]={ "b", "h","",""}; // Normal ARM Extensions for operand sizes 0,1,2
char *Sarm[4]={"sb","sh","",""}; // Sign-extend ARM Extensions for operand sizes 0,1,2
int Cycles; // Current cycles for opcode
void ot(const char *format, ...)
{
va_list valist=NULL;
int i, len;
// notaz: stop me from leaving newlines in the middle of format string
// and generating bad code
for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++);
if(i < len-1 && format[len-1] != '\n') printf("\nWARNING: possible improper newline placement:\n%s\n", format);
va_start(valist,format);
if (AsmFile) vfprintf(AsmFile,format,valist);
va_end(valist);
}
void ltorg()
{
if (ms) ot(" LTORG\n");
else ot(" .ltorg\n");
}
// trashes all temp regs
static void PrintException(int ints)
{
if(!ints) {
ot(" ;@ Cause an Exception - Vector address in r0\n");
ot(" mov r11,r0\n");
}
ot(";@ swap OSP <-> A7?\n");
ot(" ldrb r0,[r7,#0x44] ;@ Get SR high\n");
ot(" tst r0,#0x20\n");
ot(" bne no_sp_swap%i\n",ints);
ot(";@ swap OSP and A7:\n");
ot(" ldr r0,[r7,#0x3C] ;@ Get A7\n");
ot(" ldr r1,[r7,#0x48] ;@ Get OSP\n");
ot(" str r1,[r7,#0x3C]\n");
ot(" str r0,[r7,#0x48]\n");
ot("no_sp_swap%i%s\n",ints,ms?"":":");
ot(" ldr r10,[r7,#0x60] ;@ Get Memory base\n");
ot(" mov r1,r4,lsl #8\n");
ot(" sub r1,r1,r10,lsl #8 ;@ r1 = Old PC\n");
ot(" mov r1,r1,asr #8 ;@ push sign extended\n");
OpPush32();
OpPushSr(1);
ot(" mov r0,r11\n");
ot(";@ Read IRQ Vector:\n");
MemHandler(0,2);
if(ints) {
ot(" tst r0,r0 ;@ uninitialized int vector?\n");
ot(" moveq r0,#0x3c\n");
ot(" moveq lr,pc\n");
ot(" ldreq pc,[r7,#0x70] ;@ Call read32(r0) handler\n");
}
#if USE_CHECKPC_CALLBACK
ot(" add r0,r0,r10 ;@ r0 = Memory Base + New PC\n");
ot(" mov lr,pc\n");
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
ot(" mov r4,r0\n");
#endif
ot("\n");
if(!ints) {
ot(" ldrb r0,[r7,#0x44] ;@ Get SR high\n");
ot(" bic r0,r0,#0xd8 ;@ clear trace and unused flags\n");
ot(" orr r0,r0,#0x20 ;@ set supervisor mode\n");
ot(" strb r0,[r7,#0x44]\n");
}
}
// Trashes r0
void CheckInterrupt(int op)
{
ot(";@ CheckInterrupt:\n");
ot(" ldrb r0,[r7,#0x47] ;@ Get IRQ level\n");
ot(" tst r0,r0\n");
ot(" beq NoInts%x\n",op);
ot(" cmp r0,#6 ;@ irq>6 ?\n");
ot(" ldrleb r1,[r7,#0x44] ;@ Get SR high: T_S__III\n");
ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");
ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");
ot(" blgt DoInterrupt\n");
ot("NoInts%x%s\n", op,ms?"":":");
ot("\n");
}
static void PrintFramework()
{
ot(";@ --------------------------- Framework --------------------------\n");
if (ms) ot("CycloneRun\n");
else ot("CycloneRun:\n");
ot(" stmdb sp!,{r4-r11,lr}\n");
ot(" mov r7,r0 ;@ r7 = Pointer to Cpu Context\n");
ot(" ;@ r0-3 = Temporary registers\n");
ot(" ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)\n");
ot(" ldr r6,=JumpTab ;@ r6 = Opcode Jump table\n");
ot(" ldr r5,[r7,#0x5c] ;@ r5 = Cycles\n");
ot(" ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base\n");
ot(" ;@ r8 = Current Opcode\n");
ot(" mov r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format\n");
ot(" ;@ r10 = Source value / Memory Base\n");
ot("\n");
CheckInterrupt(0);
ot(";@ Check if our processor is in stopped state\n");
ot(" ldr r0,[r7,#0x58]\n");
ot(" tst r0,r0 ;@ stopped?\n");
ot(" movne r0,#0\n");
ot(" strne r0,[r7,#0x5C] ;@ eat all cycles\n");
ot(" ldmneia sp!,{r4-r11,pc} ;@ we are stopped, do nothing!\n");
ot("\n");
ot(";@ Check if interrupt used up all the cycles:\n");
ot(" subs r5,r5,#0\n");
ot(" blt CycloneEndNoBack\n");
ot("\n");
OpFirst();
ltorg();
ot("\n");
ot(";@ We come back here after execution\n");
ot("CycloneEnd%s\n", ms?"":":");
ot(" sub r4,r4,#2\n");
ot("CycloneEndNoBack%s\n", ms?"":":");
ot(" mov r9,r9,lsr #28\n");
ot(" str r4,[r7,#0x40] ;@ Save Current PC + Memory Base\n");
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");
ot(" strb r9,[r7,#0x46] ;@ Save Flags (NZCV)\n");
ot(" ldmia sp!,{r4-r11,pc}\n");
ot("\n");
#if COMPRESS_JUMPTABLE
ot(";@ uncompress jump table\n");
if (ms) ot("CycloneInit\n");
else ot("CycloneInit:\n");
ot(" ldr r12,=JumpTab\n");
ot(" add r0,r12,#0xe000*4 ;@ ctrl code pointer\n");
ot(" ldr r1,[r0,#-4]\n");
ot(" tst r1,r1\n");
ot(" movne pc,lr ;@ already uncompressed\n");
ot(" add r3,r12,#0xa000*4 ;@ handler table pointer, r12=dest\n");
ot("unc_loop%s\n", ms?"":":");
ot(" ldrh r1,[r0],#2\n");
ot(" and r2,r1,#0xf\n");
ot(" bic r1,r1,#0xf\n");
ot(" ldr r1,[r3,r1,lsr #2] ;@ r1=handler\n");
ot(" cmp r2,#0xf\n");
ot(" addeq r2,r2,#1 ;@ 0xf is really 0x10\n");
ot(" tst r2,r2\n");
ot(" ldreqh r2,[r0],#2 ;@ counter is in next word\n");
ot(" tst r2,r2\n");
ot(" beq unc_finish ;@ done decompressing\n");
ot(" tst r1,r1\n");
ot(" addeq r12,r12,r2,lsl #2 ;@ 0 handler means we should skip those bytes\n");
ot(" beq unc_loop\n");
ot("unc_loop_in%s\n", ms?"":":");
ot(" subs r2,r2,#1\n");
ot(" str r1,[r12],#4\n");
ot(" bgt unc_loop_in\n");
ot(" b unc_loop\n");
ot("unc_finish%s\n", ms?"":":");
ot(" ldr r12,=JumpTab\n");
ot(" ;@ set a-line and f-line handlers\n");
ot(" add r0,r12,#0xa000*4\n");
ot(" ldr r1,[r0,#4] ;@ a-line handler\n");
ot(" ldr r3,[r0,#8] ;@ f-line handler\n");
ot(" mov r2,#0x1000\n");
ot("unc_fill3%s\n", ms?"":":");
ot(" subs r2,r2,#1\n");
ot(" str r1,[r0],#4\n");
ot(" bgt unc_fill3\n");
ot(" add r0,r12,#0xf000*4\n");
ot(" mov r2,#0x1000\n");
ot("unc_fill4%s\n", ms?"":":");
ot(" subs r2,r2,#1\n");
ot(" str r3,[r0],#4\n");
ot(" bgt unc_fill4\n");
ot(" bx lr\n");
ltorg();
ot("\n");
#else
ot(";@ do nothing\n");
if (ms) ot("CycloneInit\n");
else ot("CycloneInit:\n");
ot(" bx lr\n");
ot("\n");
#endif
if (ms) ot("CycloneSetSr\n");
else ot("CycloneSetSr:\n");
ot(" mov r2,r1,lsr #8\n");
ot(" ldrb r3,[r0,#0x44] ;@ get SR high\n");
ot(" eor r3,r3,r2\n");
ot(" tst r3,#0x20\n");
ot(" and r2,r2,#0xa7 ;@ only nonzero bits\n");
ot(" strb r2,[r0,#0x44] ;@ set SR high\n");
ot(" bne setsr_noswap\n");
ot(" ldr r2,[r0,#0x3C] ;@ Get A7\n");
ot(" ldr r3,[r0,#0x48] ;@ Get OSP\n");
ot(" str r3,[r0,#0x3C]\n");
ot(" str r2,[r0,#0x48]\n");
ot("setsr_noswap%s\n",ms?"":":");
ot(" mov r2,r1,lsr #3\n");
ot(" strb r2,[r0,#0x45] ;@ the X flag\n");
ot(" bic r2,r1,#0xf3\n");
ot(" tst r1,#1\n");
ot(" orrne r2,r2,#2\n");
ot(" tst r1,#2\n");
ot(" orrne r2,r2,#1\n");
ot(" strb r2,[r0,#0x46] ;@ flags\n");
ot(" bx lr\n");
ot("\n");
if (ms) ot("CycloneGetSr\n");
else ot("CycloneGetSr:\n");
ot(" ldrb r1,[r0,#0x46] ;@ flags\n");
ot(" bic r2,r1,#0xf3\n");
ot(" tst r1,#1\n");
ot(" orrne r2,r2,#2\n");
ot(" tst r1,#2\n");
ot(" orrne r2,r2,#1\n");
ot(" ldrb r1,[r0,#0x45] ;@ the X flag\n");
ot(" tst r1,#2\n");
ot(" orrne r2,r2,#0x10\n");
ot(" ldrb r1,[r0,#0x44] ;@ the SR high\n");
ot(" orr r0,r2,r1,lsl #8\n");
ot(" bx lr\n");
ot("\n");
ot(";@ DoInterrupt - r0=IRQ number\n");
ot("DoInterrupt%s\n", ms?"":":");
ot(" stmdb sp!,{lr} ;@ Push ARM return address\n");
ot(";@ Get IRQ Vector address:\n");
ot(" mov r0,r0,asl #2\n");
ot(" add r11,r0,#0x60\n");
PrintException(1);
ot(" ldrb r0,[r7,#0x47] ;@ IRQ\n");
ot(" orr r1,r0,#0x20 ;@ Supervisor mode + IRQ number\n");
ot(" strb r1,[r7,#0x44] ;@ Put SR high\n");
ot(";@ Clear stopped states:\n");
ot(" mov r1,#0\n");
ot(" str r1,[r7,#0x58]\n");
ot(" sub r5,r5,#%d ;@ Subtract cycles\n",44);
ot("\n");
#if USE_INT_ACK_CALLBACK
#if INT_ACK_NEEDS_STUFF
ot(" str r4,[r7,#0x40] ;@ Save PC\n");
ot(" mov r1,r9,lsr #28\n");
ot(" strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n");
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");
#endif
ot(" ldr r11,[r7,#0x8c] ;@ IrqCallback\n");
ot(" tst r11,r11\n");
ot(" movne lr,pc\n");
ot(" movne pc,r11 ;@ call IrqCallback if it is defined\n");
#if INT_ACK_CHANGES_STUFF
ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n");
ot(" ldrb r9,[r7,#0x46] ;@ r9 = Load Flags (NZCV)\n");
ot(" mov r9,r9,lsl #28\n");
ot(" ldr r4,[r7,#0x40] ;@ Load PC\n");
#endif
#else // not USE_INT_ACK_CALLBACK
ot(";@ Clear irq:\n");
ot(" strb r1,[r7,#0x47]\n");
#endif
ot(" ldmia sp!,{pc} ;@ Return\n");
ot("\n");
ot("Exception%s\n", ms?"":":");
ot("\n");
ot(" stmdb sp!,{lr} ;@ Preserve ARM return address\n");
PrintException(0);
ot(" ldmia sp!,{pc} ;@ Return\n");
ot("\n");
}
// ---------------------------------------------------------------------------
// Call Read(r0), Write(r0,r1) or Fetch(r0)
// Trashes r0-r3
int MemHandler(int type,int size)
{
int func=0;
func=0x68+type*0xc+(size<<2); // Find correct offset
#if MEMHANDLERS_NEED_PC
ot(" str r4,[r7,#0x40] ;@ Save PC\n");
#endif
#if MEMHANDLERS_NEED_FLAGS
ot(" mov r3,r9,lsr #28\n");
ot(" strb r3,[r7,#0x46] ;@ Save Flags (NZCV)\n");
#endif
#if MEMHANDLERS_NEED_CYCLES
ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");
#endif
ot(" mov lr,pc\n");
ot(" ldr pc,[r7,#0x%x] ;@ Call ",func);
// Document what we are calling:
if (type==0) ot("read");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -