//main.htm Project:{armt} main source file ©CTPP 2015 created 25/03/15 6:48:43 //ARM Thumb Assembler for Cortex-M3 #pragma breakpoints on #include {ctype.htm} #include {string.htm} #include {stdlib.htm} #include {lseq.htm} #include {accdis.htm} #include {ftype.htm} #include {raw.htm} #include {nc.htm} //#include {arm.htm} //NZCV condition codes //P:arm/arm2 //0000 EQ Z //0001 NE !Z //0010 CS/HS/AE C //0011 CC/LO/B !C //0100 MI N //0101 PL or 0 !N //0110 VS/O V //0111 VC/NO !V //1000 HI/A C&&!Z //1001 LS/BE !C||Z //1010 GE N==V //1011 LT/L N!=V //1100 GT/G !Z&&(N==V) //1101 LE Z||(N!=V) //1110 //1111 SL blnk( CH** ptr); SL expect(CH**ptr,UL c); #define COMMA ',' #define COLON ':' #define SEMIC ';' UL platform=0; UL cortexm0,cortexm0warn,cortexm0ok; UL cortexm4; UL sramb; UL sramaddressing; UL sramtop; UL sram0base; UL stacktop; UL flash0base; UL flash1base; UL linear; UL ivtlen=-1,ivsize,cg; UL* ivt; UL flashbase=0x00000000,flashsize,eepromsize,sramsize,noivt,nostartup,condition,modified; UL compilertest=1; //constant expression analyzer on by default now, 6.6.15 UL endorg; UL lastorg; UL dataalign=4; UL maxdataalign; UL inlinedat=1; //essential for CortexM0 to reach pool variables! UL pmode=1; //default to Thumb mode UL binfile; UL dofixups=0; UL poolrange; UL initialjump; UL relocatable; CH gash[1024]; UL gashlen; LINE* xline(UL textlen); struct BRANCH { LSEQ* L; UL lno,lnoffset; UL flg; UL edo; UL size; // IDENT* lab; // SY* s; UL syoff; UL pmode; UL scope; }; BRANCH branch[MAXBRANCHES]; UL branches=0; MACRO macro[MAXMACROS]; UL macros=0; //.dot directives IDENT INCLUDE= {7,"include"}; IDENT ORG= {3,"org"}; IDENT ENDORG= {6,"endorg"}; IDENT PLATFORM= {8,"platform"}; IDENT CORTEXM0= {8,"cortexm0"}; IDENT CORTEXM4= {8,"cortexm4"}; IDENT CORTEXM0WARN= {12,"cortexm0warn"}; IDENT FLASHBASE= {9,"flashbase"}; IDENT FLASHSIZE= {9,"flashsize"}; IDENT SRAMBASE= {8,"srambase"}; IDENT SRAMSIZE= {8,"sramsize"}; IDENT SRAMTOP= {7,"sramtop"}; IDENT EEPROMSIZE= {10,"eepromsize"}; IDENT IVSIZE= {6,"ivsize"}; IDENT IVTLEN= {6,"ivtlen"}; IDENT VECTOR= {6,"vector"}; IDENT NOIVT= {5,"noivt"}; IDENT NOSTARTUP= {9,"nostartup"}; // IDENT FIXSJUMPS= {18,"fixshortjumperrors"}; IDENT IF= {2,"if"}; IDENT ENDIF= {5,"endif"}; IDENT COMPILERTEST= {12,"compilertest"}; IDENT POOL= {4,"pool"}; IDENT REGISTERBANK= {12,"registerbank"}; IDENT BINFILE= {3,"bin"}; IDENT PMODE= {5,"pmode"}; IDENT PMODEARM= {3,"arm"}; IDENT PMODETHUMB= {5,"thumb"}; IDENT INITIALJUMP= {11,"initialjump"}; #define INITJUMPARM 1 #define INITJUMPTHUMB 2 IDENT RELOCATABLE= {11,"relocatable"}; //compiler-generated symbols for avrstartup code IDENT codeend={7,"CODEEND"}; //start of program data in flash IDENT sramend={7,"SRAMEND"}; //end of sram data(datalen=sramend-srambase) IDENT DEFINE={6,"define"}; IDENT PORT={4,"port"}; IDENT PIN={3,"pin"}; IDENT SET={3,"set"}; IDENT CLR={3,"clr"}; IDENT ENAP={4,"enap"}; IDENT DISP={4,"disp"}; IDENT ENAO={4,"enao"}; IDENT DISO={4,"diso"}; IDENT SETO={4,"seto"}; IDENT CLRO={4,"clro"}; IDENT DATAWORD={8,"dataword"}; IDENT BYTE={4,"byte"}; IDENT WORD={4,"word"}; IDENT DWORD={5,"dword"}; IDENT CHDATA={2,"CH"}; IDENT UCDATA={2,"UC"}; IDENT UIDATA={2,"UI"}; IDENT ULDATA={2,"UL"}; IDENT UmDATA={2,"Um"}; IDENT UMDATA={2,"UM"}; IDENT SIDATA={2,"SI"}; IDENT SLDATA={2,"SL"}; IDENT SmDATA={2,"Sm"}; IDENT SMDATA={2,"SM"}; IDENT cCHDATA={3,"cCH"}; IDENT cULDATA={3,"cUL"}; IDENT PLATFORMSAM3X= {5,"sam3x"}; IDENT PLATFORMATMEGA328P={10,"AtMega328P"}; IDENT PLATFORMATMEGA2560={10,"AtMega2560"}; IDENT ATMEGA328PREGS={14,"Atmega328Pregs"}; IDENT ATMEGA2560REGS={14,"Atmega2560regs"}; IDENT IVT328P={7,"ivt328P"}; IDENT IVT2560={7,"ivt2560"}; IDENT ARMSTARTUP={11,"armstartup0"}; IDENT ARMSTARTUP0={11,"armstartup0"}; IDENT LINEAR={6,"linear"}; IDENT ALIGN={5,"align"}; IDENT end={7,"CODEEND"}; IDENT veryend={7,"!!!!!!!"}; IDENT srambase={8,"srambase"}; // IDENT sramend={7,"SRAMEND"}; IDENT sramendval={10,"SRAMENDVAL",0,0,0}; //ARM mnemonics IDENT ADC= {3,"adc"}; IDENT ADCS={4,"adcs"}; IDENT ADD= {3,"add"}; IDENT ADDS={4,"adds"}; IDENT AND= {3,"and"}; IDENT ANDS={4,"ands"}; IDENT ASR= {3,"asr"}; IDENT ASRS={4,"asrs"}; IDENT B= {1,"b"}; IDENT BIC= {3,"bic"}; IDENT BICS={4,"bics"}; IDENT BEQ= {3,"beq"}; IDENT BKPT={4,"bkpt"}; IDENT BNE= {3,"bne"}; IDENT BPL= {3,"bpl"}; IDENT BMI= {3,"bmi"}; IDENT BLT= {3,"blt"}; IDENT BGE= {3,"bge"}; IDENT BGT= {3,"bgt"}; IDENT BLE= {3,"ble"}; IDENT BAE= {3,"bae"}; IDENT BA= {2,"ba"}; IDENT BBE= {3,"bbe"}; IDENT BB= {2,"bb"}; IDENT BL= {2,"bl"}; IDENT BLX= {3,"blx"}; IDENT BX= {2,"bx"}; IDENT CMN= {3,"cmn"}; IDENT CMNS={4,"cmns"}; IDENT CMP= {3,"cmp"}; IDENT CMPS={4,"cmps"}; IDENT DMB= {3,"dmb"}; IDENT DSB= {3,"dsb"}; IDENT ISB= {3,"isb"}; IDENT EOR= {3,"eor"}; IDENT EORS={4,"eors"}; IDENT LDR= {3,"ldr"}; IDENT LDRB={4,"ldrb"}; IDENT LDRH={4,"ldrh"}; IDENT LDRSB={5,"ldrsb"}; IDENT LDRSH={5,"ldrsh"}; IDENT LSL= {3,"lsl"}; IDENT LSLS={4,"lsls"}; IDENT LSR= {3,"lsr"}; IDENT LSRS={4,"lsrs"}; IDENT MOV= {3,"mov"}; IDENT MOVS={4,"movs"}; IDENT MVN= {3,"mvn"}; IDENT MVNS={4,"mvns"}; IDENT MOVT={4,"movt"}; IDENT MUL= {3,"mul"}; IDENT MRS= {3,"mrs"}; IDENT MSR= {3,"msr"}; IDENT ORN= {3,"orn"}; IDENT ORNS={4,"orns"}; IDENT ORR= {3,"orr"}; IDENT ORRS={4,"orrs"}; IDENT POP= {3,"pop"}; IDENT ROR= {3,"ror"}; IDENT RORS={4,"rors"}; IDENT RSB= {3,"rsb"}; IDENT RSBS={4,"rsbs"}; IDENT PUSH={4,"push"}; IDENT REV ={3,"rev"}; IDENT REV16={5,"rev16"}; IDENT REVSH={5,"revsh"}; IDENT SBC ={3,"sbc"}; IDENT SBCS={4,"sbcs"}; IDENT STR= {3,"str"}; IDENT STRB={4,"strb"}; IDENT STRH={4,"strh"}; IDENT SUB ={3,"sub"}; IDENT SUBS={4,"subs"}; IDENT SWI={3,"swi"}; IDENT SVC={3,"svc"}; IDENT TEQ= {3,"teq"}; IDENT TST= {3,"tst"}; IDENT SDIV={4,"sdiv"}; IDENT UDIV={4,"udiv"}; //ARM FPU instructions IDENT VADD={4,"vadd"}; IDENT VMOV={4,"vmov"}; IDENT VMSR={4,"vmsr"}; IDENT VMRS={4,"vmrs"}; //CTPP/Intel/AVR alias mnemonics for easier reading of assembly code IDENT CALL={4,"call"}; IDENT JMP={3,"jmp"}; IDENT OR={2,"or"}; IDENT POP3={4,"pop3"}; IDENT POP3S={5,"pop3s"}; IDENT PUSH3={5,"push3"}; IDENT PUSH3S={6,"push3s"}; IDENT RET={3,"ret"}; IDENT SHL={3,"shl"}; IDENT SHR={3,"shr"}; //Atmel mnemonics IDENT ADIW={4,"adiw"}; IDENT ANDI={4,"andi"}; IDENT BCLR={4,"bclr"}; IDENT BLD= {3,"bld"}; IDENT BRBC={4,"brbc"}; IDENT BRBS={4,"brbs"}; IDENT BRCC={4,"brcc"}; IDENT BRCS={4,"brcs"}; IDENT BREQ={4,"breq"}; IDENT BRGE={4,"brge"}; IDENT BRHC={4,"brhc"}; IDENT BRHS={4,"brhs"}; IDENT BRID={4,"brid"}; IDENT BRIE={4,"brie"}; IDENT BRLO={4,"brlo"}; IDENT BRLT={4,"brlt"}; IDENT BRMI={4,"brmi"}; IDENT BRNE={4,"brne"}; IDENT BRPL={4,"brpl"}; IDENT BRSH={4,"brsh"}; IDENT BRTC={4,"brtc"}; IDENT BRTS={4,"brts"}; IDENT BRVC={4,"brvc"}; IDENT BRVS={4,"brvs"}; IDENT BREAK={5,"break"}; IDENT BSET={4,"bset"}; IDENT BST={3,"bst"}; IDENT CBI={3,"cbi"}; IDENT CBR={3,"cbr"}; IDENT CLC={3,"clc"}; IDENT CLH={3,"clh"}; IDENT CLI={3,"cli"}; IDENT CLN={3,"cln"}; IDENT CLS={3,"cls"}; IDENT CLT={3,"clt"}; IDENT CLV={3,"clv"}; IDENT CLZ={3,"clz"}; // IDENT CLR={3,"clr"}; IDENT COM={3,"com"}; IDENT CP={2,"cp"}; IDENT CPC={3,"cpc"}; IDENT CPI={3,"cpi"}; IDENT CPSE={4,"cpse"}; IDENT DEC={3,"dec"}; IDENT EICALL={6,"eicall"}; IDENT EIJMP={5,"eijmp"}; IDENT ELPM={4,"elpm"}; IDENT FMUL={4,"fmul"}; IDENT FMULS={5,"fumls"}; IDENT FMULSU={6,"fumlsu"}; IDENT ICALL={5,"icall"}; IDENT IJMP={4,"ijmp"}; IDENT IN={2,"in"}; IDENT INC={3,"inc"}; IDENT LAC={3,"lac"}; IDENT LAS={3,"las"}; IDENT LAT={3,"lat"}; IDENT LD={2,"ld"}; IDENT LDD={3,"ldd"}; IDENT LDI={3,"ldi"}; IDENT LDS={3,"lds"}; IDENT LPM={3,"lpm"}; IDENT MOVW={4,"movw"}; IDENT MULS={4,"muls"}; IDENT MULSU={5,"mulsu"}; IDENT NEG={3,"neg"}; IDENT NOP={3,"nop"}; IDENT ORI={3,"ori"}; IDENT OUT={3,"out"}; IDENT RCALL={5,"rcall"}; IDENT RETI={4,"reti"}; IDENT RJMP={4,"rjmp"}; IDENT ROL={3,"rol"}; IDENT SBCI={4,"sbci"}; IDENT SBI={3,"sbi"}; IDENT SBIC={4,"sbic"}; IDENT SBIS={4,"sbis"}; IDENT SBIW={4,"sbiw"}; IDENT SBR={3,"sbr"}; IDENT SBRC={4,"sbrc"}; IDENT SBRS={4,"sbrs"}; IDENT SEC={3,"sec"}; IDENT SEH={3,"seh"}; IDENT SEI={3,"sei"}; IDENT SEN={3,"sen"}; IDENT SER={3,"ser"}; IDENT SES={3,"ses"}; // IDENT SET={3,"set"}; // IDENT SEV={3,"sev"}; IDENT SEZ={3,"sez"}; IDENT SLEEP={5,"sleep"}; IDENT SPM={3,"spm"}; IDENT STx={2,"st"}; IDENT STD={3,"std"}; IDENT STS={3,"sts"}; IDENT SUBI={4,"subi"}; IDENT SWAP={4,"swap"}; IDENT WDR={3,"wdr"}; IDENT XCH={3,"xch"}; //CTPP super-instructions IDENT LDIW={4,"ldiw"}; //load 16-bit immediate into register pair IDENT LDSW={4,"ldsw"}; //load 16-bits from SRAM into register pair IDENT STSW={4,"stsw"}; //store 16-bits from register pair into SRAM IDENT LDID={4,"ldid"}; //load 32-bit immediate into adjacent register pairs IDENT LDSD={4,"ldsd"}; //load 32-bits from SRAM to adjacent register pairs IDENT STSD={4,"stsd"}; //store 32-bits from adjacent register pairs to SRAM SL doinitialjump(SF* a) { UL* jmp=(UL*)a->buf; switch(initialjump) { case INITJUMPARM: *jmp=0xea00000e; break; case INITJUMPTHUMB: *jmp=0x0000e01e; break; } } SL allocateivt(SF* a) { if(noivt){return 0;} if(!ivsize){brk return 1;} //!!error a->edo+=ivtlen*4; a->pc=(UI*)(a->buf+a->hdrlen+a->edo); cg=1;cortexm0ok=1; } SL generateivt(SF* a) { if(noivt){return 0;} UL n,edo=0,opcode,lastused=0,reset=0; SL jdist; UL* pcd; SY* s; //brk for(n=0;n< ivtlen;n++) { pcd=(UL*)(a->buf+a->hdrlen+edo); s=(SY*)(sy+ivt[n]); if(!n) { *pcd=sramtop+1; } else if(s) { if(s->rtaddr==-1) { // *pcd=reset+flashbase|1; *pcd=reset|1; // if(!dlab){return 1;} //error,no DUMMYIRET for unused interrupt vectors // lab=dlab; } else { // *pcd=lab->no+flashbase|1; *pcd=s->rtaddr|1; if(n==1){reset=s->rtaddr;} lastused=n; } } edo+=4; } lastused++; if(lastused< n) { clidisplay("Unused entries in IVT, .ivtlen could be %2lc1400",&lastused); } return 0; } SL emit4(SF* a,UL opcode); SL emit1(SF* a,UL byte) {//push a byte into the code stream, if(a->edo==flashsize){clidisplay("Program memory full!");return 1;} if(!cg){allocateivt(a);} *(UC*)a->pc=byte; a->edo++; a->pc=(UI*)(a->buf+a->hdrlen+a->edo); } SL emit2(SF* a,UL opcode) { if(a->edo==flashsize){clidisplay("Program memory full!");return 1;} if(!cg){allocateivt(a);} if(a->edo&1) {//emitbyte may have left instruction pointer misaligned emit1(a,0); } if(opcode==0xe7ff) {//Thumb2 16bit jump to next instruction, pointless return a->edo; } *a->pc=opcode; a->edo+=2; a->pc=(UI*)(a->buf+a->hdrlen+a->edo); return a->edo } SL emit4(SF* a,UL opcode) { if(a->edo==flashsize){clidisplay("Program memory full!");return 1;} if(!cg){allocateivt(a);} if(a->edo&1) {//emitbyte may have left instruction pointer misaligned emit1(a,0); } *(UL*)a->pc=opcode; a->edo+=4; a->pc=(UI*)(a->buf+a->hdrlen+a->edo); return a->edo } SL aligndata(SF* a) { UL msk=dataalign-1; UL nmsk=~msk; UL pad=((a->edo+msk)&nmsk)-a->edo; if(pad){datasegalloc(pad);} if(inlinedat&&pad) { while(pad--) { emit1(a,0xbe); } a->pc=(UI*)(a->buf+a->hdrlen+a->edo); } if(dataalign>maxdataalign){maxdataalign=dataalign;} return 0; } CH* x0000="_x0000"; UL xctr=0; IDENT* xlabel(VD) { IDENT* i=(IDENT*)calloc(sizeof(IDENT)+7,1); if(!i){return NULL;} i->p=(CH*)i;i->p+=sizeof(IDENT); i->len=6; catprint(i->p,"_x%04X",&xctr); xctr++; return i; } //literal pool mechanism 5.9.15 UL emptypool(SF* a,UL holdlast) { UC* ptr=sy; SY* s; UL ctr=0; //brk while(ctr< syms) { s=(SY*)ptr; // if(holdlast&& // ((*(Um*)s->name=='_p'))&& // (s->name[2]=='l') && // (s->name[3]=='0') ) // {brk; // //break; //hold back last pool entry? // } if((*(Um*)s->name=='_p')&& // (!(s->scope&0x40000000)) ) (s->data)&& (!(s->mods&1)) ) { // if(!memcmp(s->name,"_pl00be",7)){brk;} if(!s->data){brk;} if(a->edo&1){emit1(a,0);} if(a->edo&2){emit2(a,0xbe00);} s->rtaddr=a->edo+flashbase; switch(s->name[2]) { case 'f': case 'd': //brk fastreloc(s->rtaddr-flashbase+a->hdrlen); break; } // if(ctr==160){brk;} emit4(a,s->data); s->mods|=1; // s->scope|=0x40000000; // s->scope&=0xc0000000; } ptr+=sizeof(SY)+s->namelen; ctr++; } if(a->edo&2){emit2(a,0xbe00);} poolrange=a->edo; return 0; } //literal pool mechanism 26.7.15 //quick hack to reduce repetition on assembler for Cortex-M0, which needs //literals to load 32-bit values. //identifiers beginning with "_p" are entered into the pool //.pool directive or end of compilation run empties the pool by assembling // cUL _p{identifier} {identifier} for each victim //thereby dumping the 32-bit {identifier} values into the code stream //Limitation: //once a _p{identifier} has been dumped it cannot be used again (it will //produce a duplicate code label) //Workaround: keep code which uses particular _p{identifier}s together in //subfunctions //Fix: create new label type for the purpose, to be ignored by getlabel(), //addlabel(), once out of scope, allowing the name to be re-used. Indeed //label->scope is the exact field which needs to be added. The same mechanism //will be needed for local variables #define MAXPOOLS 128 UL pools,poolsdone; IDENT pool[MAXPOOLS]; CH poolstr[16384]; UL poolstrlen; SL addpool(IDENT* i) { if(pools==MAXPOOLS){brk return 1;} UL n; IDENT* p=pool; for(n=0;n< pools;n++) { if((!memcmp(i->p,p->p,p->len))&&(i->len==p->len)) { return 0; } } pool[pools]=*i; pools++; return 0; } SL addliteral1(SF* a,SY* s) { UL n,nlen; CH msg[256]; IDENT* p=pool+poolsdone; LINE li; if(a->edo&2) {emit2(a,0xbf00);} //p:arm/arm2 366 //compiling the literal overwrites 4 bytes of program memory, so keep it safe: UL* pdata=(UL*)a->pc; UL datasafe=*pdata; msg[0]=0;nlen=s->namelen; catprint(msg,"cUL _p%#s 0x%08X",&nlen,s->name,&s->rtaddr); strcpy(poolstr+poolstrlen,msg); li.text=poolstr+poolstrlen;li.len=strlen(msg); poolstrlen+=li.len+1; if(assemble(a,&li,0,0)){brk return 1;} //restore lost initialiser data *pdata=datasafe; return 0; } SL addliteral(SF* a,SY* s) { // return 0; //brk UL psoff; UL namelen=s->namelen; CH pname[32];pname[0]=0;catprint(pname,"_p%#s",&namelen,s->name); if(!revsynamematch(pname,namelen+2,&psoff)) { SY* ps=(SY*)(sy+psoff); ps->data=s->rtaddr; return 0; } return 1; addsym(pname,namelen+2,stCODE,utbasic(4,0),&psoff,-1); ps=(SY*)(sy+psoff); ps->data=s->rtaddr; ps->scope=0; return 0; } SL addliteral(SF* a,IDENT* i) { // return 0; //brk UL psoff; UL namelen=i->len; CH pname[32];pname[0]=0;catprint(pname,"_p%#s",&namelen,i->p); //brk if(!revsynamematch(pname,namelen+2,&psoff)) { SY* ps=(SY*)(sy+psoff); ps->data=i->no; return 0; } return 1; addsym(pname,namelen+2,stCODE,utbasic(4,0),&psoff,-1); ps=(SY*)(sy+psoff); ps->data=i->no; ps->scope=0; return 0; } SL addliteral1(SF* a,IDENT* s) { UL n,nlen; CH msg[256]; IDENT* p=pool+poolsdone; LINE li; if(a->edo&2) {emit2(a,0xbf00);} //p:arm/arm2 366 msg[0]=0;nlen=s->len; catprint(msg,"cUL _p%#s 0x%08X",&nlen,s->p,&s->no); strcpy(poolstr+poolstrlen,msg); li.text=poolstr+poolstrlen;li.len=strlen(msg); poolstrlen+=li.len+1; if(assemble(a,&li,0,0)){brk return 1;} } SL srvdisplay(CH* format,...); SL emptyliteralpool(SF* a) { return emptypool(a,0); UL n,nlen; CH msg[256]; IDENT* p=pool+poolsdone; LINE li; if(a->edo&2) {emit2(a,0xbf00);} //p:arm/arm2 366 for(n=poolsdone;n< pools;n++) { msg[0]=0;nlen=p->len-2; catprint(msg,"cUL %#s %#s",&p->len,p->p,&nlen,p->p+2); srvdisplay(msg); strcpy(poolstr+poolstrlen,msg); li.text=poolstr+poolstrlen;li.len=strlen(msg); poolstrlen+=li.len+1; if(assemble(a,&li,0,0)){brk return 1;} p++; } poolsdone=n; // poolstrlen=0; } SL srvdisplay(CH* format,...); //P:atmel/sam3x SL dispcchipid(UL id) { //p:atmel/sam3x 589 UL eproc=(id>>5)&0x7; CH* eprocS; switch(eproc) { case 1:eprocS="ARM964ES";break; case 2:eprocS="ARM7TDMI";break; case 3:eprocS="CortexM3";break; case 4:eprocS="ARM920T"; break; case 5:eprocS="ARM926EJB"; break; case 6:eprocS="CortexA3";break; default:eprocS="??????";break; } UL nvpsiz=(id>>8)&0x0f; //p:atmel/sam3x 589 switch(nvpsiz) { case 0: nvpsiz=0; break; case 1: nvpsiz=8; break; case 2: nvpsiz=16; break; case 3: nvpsiz=32; break; case 5: nvpsiz=64; break; case 7: nvpsiz=128; flash0base=0x00080000;flash1base=0x00090000;break; case 9: nvpsiz=256; flash0base=0x00080000;flash1base=0x000a0000;break; case 10:nvpsiz=512; flash0base=0x00080000;flash1base=0x000c0000;break; case 12:nvpsiz=1024; break; case 14:nvpsiz=2048; break; default:nvpsiz=0; } UL nvpsiz2=(id>>12)&0x0f; //p:atmel/sam3x 589 switch(nvpsiz2) //p:atmel/sam3x 590 { case 0: nvpsiz2=0; break; case 1: nvpsiz2=8; break; case 2: nvpsiz2=16; break; case 3: nvpsiz2=32; break; case 5: nvpsiz2=64; break; case 7: nvpsiz2=128; break; case 9: nvpsiz2=256; break; case 10:nvpsiz2=512; break; case 12:nvpsiz2=1024; break; case 14:nvpsiz2=2048; break; default:nvpsiz2=0; } UL arch=(id>>20)&0xff; //p:atmel/sam3x 589 CH* archS; switch(arch) //p:atmel/sam3x 591 { case 0x80:archS="SAM3UxC/100";break; case 0x81:archS="SAM3UxE/144";break; case 0x83:archS="SAM3AxC/100";break; case 0x84:archS="SAM3XxC/100";break; case 0x85:archS="SAM3XxE/144";break; case 0x86:archS="SAM3XxG/217";break; case 0x88:archS="SAM3SxA/48";break; case 0x89:archS="SAM3SxB/64";break; case 0x8a:archS="SAM3SxC/100";break; default:archS="????????";break; } UL sramsiz=(id>>16)&0x0f; //p:atmel/sam3x 589 switch(sramsiz) //p:atmel/sam3x 590 { case 0:sramsiz=48; break; case 1:sramsiz=1; break; case 2:sramsiz=2; break; case 3:sramsiz=6; break; case 4:sramsiz=24; break; case 5:sramsiz=4; break; case 6:sramsiz=80; break; case 7:sramsiz=160; break; case 8:sramsiz=8; break; case 9:sramsiz=16; break; case 10:sramsiz=32; break; case 11:sramsiz=64; sram0base=0x20078000;stacktop=0x20088000;archS[5]='4';break;break; case 12:sramsiz=128; break; case 13:sramsiz=256; break; case 14:sramsiz=96; sram0base=0x20070000;stacktop=0x20088000;archS[5]='8';break; case 15:sramsiz=512; break; } UL nvptyp=(id>>28)&0x07; //p:atmel/sam3x 589 CH* nvptypS; switch(nvptyp) //p:atmel/sam3x 592 { case 0:nvptypS="Rom"; break; case 1:nvptypS="Romless"; break; case 2:nvptypS="Flash"; break; case 3:nvptypS="Rom/Flash"; break; case 4:nvptypS="Sram"; break; default:nvptypS="????????";break; } if(nvptyp==4) { srvdisplay("%12sc600 %9sc600 %9sc600|c600 %4lc600k/%4lc600k SRAM %3lc600k",archS,eprocS,nvptypS,&nvpsiz2,&nvpsiz,&sramsiz); } else { srvdisplay("%sc600 %sc600 %sc600|c600 %4lc600k Sram %3lc600k",archS,eprocS,nvptypS,&nvpsiz,&sramsiz); } } //SL ident(IDENT* i,CH** ptr) //{ // if(isalpha(**ptr)) // { // i->len=1; // i->p=*ptr;(*ptr)++; // while((isalnum(**ptr))||(**ptr=='_')) // { // i->len++; // (*ptr)++; // } // return 0; // } // return 1; //} SL ident(IDENT* i,CH** ptr) { //27.5.15 added white space gobbler if(blnk(ptr)){return 1;} if((isalpha(**ptr))||(**ptr=='_')) { i->len=1; i->p=*ptr;(*ptr)++; while(isalnum(**ptr)||(**ptr=='_')) { i->len++; (*ptr)++; } i->key=keyword(i->len,i->p); blnk(ptr); return 0; } return 1; } SL matchident(IDENT* a,IDENT* b) { if(a->len==b->len) { if(!memicmp(a->p,b->p,a->len)){return 0;} } return 1; } SL matchidentC(IDENT* a,IDENT* b) { if(a->len==b->len) { if(!memcmp(a->p,b->p,a->len)){return 0;} } return 1; } SL matchlabel(IDENT* a,IDENT* b) { if(a->len==b->len) { if(!memcmp(a->p,b->p,a->len)){return 0;} } return 1; } MACRO* getmacro(IDENT* str); UL sramdataaddress; SL resolvebranches(SF* a) { UL m,err,adv; BRANCH* b=branch; for(m=0;m< branches;m++) { if(b->flg) { //recompile source line containing branch symbol UL edosave=a->edo; adv=a->edo=b->edo;a->pc=(UI*)(a->buf+a->edo+a->hdrlen); LINE* li=b->L->line+b->lno; UL pmodesave=pmode; pmode=b->pmode; UL scopesave=scope; scope=b->scope; if(!assemble(a,li,b->lnoffset,1)) {b->flg=0; adv=a->edo-adv; if(adv!=b->size) { clidisplay("Forward declaration on line %4lc1400 of %sc1400 leaving hole in code stream",&b->lno,a->fname); } } else{brk err++;} //will be good place to display assembly error message a->edo=edosave;a->pc=(UI*)(a->buf+a->edo+a->hdrlen); pmode=pmodesave; scope=scopesave; } b++; } return err; } SL countunresolved(SF* a) { BRANCH* b; UL m,ctr=0; LINE* li; b=branch; for(m=0;m< branches;m++) { if(b->flg) { li=b->L->line+b->lno; // clidisplay("Unresolved %s",b->lab->p); clidisplay("Unresolved %s",li->text+b->lnoffset); ctr++; } b++; } return ctr; } EX UL ininit; UL patchrlcdst(UL olddst,UL newdst); SL addbranch(SF* a,UL lno,IDENT* lab,UL lineoffset,UL size) { if(branches==MAXBRANCHES){clidisplay("Too many branches");return 1;} // IDENT* l=label; // UL n; // for(n=0;n< labels;n++) // { // if(!matchlabel(l,lab)){break;} // l++; // } // if(n==labels) // { // *l=*lab; // l->no=-1; // labels++; // if(*(Um*)lab->p=='_p') // { // addpool(lab); // } // } UL syoff; SY* s; SY* ps; //NB addbranch should only be called by the assembler after symmatch has failed //brk UL scopesave=scope; if(scope==1){scope=0;} if(addsym(lab->p,lab->len,0,0,&syoff,-1)) { scope=scopesave; s=(SY*)(sy+syoff); if((s->rtaddr!=-1)&& (*(Um*)lab->p=='_p')&& (a->edo+flashbase>s->rtaddr) ) { s->scope|=0x80000000; addsym(lab->p,lab->len,0,0,&syoff,-1); } else { //brk return 1; } } scope=scopesave; MACRO* m; if(*(Um*)lab->p=='_p') { s=(SY*)(sy+syoff); lab->p+=2;lab->len-=2; m=getmacro(lab); if(m) { s->data=strtoul(m->imm.p,0,0); lab->p-=2;lab->len+=2; } else { UL psoff; if(!revsynamematch(lab->p,lab->len,&psoff)) {//fills in address of global variable for cortexm0 ps=(SY*)(sy+psoff); // s->data=ps->rtaddr; s->data=1; rgen(2,syoff,0,psoff,0); } else { // if(*lab->p=='0') // {//only for _p0xnnnnnnnn cortexm0 constants // if(!s->data) // { // s->data=strtoul(lab->p,0,0); // } // } if(*(Um*)&lab->p[1]=='0x') {//only for _px0xnnnnnnnn cortexm0 constants if(!s->data) { s->data=strtoul(lab->p+1,0,0); } } // else if(*(Um*)&lab->p[0]=='l0') // { // if(!s->data) // { // s->data=strtoul(lab->p+1,0,0); // } // } else {//some kind of reloc patch is needed... //...ps is a degenerate symbol //there is a better way to do this // brk; if(addsym(lab->p,lab->len,stCODE,0,&psoff,-1)){brk return 1;} // if(!memcmp(s->name,"_pl00bd",7)){brk;} // if(!memcmp(s->name,"_pl00be",7)){brk;} // if(s->scope==1){s->scope=0;} ps=(SY*)(sy+psoff); // if(*(Um*)&lab->p[0]=='l0'){s->data=strtoul(lab->p+1,0,0);} s->data=1; if(s->scope==1) {//pre-emptive pool dump may cause literals to be output //before they have been referenced if(!synamematch(s->name,s->namelen,&psoff)) { patchrlcdst(psoff,syoff); } else{brk;} //unable to relink orphaned pool literal } else {rgen(2,syoff,0,psoff,0);} } } lab->p-=2;lab->len+=2; } } BRANCH* b=branch+branches; branch[branches].L=a->L; branch[branches].lno=lno; branch[branches].lnoffset=lineoffset; branch[branches].edo=a->edo; branch[branches].flg=1; // branch[branches].lab=l; // branch[branches].s=s; branch[branches].syoff=syoff; branch[branches].size=size; branch[branches].pmode=pmode; branch[branches].scope=scope; branches++; return 0; } MACRO* getmacro(IDENT* str) { UL n; MACRO* m=macro; for(n=0;n< macros;n++) { if(!matchlabel(m->str,str)){return m;} m++; } return NULL; } SL addmacro(IDENT* str,IDENT* imm,UL dtype) { if(macros==MAXMACROS){clidisplay("Too many macros");return 1;} MACRO* m=macro+macros; m->str=*str; m->imm=*imm; m->str.dtype=dtype; macros++; return 0; } SL matchr00_07(IDENT* a) { if(!isdigit(*(a->p+1))) { if((a->len==2)&&(!memicmp(a->p,"sp",2))){a->no=13;} if((a->len==2)&&(!memicmp(a->p,"lr",2))){a->no=14;} if((a->len==2)&&(!memicmp(a->p,"pc",2))){a->no=15;} return 1; } if(*a->p!='r'){return 1;} UL rno=strtol(a->p+1,NULL,10); if(rno<8){a->no=rno;return 0;} return 1; } SL matchr00_15(IDENT* a) { if(!isdigit(*(a->p+1))) { if((a->len==2)&&(!memicmp(a->p,"sp",2))){a->no=13;return 0;} if((a->len==2)&&(!memicmp(a->p,"lr",2))){a->no=14;return 0;} if((a->len==2)&&(!memicmp(a->p,"pc",2))){a->no=15;return 0;} return 1; } if(*a->p!='r'){return 1;} UL rno=strtol(a->p+1,NULL,10); if(rno<16){a->no=rno;return 0;} return 1; } SL matchr08_15(IDENT* a) { if(*a->p!='r'){return 1;} if(!isdigit(*(a->p+1))) { if((a->len==2)&&(!memicmp(a->p,"sp",2))){a->no=13;return 0;} if((a->len==2)&&(!memicmp(a->p,"lr",2))){a->no=14;return 0;} if((a->len==2)&&(!memicmp(a->p,"pc",2))){a->no=15;return 0;} return 1; } UL rno=strtol(a->p+1,NULL,10); if((rno>8)&&(rno<=15)){a->no=rno;return 0;} return 1; } SL matchs00_31(IDENT* a) { if(*a->p!='s'){return 1;} if(!isdigit(*(a->p+1))){return 1;} UL rno=strtol(a->p+1,NULL,10); if(rno<32){a->no=rno;return 0;} return 1; } SL exp(IDENT* a,CH** ptr); SL imm(IDENT* a,CH** ptr) { if(compilertest==1){return exp(a,ptr);} a->p=*ptr; UL minus=0; UL comp=0; if(*a->p=='-'){minus=1;(*ptr)++;} else if(*a->p=='~'){comp=1;(*ptr)++;} if(!isdigit(**ptr)) { IDENT m; IDENT* l; if(ident(&m,ptr)){return 1;} MACRO* q=getmacro(&m); if(q) { a->no=q->imm.no; a->len=q->imm.len; a->p=q->imm.p; a->dtype=q->str.dtype; if(comp) {a->no=~a->no;} if(minus){a->no=-a->no;} //if(a->len==4){a->no&=0xff;} //if(a->len==6){a->no&=0xffff;} DO_ORS: if(**ptr=='|') { (*ptr)++; if((!ident(&m,ptr))&&(q=getmacro(&m))) { if(comp){a->no&=~q->imm.no;} else {a->no|=q->imm.no;} } goto DO_ORS; } return 0; } else {return 1;} } a->no=strtol(*ptr,ptr,0); a->len=*ptr-a->p; a->dtype=0; if(minus){a->no=-a->no;} if(comp) {a->no=~a->no;} //if(a->len==4+minus+comp){a->no&=0xff;} //if(a->len==6+minus+comp){a->no&=0xffff;} return 0; } SL matchK00_07(IDENT* a) { if(!isdigit(*a->p)){return 1;} // UL K=strtol(a->p,NULL,0); UL K=a->no; if((K>=0)&&(K<=07)){a->no=K;return 0;} return 1; } SL matchK00_31(IDENT* a) { if(!isdigit(*a->p)){return 1;} // UL K=strtol(a->p,NULL,0); UL K=a->no; if((K>=0)&&(K<=31)){a->no=K;return 0;} return 1; } SL matchK00_63(IDENT* a) { if(!isdigit(*a->p)){return 1;} // UL K=strtol(a->p,NULL,0); UL K=a->no; if((K>=0)&&(K<=63)){a->no=K;return 0;} return 1; } SL matchK00_255(IDENT* a) { // if(!isdigit(*a->p)){return 1;} // UL K=strtol(a->p,NULL,0); UL K=a->no; if((K>=0)&&(K<=255)){a->no=K;return 0;} if((K&0x80000000)&&((K&0xffffff00)==0xffffff00)){return 0;} return 1; } SL matchK00_65535(IDENT* a) { // if(!isdigit(*a->p)){return 1;} // UL K=strtol(a->p,NULL,0); UL K=a->no; if((K>=0)&&(K<=65565)){a->no=K;return 0;} return 1; } UL sigbits(UL val) { UL msk=0x80000000; UL bits=32; while(bits) { if(val&msk){return bits;} bits--; msk>>=1; } return 0; } SL arminclude(SF* a,IDENT* ifname) { CH fname[128]; memcpy(fname,ifname->p,ifname->len);fname[ifname->len]=0; CH* rptr=strchr(fname,'.'); if(!rptr){strcat(fname,".armi");} LSEQ* L=loadSEQ(fname); if(!L) { memset(fname,0,128); strcpy(fname,"/z/arms/i/"); memcpy(fname+10,ifname->p,ifname->len); rptr=strchr(fname,'.'); if(!rptr){strcat(fname,".armi");} L=loadSEQ(fname); } if(!L){clidisplay("|c1200Include file %sc1400 not found",fname);return 1;} clidisplay("|c1000including file %sc1400",fname); SF ai;ai.edo=a->edo;ai.line=0; strcpy(ai.fname,fname); // ai.buf=calloc(L->lines,4); // if(!ai.buf){clidisplay("|c1200Insufficient memory");return 1;} ai.buf=a->buf; ai.pc=(UI*)(a->buf+a->edo+a->hdrlen); ai.L=L; ai.hdrlen=a->hdrlen; LINE* li=L->line; while(li) { ai.pc=(UI*)(ai.buf+ai.edo+ai.hdrlen); UL sedo=(UL)ai.pc;cortexm0ok=0; if(assemble(&ai,li,0,0)) { clidisplay("|c1200Error at line %4lc1400 {%sc1400}",&ai.line,ai.fname);return 1; } if(cortexm0&&cortexm0warn&&(ai.edo-sedo>2)&&(!cortexm0ok)) { clidisplay("|c1200Cortex-M0 edo advanced more than 2 at line %4lc1400 {%sc1400} %s",&ai.line,ai.fname,li->text); } ai.line++; if(ai.line>=L->lines){break;} li=ai.L->line+ai.line; // li=li->next; } a->edo=ai.edo; a->pc=(UI*)(ai.buf+ai.edo+ai.hdrlen); return 0; } SL thumbexpandable(UL val,UL* enc) { if(val<256){*enc=val;return 1;} switch(val) //p:arm/arm2 167 { case 0x00000100:*enc=0x04007080;return 1; case 0x00000200:*enc=0x04007000;return 1; case 0x00000400:*enc=0x04006080;return 1; case 0x00000800:*enc=0x04006000;return 1; case 0x00001000:*enc=0x04005080;return 1; case 0x00002000:*enc=0x04005000;return 1; case 0x00004000:*enc=0x04004080;return 1; case 0x00008000:*enc=0x04004000;return 1; case 0x00010000:*enc=0x04003080;return 1; case 0x00020000:*enc=0x04003000;return 1; case 0x00040000:*enc=0x04002080;return 1; case 0x00080000:*enc=0x04002000;return 1; case 0x00100000:*enc=0x04001080;return 1; case 0x00200000:*enc=0x04001000;return 1; case 0x00400000:*enc=0x04000080;return 1; case 0x00800000:*enc=0x04000000;return 1; case 0x01000000:*enc=0x00007080;return 1; case 0x02000000:*enc=0x00007000;return 1; case 0x04000000:*enc=0x00006080;return 1; case 0x08000000:*enc=0x00006000;return 1; case 0x10000000:*enc=0x00005080;return 1; case 0x20000000:*enc=0x00005000;return 1; case 0x40000000:*enc=0x00004080;return 1; case 0x80000000:*enc=0x00004000;return 1; } return 0; UL n,ctr=0,msk=0x80000000,first=-1,last=-1; for(n=0;n<32;n++) { if(val&msk) { ctr++; if(first==-1){first=n;} last=n; } msk>>=1; } } SL movregimm32(SF* a,UL reg,UL imm32) { //for immediate>16 bits, encode MOV and MOVT instructions //T3 encoding //p:arm/arm2 347 UL imm4,imm1,imm3,imm8,opcode; imm4=(imm32&0xf000)>>12; imm1=(imm32&0x800)>>1; imm3=(imm32&0x700)<<4; imm8= imm32&0xff; opcode=0xf240+imm1+imm4; emit2(a,opcode); opcode=imm3+(reg<<8)+imm8;emit2(a,opcode); imm4=(imm32&0xf0000000)>>28; imm1=(imm32&0x08000000)>>17; imm3=(imm32&0x07000000)>>12; imm8=(imm32&0x00ff0000)>>16; opcode=0xf2c0+imm1+imm4; emit2(a,opcode); opcode=imm3+(reg<<8)+imm8;emit2(a,opcode); } SL ldrregmregoff(SF* a,UL reg,UL mreg,UL off) { //p:arm/arm2 287 UL opcode; if((off<256)&&(reg<8)&&(mreg<8)&&(!(off&3))) { opcode=0x6800+(mreg<<3)+reg+(off<<4);emit2(a,opcode); } else if(off<4096) { //p:arm/arm2 287 opcode=0xf8d0+mreg; emit2(a,opcode); opcode=(reg<<12)+off;emit2(a,opcode); } } SL strregmregoff(SF* a,UL reg,UL mreg,UL off) { //p:arm/arm2 473 UL opcode; if((off<256)&&(reg<8)&&(mreg<8)&&(!(off&3))) { opcode=0x6000+(mreg<<3)+reg+(off<<4);emit2(a,opcode); } else if(off<4096) { opcode=0xf8c0+mreg; emit2(a,opcode); opcode=(reg<<12)+off;emit2(a,opcode); } } SL orrregthumbimm(SF* a,UL tgtreg,UL srcreg,UL imm) { //p:arm/arm2 387 UL th,opcode; if(thumbexpandable(imm,&th)) { opcode=0xf0400000+(tgtreg<<16)+(srcreg<<8)+th; emit2(a,opcode>>16);emit2(a,opcode); } else{brk return 1;} //imm not encodable yet } SL bicregthumbimm(SF* a,UL tgtreg,UL srcreg,UL imm) { //p:arm/arm2 243 UL th,opcode; if(thumbexpandable(imm,&th)) { opcode=0xf0200000+(tgtreg<<16)+(srcreg<<8)+th; emit2(a,opcode>>16);emit2(a,opcode); } else{brk return 1;} //imm not encodable yet } VD preprocesscommandline(CH* str,UL* argc,CH** argv,UL cmdlinelen); SL armassemble(SF* a,LINE* li,UL lineoffset,CH** tptr,IDENT* i,UL recurse); SL assemble(SF* a,LINE* li,UL lineoffset,UL recurse) { CH* ptr=li->text; CH* end=ptr+li->len; IDENT i ;memset(&i, 0,sizeof(IDENT)); IDENT op1;memset(&op1,0,sizeof(IDENT)); IDENT op2;memset(&op2,0,sizeof(IDENT)); IDENT op3;memset(&op3,0,sizeof(IDENT)); IDENT op4;memset(&op4,0,sizeof(IDENT)); IDENT op5;memset(&op5,0,sizeof(IDENT)); IDENT* lab; MACRO* mac; MACRO* pmac; UL opcode; SL jdist,n,offset; UL plus=0,minus=0,reg,val,port,bit,ctr,msk,comp,setmsk,clrmsk,ioff; CH* ptrsave; FTRAW* ftr=(FTRAW*)a->buf; CH chipfile[128]; IDENT pi; CH cmdline[512]; UL argc; CH* argv[64]; CH** argp; UL argctr; UL preclude=0; CH* precludefile=NULL; SY* s; //SKIP: while(isspace(*ptr)){ptr++;} if(!*ptr) { return 0; } else if(*ptr=='{') { return compile(a,&ptr); //entry into c compiler } else if(*(UI*)ptr=='//') { return 0; } else if(*ptr=='.') {//.dot directives ptr++; //skip '.' if(ident(&i,&ptr)){return 1;} // if(!matchident(&i,PLATFORM)) // { // if(platform){return 1;} //only one .platform directive allowed // while(isspace(*ptr)){ptr++;}if(!*ptr){return 1;} // if(ident(&op1,&ptr)){return 1;} //platformname expected // if(!matchident(&op1,PLATFORMSAM3X)) // { // platform=3; // ftr->chipsig=0x285e0a60; // dispcchipid(0x285e0a60); //P:atmel/sam3x 589 // } // else{clidisplay("Unknown platform %#sc1400",&op1.len,op1.p);return 1;} // } if(!matchident(&i,IVTLEN)) { if(ivtlen==-1){ivtlen=strtoul(ptr,&ptr,0);} } else if(!matchident(&i,NOIVT)) { noivt=1; } else if(!matchident(&i,NOSTARTUP)) { nostartup=1; } else if(!matchident(&i,PLATFORM)) { //only one .platform directive allowed if(platform){return 1;} //only one .platform directive allowed platform=strtoul(ptr,&ptr,16);//platform is HEX CHIP SIGNATURE strncpy(cmdline,li->text,510); preprocesscommandline(cmdline,&argc,argv,li->len); if(argc>2) {//expanded .platform syntax 18.5.15, to allow definition of //ivtlen,noivt,nostartup before autoincluding 1e.... file //also allowed is ONE include file definition, a good place for //a circuit board pin definition file. This reduces the //AVR program target to one line, whilst still being flexible //eg: .platform 1e950f ivtlen 17 include arduinouno argp=argv+2;argctr=2; while(argctr< argc) { if(!strcmp(*argp,"noivt")) {noivt=1;ivtlen=0;} else if (!strcmp(*argp,"nostartup")){nostartup=1;} else if (!strcmp(*argp,"ivtlen")) { argp++; argctr++; if(!isdigit(**argp)){clidisplay("expected value for ivtlen!");return 1;} if(ivtlen==-1){ivtlen=strtoul(*argp,0,0);} } else if(!strcmp(*argp,"include")) { argp++; argctr++; preclude=1; precludefile=*argp; } argp++; argctr++; } } chipfile[0]=0; catprint(chipfile,"/z/arms/i/%08X.armi",&platform); ftr->chipsig=platform;//0x1e950f; pi.p=chipfile; pi.len=strlen(chipfile); if(arminclude(a,&pi)){return 1;} // dispcchipid(0x285e0a60); //NB: SETS FLASH0BASE! //P:atmel/sam3x 589 if(!nostartup) { if(cortexm0) { if(arminclude(a,&ARMSTARTUP0)) {return 1;} } else { if(arminclude(a,&ARMSTARTUP)) {return 1;} } } if(preclude) { pi.len=strlen(precludefile); pi.p=precludefile; if(arminclude(a,&pi)){return 1;} } } else if(!matchident(&i,CORTEXM0)) { cortexm0=1; } else if(!matchident(&i,CORTEXM0WARN)) { cortexm0warn=1; } else if(!matchident(&i,CORTEXM4)) { cortexm4=1; } else if(!matchident(&i,FLASHBASE)) { flashbase=strtoul(ptr,&ptr,0); } else if(!matchident(&i,FLASHSIZE)) { flashsize=strtoul(ptr,&ptr,0); } else if(!matchident(&i,EEPROMSIZE)) { eepromsize=strtoul(ptr,&ptr,0); } else if(!matchident(&i,SRAMSIZE)) { sramsize=strtoul(ptr,&ptr,0); } else if(!matchident(&i,IVSIZE)) { ivsize=strtoul(ptr,&ptr,0); if(!ivsize) {return 1;} if(ivsize>2){return 1;} } else if(!matchident(&i,VECTOR)) { if(!ivtlen) {//quietly omit ivt, .ivtlen is set to 0 before .platform return 0; } if(ivtlen==-1) {clidisplay("need .ivtlen before .vector!!",&i.len,i.p);return 1;} if(!ivt) { ivt=(UL*)calloc(ivtlen,4); if(!ivt){return 1;} } //ivt index is 1-based, leaving entry 0 for startup stack pointer val=strtoul(ptr,&ptr,0);if(!val){return 1;}//val--; if(expect(&ptr,'(')){return 1;} while(*ptr!=')') { if(val>=ivtlen) {//quietly truncate ivt, .ivtlen is set before .platform return 0; } if(blnk(&ptr)){return 1;} if(*ptr=='-'){ptr++;blnk(&ptr);if(*ptr==')'){break;}} if(*ptr==','){ptr++;} else if(!ident(&op1,&ptr)) { UL lsyoff; if(addsym(op1.p,op1.len,stCODE,utpointer(0,0),&lsyoff,-1)){return 1;} ivt[val]=lsyoff; if(blnk(&ptr)){return 1;} if(*ptr==','){ptr++;} } else{return 1;} val++; } } else if(!matchident(&i,SRAMBASE)) { if(!imm(&op1,&ptr)) { addmacro(&i,&op1,0); sramb=op1.no; inlinedat=0;//inlinedat and sramaddressing are mutually exclusive sramaddressing=1; } } else if(!matchident(&i,SRAMTOP)) { sramtop=strtoul(ptr,&ptr,0); } else if(!matchident(&i,INCLUDE)) { while(isspace(*ptr)){ptr++;}if(!*ptr){return 1;} if(*ptr!='{'){return 1;} //opening brace expected ptr++; //skip '{' if(ident(&op1,&ptr)){return 1;} //filename expected while(isspace(*ptr)){ptr++;}if(!*ptr){return 1;} if(*ptr!='}'){return 1;} //closing brace expected ptr++; //skip '}' if(arminclude(a,op1)){return 1;} } else if(!matchident(&i,ORG)) { UL org=strtoul(ptr,&ptr,0); if(org< flashbase) {clidisplay(".org target less than flash base address!",&i.len,i.p);return 1;} UL newedo=org-flashbase; endorg=a->edo; a->edo=newedo; // if(newedo>=a->edo){a->edo=newedo;} // else{clidisplay(".org target less than edo!",&i.len,i.p);return 1;} } else if(!matchident(&i,ENDORG)) { a->edo=endorg; } else if(!matchident(&i,POOL)) { emptyliteralpool(a); } else if(!matchident(&i,IF)) { if(condition){clidisplay("nested .if not allowed!");return 1;} condition=strtoul(ptr,&ptr,16); } else if(!matchident(&i,ENDIF)) { if(!condition){clidisplay(".endif before .if not allowed!");return 1;} condition=0; } else if(!matchident(&i,ALIGN)) { brk if(a->edo&1) { emit1(a,0xaa); } if(a->edo&2) { emit2(a,0xaaaa); } return 0; } else if(!matchident(&i,COMPILERTEST)) { compilertest=strtoul(ptr,&ptr,0); } else if(!matchident(&i,REGISTERBANK)) { n=strtoul(ptr,&ptr,0); if((n>=4)&&(n<=8)){AREGMAX=n;} else{clidisplay(".registerbank minimum 4 maximum 8!");return 1;} } else if(!matchident(&i,BINFILE)) { binfile=1; } else if(!matchident(&i,PMODE)) { if(!ident(&op1,&ptr)) { if(!matchident(&op1,PMODEARM)) { pmode=0; } else if(!matchident(&op1,PMODETHUMB)) { pmode=1; } else{clidisplay("unrecognised parameter for .pmode directive (not arm or thumb!)");return 1;} } } else if(!matchident(&i,INITIALJUMP)) { if(!ident(&op1,&ptr)) { if(!matchident(&op1,PMODEARM)) { initialjump=INITJUMPARM; } else if(!matchident(&op1,PMODETHUMB)) { initialjump=INITJUMPTHUMB; } else{clidisplay("unrecognised parameter for .initialjump directive (not arm or thumb!)");return 1;} } } else if(!matchident(&i,RELOCATABLE)) { relocatable=1;flashbase=0; } else {//quietly skip unrecognised .dot directives return 0; // clidisplay("Unknown .dot directive .%#sc1400",&i.len,i.p);return 1; } return 0; } else if(isdigit(*ptr)) {//skip arm disassembly address dump val=strtol(ptr,&ptr,16); if(*ptr==':'){ptr++;} while(isspace(*ptr)){ptr++;} // goto SKIP; } // else while(!declaration(a,&ptr)) // { // } //28.5.2015 multiassembler implementation //the idea is to allow multiple assembly language statements on one source line, //separated by semicolons. All successful exits from the assembler below are //directed to DONE: instead of returning 0 //There we can check for the semicolon, to L01 to process another statement... if(recurse){ptr=li->text+lineoffset;} UL mnoffset; L01: if((!recurse)&&(!(a->edo&2))) //p:arm/arm1 567 { //------------------------------------------------------------------- //PRE-EMPTIVE POOL DUMP to stop Cortex-M0 LDR (literal) //from going out of range. MESSY, but can't think of anything better //------------------------------------------------------------------- //there is a possibility that 16-bit LDR (literal) instructions in the //code stream will go out of range if pool dumps are not performed //often enough. poolrange contains the edo of the last dump, so when //edo-poolrange approaches 0x3fc, any LDR (literal) instructions just //after the last dump will be approaching maximum range when resolved //to the next dump. //the code below is triggered at > 0x300 from the last dump, allowing //a maximum of 0xfc bytes for the dump itself (dependent on alignment) //cleverer code would keep track of the first LDR (literal) instruction //after the last dump, and monitor the total number of pool variables //ready for dumping, to stretch the equations to the limit //A 16-bit jump over the pool variables emitted, so program flow //is unaffected. If no pool varables exist, no code is generated //a couple of hard breakpoints have been left in place below in case //things go out of limits - so long as emptypool is called regularly //these limits are unlikely to be be reached. Thumb2 instructions //allow a much greater range using LDR.W, as well as negative offsets. //However for time being I will use the 16-bit positive-only LDR //for all ARM Thumb cpus, to keep things simple. //29.1.16 pool variables may be output before they are used, especially //constant character string operands which get linked up at the end //of fct-body. Duplicate pool varables will be generated when the //PC-offset is found to be negative, and code will link to the latest //record according to revsynearest().. The first orphaned record has //a relocation record, to patch in the runtime address. See addbranch //for the kludge code used to find and patch this relocation records. UL poolcheck=a->edo-poolrange; if(poolcheck>0x300) //16-bit LDR (literal) offset is max 0x3fc { //allow slack for up to 252 bytes of pool data //brk // srvdisplay("poolcheck %08X",&poolcheck); UL jmpins=a->edo; emit2(a,0xbbbb); emptypool(a,1); //p:arm/arm2 239 UL jmpdst=a->edo-jmpins; if(jmpdst==2) {//pool was empty, rewind a->edo-=2; a->pc=(UI*)(a->buf+a->hdrlen+a->edo); } else { jmpdst-=4; // if(jmpins&2){jmpdst-=2;} if(jmpdst>1020){brk;} //pool data > 252 dwords?? jmpdst>>=1; UI* poke=(UI*)(a->buf+a->hdrlen+jmpins); *poke=0xe000+jmpdst; } } } blnk(&ptr); if(*ptr=='}'){brk;return 0;} //quietly return, maybe end of asm{} block mnoffset=ptr-li->text; if(ident(&i,&ptr)) { return ptr-li->text; } UI* pcw=(UI*)a->pc; UL* pcd=(UL*)a->pc; UL immbits; UL imm1,imm8,imm6,imm5,imm4,imm3,tgt,cond,th; SL tgtoff; UL* cptr; UL j1,j2,i1,i2,imm10,imm11,shift; UL Rm,Rd,S=0; //ARM instruction summary (NOT Cortex-M3!)//P:arm/arm_inst //Cortex-M3 instruction summary 16-bit //p:arm/cortex_m3 44 //Cortex-M3 instruction summary 32-bit //p:arm/cortex_m3 47 if(!pmode) { if(armassemble(a,li,lineoffset,&ptr,&i,recurse)){return ptr-li->text;} else {goto DONE;} } else if((!matchident(&i,ASR))||(S=(!matchident(&i,ASRS)))) { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 237 opcode=0x4100+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else {ptrsave=ptr; if((!imm(&op3,&ptr))&&(op3.no<32)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 235 opcode=0x1000+(op2.no<<3)+op1.no+(op3.no<<6);emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { //p:arm/arm2 235 opcode=0xea4f0020+(op1.no<<8)+op2.no+(S<<20)+((op3.no&0x1c)<<10)+((op3.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 237 opcode=0xfa40f000+(op2.no<<16)+(op1.no<<8)+op3.no+(S<<20); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else {return ptr-li->text;} } } else if((!matchident(&i,LSL))||(!matchident(&i,SHL))||(S=(!matchident(&i,LSLS)))) { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 335 opcode=0x4080+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else {ptrsave=ptr; if((!imm(&op3,&ptr))&&(op3.no<32)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 333 opcode=0x0000+(op2.no<<3)+op1.no+(op3.no<<6);emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { //p:arm/arm2 333 opcode=0xea4f0000+(op1.no<<8)+op2.no+(S<<20)+((op3.no&0x1c)<<10)+((op3.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 335 opcode=0xfa00f000+(op2.no<<16)+(op1.no<<8)+op3.no+(S<<20); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else {return ptr-li->text;} } } else if((!matchident(&i,LSR))||(!matchident(&i,SHR))||(S=(!matchident(&i,LSRS)))) { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 339 opcode=0x40c0+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else {ptrsave=ptr; if((!imm(&op3,&ptr))&&(op3.no<32)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 337 opcode=0x0800+(op2.no<<3)+op1.no+(op3.no<<6);emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { //p:arm/arm2 337 opcode=0xea4f0010+(op1.no<<8)+op2.no+(S<<20)+((op3.no&0x1c)<<10)+((op3.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 339 opcode=0xfa20f000+(op2.no<<16)+(op1.no<<8)+op3.no+(S<<20); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else {return ptr-li->text;} } } else if((!matchident(&i,ROR))||(S=(!matchident(&i,RORS)))) { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 389 opcode=0x41c0+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else {ptrsave=ptr; if((!imm(&op3,&ptr))&&(op3.no<32)&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { //p:arm/arm2 405 opcode=0xea4f0030+(op1.no<<8)+op2.no+(S<<20)+((op3.no&0x1c)<<10)+((op3.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 407 opcode=0xfa60f000+(op2.no<<16)+(op1.no<<8)+op3.no+(S<<20); emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else {return ptr-li->text;} } } else if((!matchident(&i,ADC))||(S=(!matchident(&i,ADCS)))) { //p:arm/arm2 217 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto ADCIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 217 ADCIMM: opcode=0xf1400000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 219 opcode=0xeb400000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 219 opcode=0xeb400000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 219 opcode=0x4140+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 219 opcode=0xeb400000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchident(&i,ADD))||(S=(!matchident(&i,ADDS)))) { //p:arm/arm2 217 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))) { if((op1.no==13)&&(op2.no<0x200)&&(!(op2.no&0x03))) { //p:arm/arm2 225 opcode=0xb000+(op2.no>>2); emit2(a,opcode);goto DONE; } //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto ADDIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if(!imm(&op3,&ptr)) { ADDIMM: if((op1.no<8)&&(op2.no==13)&&(op3.no<0x100)) { //p:arm/arm2 225 opcode=0xa800+(op1.no<<8)+op3.no; emit2(a,opcode);goto DONE; } else if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 221 opcode=0x1c00+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op1.no<8)&&(op1.no==op2.no)&&(op3.no<0x100)) { //p:arm/arm2 221 opcode=0x3000+(op1.no<<8)+op3.no; emit2(a,opcode);goto DONE; } else if(thumbexpandable(op3.no,&th)) { //p:arm/arm2 221 opcode=0xf1000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if(op3.no<0x1000) { opcode=0xf2000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+((op3.no&0x800)<<15)+((op3.no&0x700)<<4)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { //p:arm/arm2 223 shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 219 opcode=0xeb000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 223 opcode=0x1800+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 219 opcode=0xeb000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 223 opcode=0x1800+(op2.no<<6)+(op1.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 223 opcode=0x4400+(op2.no<<3)+((op1.no&8)<<4)+(op1.no&7); emit2(a,opcode);goto DONE; } // else // { //p:arm/arm2 223 // opcode=0xeb000000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; // emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; // } } return ptr-li->text; } else if((!matchident(&i,AND))||(S=(!matchident(&i,ANDS)))) { //p:arm/arm2 231 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto ANDIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 231 ANDIMM: opcode=0xf0000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 233 opcode=0xea000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 233 opcode=0xea000000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 233 opcode=0x4000+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 233 opcode=0xea000000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchident(&i,BIC))||(S=(!matchident(&i,BICS)))) { //p:arm/arm2 243 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto BICIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 243 BICIMM: opcode=0xf0200000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 245 opcode=0xea200000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 245 opcode=0xea200000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 245 opcode=0x4380+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 245 opcode=0xea200000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchident(&i,CMN))||(S=(!matchident(&i,CMNS)))) { //p:arm/arm2 257 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: opcode=0xf1100f00+(S<<20)+(op1.no<<16)+(op1.no<<8)+th; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } ptr=ptrsave; //p:arm/arm2 259 if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 259 opcode=0xeb100f00+(S<<20)+(op1.no<<16)+op2.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 259 opcode=0x42c0+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 259 opcode=0xeb100f00+(S<<20)+(op1.no<<16)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } // else if(!matchident(&i,CMP)) //P:arm/arm2 156 // { //P:arm/arm2 158 // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(!ident(&op2,&ptr)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //P:arm/arm2 263 // opcode=0x4280+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else{return ptr-li->text;} // } // else{return ptr-li->text;} // } else if((!matchident(&i,CMP))||(S=(!matchident(&i,CMPS)))) { //p:arm/arm2 261 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))) { if((op1.no<8)&&(op2.no<0x100)) { //p:arm/arm2 261 opcode=0x2800+(op1.no<<8)+op2.no; emit2(a,opcode);goto DONE; } else if(thumbexpandable(op2.no,&th)) { //p:arm/arm2 261 //if immediate follows first comma, src reg= dst reg: opcode=0xf1b00f00+(S<<20)+(op1.no<<16)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } ptr=ptrsave; //p:arm/arm2 259 if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 263 opcode=0xebb00f00+(S<<20)+(op1.no<<16)+op2.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 263 opcode=0x4280+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 263 opcode=0x4500+(op2.no<<3)+((op1.no&8)<<4)+(op1.no&7); emit2(a,opcode);goto DONE; } // else // { //p:arm/arm2 259 // opcode=0xebb00f00+(S<<20)+(op1.no<<16)+op2.no; // emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; // } } return ptr-li->text; } //EOR (immediate) EORS Rd,Rn,#tximm //p:arm/arm2 271 //* // EOR{c} Rd,Rn,#tximm //p:arm/arm2 271 //* // (register) EOR{c} Rd,Rm //p:arm/arm2 273 //* // EOR{c} Rd,Rm //p:arm/arm2 273 //* // EOC{c} Rt,Rn,Rm //p:arm/arm2 273 //* // EORS{c} Rt,Rn,Rm //p:arm/arm2 273 //* // EOR{c} Rt,Rn,Rm{,lsl #imm2} //p:arm/arm2 273 //* // EORS{c} Rt,Rn,Rm{,lsl #imm2} //p:arm/arm2 273 //* else if((!matchident(&i,EOR))||(S=(!matchident(&i,EORS)))) { //p:arm/arm2 273 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto EORIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 271 EORIMM: opcode=0xf0800000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 273 opcode=0xea800000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 273 opcode=0xea800000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 273 opcode=0x4040+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 273 opcode=0xea800000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchident(&i,B))||(!matchident(&i,JMP))) //P:arm/arm2 129 { //P:arm/arm2 239 while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op1.p,op1.len,&s))&&(s->rtaddr!=-1)) { tgtoff=a->edo&~1; //p:arm/arm1 535 tgtoff+=4; tgtoff=s->rtaddr-tgtoff-flashbase; //symbol address known, short negative offset may be possible //otherwise we need leave space for the 32-bit opcode if((tgtoff>=-2048)&&(tgtoff<=0)&&!recurse) //P:arm/arm2 240 { //p:arm/arm2 239 tgt=tgtoff;tgt>>=1; // if(a->edo&2){tgt--;} tgt&=0x07ff; opcode=0xe000+tgt;emit2(a,opcode);goto DONE; } else if(cortexm0&&(tgtoff<2047)) { if(tgtoff<2047) { tgt=tgtoff;tgt>>=1; tgt&=0x07ff; opcode=0xe000+tgt;emit2(a,opcode);goto DONE; } else { brk return ptr-li->text; } } else if((tgtoff>=-16777216)&&(tgtoff<=0)&&!recurse) { //P:arm/arm2 239 tgtoff>>=1; if(tgtoff<0){imm1=1;}else{imm1=0;} //'S' bit i1=(tgtoff>>22)&1; i2=(tgtoff>>21)&1; j1=imm1^i1;j1^=1;j1<<=13; j2=imm1^i2;j2^=1;j2<<=11; imm1<<=10; imm11=tgtoff&0x07ff; imm10=(tgtoff&0x1ff800)>>11; opcode=0xf000+imm1+imm10; emit2(a,opcode); opcode=0x9000+j1+j2+imm11;emit2(a,opcode);goto DONE; } else if((tgtoff>=-16777216)&&(tgtoff<=16777214)) { //P:arm/arm2 239 tgtoff>>=1; if(tgtoff<0){imm1=1;}else{imm1=0;} //'S' bit i1=(tgtoff>>22)&1; i2=(tgtoff>>21)&1; j1=imm1^i1;j1^=1;j1<<=13; j2=imm1^i2;j2^=1;j2<<=11; imm1<<=10; imm11=tgtoff&0x07ff; imm10=(tgtoff&0x1ff800)>>11; opcode=0xf000+imm1+imm10; emit2(a,opcode); opcode=0x9000+j1+j2+imm11;emit2(a,opcode);goto DONE; } } else if(!recurse) {//leave space for 32-bit opcode if(cortexm0) {addbranch(a,a->line,&op1,lineoffset,2);emit2(a,0);goto DONE;} else{addbranch(a,a->line,&op1,lineoffset,4);emit4(a,0);goto DONE;} } else{return ptr-li->text;} } //P:arm/arm2 357 //P:arm/arm2 624 //P:arm/arm2 803 else if(!matchident(&i,BEQ)) //P:arm/arm2 129 { //p:arm/arm2 239 cond=0; CONDITIONALBRANCH: while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op1.p,op1.len,&s))&&(s->rtaddr!=-1)) { tgtoff=s->rtaddr-a->edo-flashbase-4; if((tgtoff>=-512)&&(tgtoff<=510)&&cortexm0) {//16-bit opcode is possible //p:arm/arm2 239 tgtoff>>=1; tgtoff&=0xff; opcode=0xd000+(cond<<8)+tgtoff; emit2(a,opcode);goto DONE; opcode=0; emit2(a,opcode); } brk //warning: not Cortex M0! (only 2 bytes in codestream!) tgtoff>>=1; S=tgtoff&0x00080000; i1=(S>>1)+(S>>2);//imask // i1^=0x00060000; if(!S){tgtoff^=i1;} j1=(tgtoff&0x00040000)>>18; j2=(tgtoff&0x00020000)>>17; S>>=9; imm11=tgtoff&0x07ff; imm6=(tgtoff&0x01f800)>>11; opcode=0xf000+S+(cond<<6)+imm6; emit2(a,opcode); opcode=0x8000+(j1<<13)+(j2<<11)+imm11;emit2(a,opcode);goto DONE; } else if(!recurse) { // //leave space for 32-bit opcode // addbranch(a,a->line,&op1,lineoffset,4);emit4(a,0);goto DONE; //leave space for 16-bit opcode addbranch(a,a->line,&op1,lineoffset,2);emit2(a,0);goto DONE; } else{return ptr-li->text;} } else if(!matchident(&i,BNE)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=1;goto CONDITIONALBRANCH; } else if(!matchident(&i,BAE)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=2;goto CONDITIONALBRANCH; } else if(!matchident(&i,BB)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=3;goto CONDITIONALBRANCH; } else if(!matchident(&i,BMI)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=4;goto CONDITIONALBRANCH; } else if(!matchident(&i,BPL)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=5;goto CONDITIONALBRANCH; } else if(!matchident(&i,BA)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=8;goto CONDITIONALBRANCH; } else if(!matchident(&i,BBE)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=9;goto CONDITIONALBRANCH; } else if(!matchident(&i,BGE)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=10;goto CONDITIONALBRANCH; } else if(!matchident(&i,BLT)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=11;goto CONDITIONALBRANCH; } else if(!matchident(&i,BGT)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=12;goto CONDITIONALBRANCH; } else if(!matchident(&i,BLE)) //p:arm/arm2 129 { //p:arm/arm2 239 cond=13;goto CONDITIONALBRANCH; } else if(!matchident(&i,BL)) //p:arm/arm2 129 { //p:arm/arm2 248 while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op1.p,op1.len,&s))&&(s->rtaddr!=-1)) { tgtoff=a->edo&~1; tgtoff+=4; tgtoff=s->rtaddr-tgtoff-flashbase; //symbol already exists, negative offset may be possible //otherwise we need leave space for the 32-bit opcode if((tgtoff>=-16777216)&&(tgtoff<=16777214)) { //P:arm/arm2 248 tgtoff>>=1; if(tgtoff<0){imm1=1;}else{imm1=0;} //'S' bit i1=(tgtoff>>22)&1; i2=(tgtoff>>21)&1; j1=imm1^i1;j1^=1;j1<<=13; j2=imm1^i2;j2^=1;j2<<=11; imm1<<=10; imm11=tgtoff&0x07ff; imm10=(tgtoff&0x1ff800)>>11; opcode=0xf000+imm1+imm10; emit2(a,opcode); opcode=0xd000+j1+j2+imm11;emit2(a,opcode);goto DONE; } else {return ptr-li->text;} //out of range? } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op1,lineoffset,4);emit4(a,0);goto DONE; } else{return ptr-li->text;} } else if(!matchident(&i,BKPT)) //p:arm/arm2 247 { opcode=0xbe00; if(!imm(&op1,&ptr)){opcode+=op1.no&0xff;} emit2(a,opcode);goto DONE; } else if(!matchident(&i,SWI)) //p:arm/arm2 503 { opcode=0xbf00; if(!imm(&op1,&ptr)){opcode+=op1.no&0xff;} emit2(a,opcode);goto DONE; } else if(!matchident(&i,SVC)) //p:arm/arm2 503 { opcode=0xbf00; if(!imm(&op1,&ptr)){opcode+=op1.no&0xff;} emit2(a,opcode);goto DONE; } else if(!matchident(&i,BX)) //P:arm/arm2 129 { //P:arm/arm2 250 while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(!matchr00_15(&op1)) { //P:arm/arm2 250 opcode=0x4700+(op1.no<<3);emit2(a,opcode);goto DONE; } else {return ptr-li->text;} //p:arm/arm1 49 } //p:arm/arm1 74 else if((!matchident(&i,MRS))&&(!pmode)) //p:arm/arm1 224 {brk if((!ident(&op1,&ptr))&&(!matchr00_15(&op1))) { opcode=0xe10f0000|(op1.no<<12); emit4(a,opcode);goto DONE; } else{return ptr-li->text;} //register operand expected } else if((!matchident(&i,BLX))&&(!pmode)) //p:arm/arm1 545 { // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op1.p,op1.len,&s))&&(s->rtaddr!=-1)) { tgtoff=a->edo&~3; tgtoff+=8; tgtoff=s->rtaddr-tgtoff-flashbase; UL blxl=tgtoff&2; //symbol already exists, negative offset may be possible //otherwise we need leave space for the 32-bit opcode if((tgtoff>=-16777216)&&(tgtoff<=16777214)) { tgtoff>>=2; tgtoff&=0x00ffffff; opcode=0xfa000000|tgtoff; //p:arm/arm1 545 if(blxl){opcode|=0x01000000;} emit4(a,opcode);goto DONE; } else {return ptr-li->text;} //out of range? } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op1,lineoffset,4);emit4(a,0);goto DONE; } else{return ptr-li->text;} } else if(!matchident(&i,BLX)) //P:arm/arm2 129 { //p:arm/arm2 249 while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(!matchr00_15(&op1)) //p:arm/arm1 545 { //p:arm/arm2 249 opcode=0x4780+(op1.no<<3);emit2(a,opcode);goto DONE; } else {return ptr-li->text;} } //p:arm/arm1 247 else if(!matchident(&i,DMB)) //p:arm/arm2 247 { opcode=0xf3bf;emit2(a,opcode); opcode=0x8f5f;emit2(a,opcode);goto DONE; } // else if(!matchident(&i,CMP)) //P:arm/arm2 156 // { //P:arm/arm2 158 // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(!ident(&op2,&ptr)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //P:arm/arm2 263 // opcode=0x4280+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else{return ptr-li->text;} // } // else{return ptr-li->text;} // } // else if((!matchident(&i,LSL))||(!matchident(&i,SHL)))//P:arm/arm2 156 // { //P:arm/arm2 157 // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}//if(!*ptr){return ptr-li->text;} // if(*ptr!=',') // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //P:arm/arm2 335 // opcode=0x4080+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } // else // { // ptr++; //skip comma // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // ptrsave=ptr; // if(!imm(&op3,&ptr)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))&&(op3.no>=0)&&(op3.no<32)) // { //P:arm/arm2 333 // opcode=0x0000+(op3.no<<6)+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } // else{return ptr-li->text;} // } // } // else if((!matchident(&i,LSR))||(!matchident(&i,SHR)))//P:arm/arm2 156 // { //P:arm/arm2 157 // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}//if(!*ptr){return ptr-li->text;} // if(*ptr!=',') // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //p:arm/arm2 339 // opcode=0x40c0+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } // else // { // ptr++; //skip comma // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // ptrsave=ptr; // if(!imm(&op3,&ptr)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))&&(op3.no>=0)&&(op3.no<32)) // { //p:arm/arm2 337 // opcode=0x0800+(op3.no<<6)+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } // else{return ptr-li->text;} // } // } else if(!matchident(&i,LDR)) //P:arm/arm2 287 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { //brk if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 291 opcode=0x5800+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 291 opcode=0xf8500000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 287 if((op1.no<8)&&(op2.no<8)&&(op3.no>=0)&&(op3.no<0x80)&&(!(op3.no&3))) { opcode=0x6800+(op3.no<<4)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op1.no<8)&&(op2.no==13)&&(op3.no<0x400)&&(!(op3.no&3))) { //p:arm/arm2 287 opcode=0x9800+(op1.no<<8)+(op3.no>>2); emit2(a,opcode);goto DONE; } else if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 287 op3.no=-op3.no; opcode=0xf8500c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 287 opcode=0xf8d00000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //P:arm/arm2 287 opcode=0x6800+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } } } return ptr-li->text; } else {//LDR (literal) if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected // if((!revsymatch(op2.p,op2.len,&s))&&(s->rtaddr!=-1)) if((!revsynearest(op2.p,op2.len,&s,a->edo+flashbase)))//&&(s->rtaddr!=-1)) { //p:arm/arm2 289 tgtoff=s->rtaddr-a->edo-4-flashbase; if(a->edo&2){tgtoff+=2;} //symbol rtaddr is known, short offset may be possible //otherwise we need to leave space for the 32-bit opcode // if((!matchr00_07(&op1))&&(tgtoff>0)&&(tgtoff<=1020))//&&!recurse) // { //p:arm/arm2 289 // tgt=tgtoff;if(a->edo&2){tgt+=2;}tgt>>=2; // opcode=0x4800+(op1.no<<8)+(tgt&0xff);emit2(a,opcode); //// if(recurse&&(!cortexm0)){opcode=0;emit2(a,opcode);} // goto DONE; // } if((!matchr00_07(&op1)))//&&(tgtoff>0)&&(tgtoff<=1020))//&&!recurse) { //p:arm/arm2 289 if(tgtoff>0) { if(tgtoff<=1020) { tgt=tgtoff;if(a->edo&2){tgt+=2;}tgt>>=2; opcode=0x4800+(op1.no<<8)+(tgt&0xff);emit2(a,opcode); // if(recurse&&(!cortexm0)){opcode=0;emit2(a,opcode);} goto DONE; } else {//pool var out of range!! //add code here to search further back in sym table //until all matches have been tried brk return ptr-li->text; } } else { //leave space for 16-bit opcode // s->scope|=0x80000000; addbranch(a,a->line,&op2,lineoffset,2);emit2(a,0); goto DONE; } } //32-bit encoding disabled at present, should be unnecessary as long as //emptypool() is called before PC goes out of range for the 16-bit encoding //i.e. 1020 bytes // if((!matchr00_15(&op1))&& // (tgtoff>=-4095)&& // (tgtoff<=4095)&& // (!cortexm0)) // {//T2 //p:arm/arm2 289 // if(tgtoff&0x80000000){imm1=0;tgtoff=-tgtoff;}else{imm1=1;} //U bit // opcode=0xf85f+(imm1<<7); emit2(a,opcode); // opcode=(op1.no<<12)+(tgtoff&0xfff);emit2(a,opcode);goto DONE; // } } else if(!recurse) { //addbranch fail here is probably unreachable assembly symbol //'_p' prefix will generate a reachable pool alias if(addbranch(a,a->line,&op2,lineoffset,2)){return ptr-li->text;} //leave space for 16-bit opcode emit2(a,0); // //leave space for 16-bit opcode // if(cortexm0){addbranch(a,a->line,op2,lineoffset,2);emit2(a,0);} // //leave space for 32-bit opcode // else {addbranch(a,a->line,op2,lineoffset,4);emit4(a,0);} goto DONE; } } return ptr-li->text; } else if(!matchident(&i,LDRB)) //p:arm/arm2 293 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 297 opcode=0x5c00+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 297 opcode=0xf8100000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 293 if((op1.no<8)&&(op2.no<8)&&(op3.no>=0)&&(op3.no<0x80)&&(!(op3.no&3))) { opcode=0x7800+(op3.no<<4)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 293 op3.no=-op3.no; opcode=0xf8100c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 293 opcode=0xf8900000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 293 opcode=0x7800+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } } } return ptr-li->text; } else {//LDRB (literal) if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op2.p,op2.len,&s))&&(s->rtaddr!=-1)) { //p:arm/arm2 295 tgtoff=s->rtaddr-a->edo-4-flashbase; if(a->edo&2){tgtoff+=2;} //symbol rtaddr is known, short offset may be possible //otherwise we need leave space for the 32-bit opcode if((!matchr00_15(&op1))&&(tgtoff>=-4095)&&(tgtoff<=4095)) {//T2 //p:arm/arm2 319 if(tgtoff&0x80000000){imm1=0;tgtoff=-tgtoff;}else{imm1=1;} //U bit opcode=0xf81f+(imm1<<7); emit2(a,opcode); opcode=(op2.no<<12)+(tgtoff&0xfff);emit2(a,opcode);goto DONE; } } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op2,lineoffset,4);emit4(a,0);goto DONE; } } } else if(!matchident(&i,LDRSB)) //p:arm/arm2 317 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 321 opcode=0x5600+(op2.no<<6)+(op3.no<<3)+op1.no; emit2(a,opcode);goto DONE; } //p:arm/arm1 275 else { //p:arm/arm2 321 opcode=0xf9100000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 317 if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 317 op3.no=-op3.no; opcode=0xf9100c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 317 opcode=0xf9900000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { opcode=0xf9900000+(op2.no<<16)+(op1.no<<12); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else {//LDRSB (literal) if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op2.p,op2.len,&s))&&(s->rtaddr!=-1)) { //p:arm/arm2 319 tgtoff=s->rtaddr-a->edo-4-flashbase; if(a->edo&2){tgtoff+=2;} //symbol rtaddr is known, short offset may be possible //otherwise we need leave space for the 32-bit opcode if((!matchr00_15(&op1))&&(tgtoff>=-4095)&&(tgtoff<=4095)) {//T2 //p:arm/arm2 319 if(tgtoff&0x80000000){imm1=0;tgtoff=-tgtoff;}else{imm1=1;} //U bit opcode=0xf91f+(imm1<<7); emit2(a,opcode); opcode=(op2.no<<12)+(tgtoff&0xfff);emit2(a,opcode);goto DONE; } } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op2,lineoffset,4);emit4(a,0);goto DONE; } } return ptr-li->text; } else if(!matchident(&i,LDRH)) //p:arm/arm2 309 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 313 opcode=0x5a00+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 313 opcode=0xf8300000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 309 if((op1.no<8)&&(op2.no<8)&&(op3.no>=0)&&(op3.no<0x80)&&(!(op3.no&3))) { //p:arm/arm2 309 opcode=0x8800+(op3.no<<4)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 309 op3.no=-op3.no; opcode=0xf8300c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 309 opcode=0xf8300000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 309 opcode=0x8800+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } } } return ptr-li->text; } else {//LDRH (literal) if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op2.p,op2.len,&s))&&(s->rtaddr!=-1)) { //p:arm/arm2 311 tgtoff=s->rtaddr-a->edo-4-flashbase; if(a->edo&2){tgtoff+=2;} //symbol rtaddr is known, short offset may be possible //otherwise we need leave space for the 32-bit opcode if((!matchr00_15(&op1))&&(tgtoff>=-4095)&&(tgtoff<=4095)) {//T2 //p:arm/arm2 311 if(tgtoff&0x80000000){imm1=0;tgtoff=-tgtoff;}else{imm1=1;} //U bit opcode=0xf83f+(imm1<<7); emit2(a,opcode); opcode=(op2.no<<12)+(tgtoff&0xfff);emit2(a,opcode);goto DONE; } } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op2,lineoffset,4);emit4(a,0);goto DONE; } } return ptr-li->text; } else if(!matchident(&i,LDRSH)) //p:arm/arm2 329 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 329 opcode=0x5e00+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 329 opcode=0xf9b00000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 325 if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 325 op3.no=-op3.no; opcode=0xf9300c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 325 opcode=0xf9b00000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { opcode=0xf9b00000+(op2.no<<16)+(op1.no<<12); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else {//LDRSH (literal) if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!revsymatch(op2.p,op2.len,&s))&&(s->rtaddr!=-1)) { //p:arm/arm2 311 tgtoff=s->rtaddr-a->edo-4-flashbase; if(a->edo&2){tgtoff+=2;} //symbol rtaddr is known, short offset may be possible //otherwise we need leave space for the 32-bit opcode if((!matchr00_15(&op1))&&(tgtoff>=-4095)&&(tgtoff<=4095)) {//T2 //p:arm/arm2 327 if(tgtoff&0x80000000){imm1=0;tgtoff=-tgtoff;}else{imm1=1;} //U bit opcode=0xf93f+(imm1<<7); emit2(a,opcode); opcode=(op2.no<<12)+(tgtoff&0xfff);emit2(a,opcode);goto DONE; } } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op2,lineoffset,4);emit4(a,0);goto DONE; } } return ptr-li->text; } else if((!matchident(&i,MOV))||(S=(!matchident(&i,MOVS)))) //p:arm/arm2 347 { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} ptrsave=ptr; if(!imm(&op2,&ptr)) {//p:arm/arm2 347 //encode move immediate value immbits=sigbits(op2.no); if((!matchr00_07(&op1))&&(immbits<=8)) { //T1 encoding //p:arm/arm2 347 opcode=0x2000+(op1.no<<8)+op2.no;emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(immbits<=16)) { //T3 encoding //p:arm/arm2 347 imm4=(op2.no&0xf000)>>12; imm1=(op2.no&0x800)>>1; imm3=(op2.no&0x700)<<4; imm8=op2.no&0xff; opcode=0xf240+imm1+imm4; emit2(a,opcode); opcode=imm3+(op1.no<<8)+imm8;emit2(a,opcode);goto DONE; } else { //p:arm/arm2 347 if(thumbexpandable(op2.no,&th)) { opcode=0xf04f0000+(op1.no<<8)+th; emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else { //encode MOV and MOVT instructions //T3 encoding //p:arm/arm2 347 imm4=(op2.no&0xf000)>>12; imm1=(op2.no&0x800)>>1; imm3=(op2.no&0x700)<<4; imm8=op2.no&0xff; opcode=0xf240+imm1+imm4; emit2(a,opcode); opcode=imm3+(op1.no<<8)+imm8;emit2(a,opcode); imm4=(op2.no&0xf0000000)>>28; imm1=(op2.no&0x8000000)>>17; imm3=(op2.no&0x7000000)>>12; imm8=(op2.no&0xff0000)>>16; opcode=0xf2c0+imm1+imm4; emit2(a,opcode); opcode=imm3+(op1.no<<8)+imm8;emit2(a,opcode);goto DONE; } } } //MOV reg,reg to go here ptr=ptrsave; if(!ident(&op2,&ptr)) { // if((!matchr08_15(&op1))&&(!matchr08_15(&op2))) // {brk //P:arm/arm2 349 // opcode=0x4600+((op1.no&0x08)<<4)+(op2.no<<3)+(op1.no&0x07); // emit2(a,opcode);goto DONE; // } if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { //p:arm/arm2 349 if(S) { opcode=0xea4f0000+(S<<20)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else { opcode=0x4600+((op1.no&8)<<4)+(op2.no<<3)+(op1.no&7); emit2(a,opcode);goto DONE; // opcode=0xea5f; emit2(a,opcode); // opcode=(op1.no<<8)+op2.no;emit2(a,opcode);goto DONE; } } if((!revsymatch(op2.p,op2.len,&s))&&(s->rtaddr!=-1)) { op2.no=s->rtaddr; if(isfunction(s->ut)){brk op2.no|=1;} //encode MOV and MOVT instructions //T3 encoding //p:arm/arm2 347 imm4=(op2.no&0xf000)>>12; imm1=(op2.no&0x800)>>1; imm3=(op2.no&0x700)<<4; imm8=op2.no&0xff; opcode=0xf240+imm1+imm4; emit2(a,opcode); opcode=imm3+(op1.no<<8)+imm8;emit2(a,opcode); imm4=(op2.no&0xf0000000)>>28; imm1=(op2.no&0x8000000)>>17; imm3=(op2.no&0x7000000)>>12; imm8=(op2.no&0xff0000)>>16; opcode=0xf2c0+imm1+imm4; emit2(a,opcode); opcode=imm3+(op1.no<<8)+imm8;emit2(a,opcode);goto DONE; } else if(!recurse) {//leave space for 32-bit opcode addbranch(a,a->line,&op2,lineoffset,8);emit4(a,0);emit4(a,0);goto DONE; } else{return ptr-li->text;} } else {return ptr-li->text;} } //MVN (immediate) MVNS{c} Rd,#tximm //p:arm/arm2 361 //* // MVN{c} Rd,#tximm //p:arm/arm2 361 //* // (register) MVNS rd,rn //p:arm/arm2 363 //* // MVN{c} rd,rn //p:arm/arm2 363 //* // MVNS{c} Rd,Rn //p:arm/arm2 363 //* // MVN{c} Rd,Rn //p:arm/arm2 363 //* else if((!matchident(&i,MVN))||(S=(!matchident(&i,MVNS)))) { //p:arm/arm2 361 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: opcode=0xf06f0000+(S<<20)+(op1.no<<8)+th;// emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } ptr=ptrsave; //p:arm/arm2 363 if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 363 opcode=0xea6f0000+(S<<20)+(op1.no<<8)+op2.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 259 opcode=0x43c0+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 259 opcode=0xea6f0000+(S<<20)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if(!matchident(&i,MOVT)) //P:arm/arm2 352 { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} if(!imm(&op2,&ptr)) {//p:arm/arm2 352 //encode move immediate value immbits=sigbits(op2.no); if((!matchr00_15(&op1))&&(immbits<=16)) { //T1 encoding //p:arm/arm2 347 imm4=(op2.no&0xf000)>>12; imm1=(op2.no&0x800)>>1; imm3=(op2.no&0x700)<<4; imm8=op2.no&0xff; opcode=0xf2c0+imm1+imm4; emit2(a,opcode); opcode=imm3+(op1.no<<8)+imm8;emit2(a,opcode);goto DONE; } } //many more MOV encodingsto go here else {return ptr-li->text;} } else if(!matchident(&i,SDIV)) //p:arm/arm2 423 {//brk if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((expect(&ptr,COMMA))&&((!matchr00_15(&op1))&&(!matchr00_15(&op2)))) { //p:arm/arm2 529 opcode=0xfb90f0f0+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else if((!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 359 opcode=0xfb90f0f0+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else if(!matchident(&i,UDIV)) //p:arm/arm2 529 {//brk if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((expect(&ptr,COMMA))&&((!matchr00_15(&op1))&&(!matchr00_15(&op2)))) { //p:arm/arm2 529 opcode=0xfbb0f0f0+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else if((!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 359 opcode=0xfbb0f0f0+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else if(!matchident(&i,MUL)) //p:arm/arm2 359 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)) { // brk if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 359 opcode=0x4340+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } else return ptr-li->text; } else if((!ident(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))&&(!matchr00_15(&op3))) { //p:arm/arm2 359 opcode=0xfb00f000+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode);goto DONE; } else{return ptr-li->text;} } else if((!matchident(&i,ORN))||(S=(!matchident(&i,ORNS)))) { //p:arm/arm2 367 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto ORNIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 367 ORNIMM: opcode=0xf0600000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 369 opcode=0xea600000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 245 opcode=0xea600000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset //p:arm/arm2 369 opcode=0xea600000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } else if((!matchident(&i,ORR))||(S=(!matchident(&i,ORRS)))) { //p:arm/arm2 371 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto ORRIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 371 ORRIMM: opcode=0xf0400000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 373 opcode=0xea400000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 373 opcode=0xea400000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 373 opcode=0x4300+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 373 opcode=0xea400000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } // else if((!matchident(&i,ORR))||(!matchident(&i,OR))) //P:arm/arm2 371 // {//brk // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // if(expect(&ptr,COMMA)){return ptr-li->text;} // if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected // if(expect(&ptr,COMMA)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //P:arm/arm2 373 // opcode=0x4300+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else return ptr-li->text; // } // else if((!imm(&op3,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) // { // if(thumbexpandable(op3.no,&th)) // { // opcode=0xf0400000+(op1.no<<16)+(op1.no<<8)+th; // emit2(a,opcode>>16);emit2(a,opcode);goto DONE; // } // else{return ptr-li->text;} // } // else{return ptr-li->text;} // } else if((!matchident(&i,RSB))||(S=(!matchident(&i,RSBS)))) { //p:arm/arm2 411 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto RSBIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 411 RSBIMM: opcode=0xf1c00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 413 opcode=0xebc00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 413 opcode=0xebc00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 413 opcode=0x4240+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 413 opcode=0xebc00000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchident(&i,SBC))||(S=(!matchident(&i,SBCS)))) { //p:arm/arm2 418 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto SBCIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if((!imm(&op3,&ptr))&&(thumbexpandable(op3.no,&th))) { //p:arm/arm2 418 SBCIMM: opcode=0xf1600000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 419 opcode=0xeb600000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { //p:arm/arm2 419 opcode=0xeb600000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 419 opcode=0x4180+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 419 opcode=0xeb600000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } // else if(!matchident(&i,POP)) //p:arm/arm2 387 // { // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // if(!matchr00_07(&op1)) // { //P:arm/arm2 387 // opcode=0xbc00; // n=1<< op1.no; // opcode|=n;emit2(a,opcode);goto DONE; // } // else if((!matchr00_15(&op1))&&(op1.no==15)) // { //p:arm/arm2 387 // opcode=0xbd00;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } // else if(!matchident(&i,PUSH)) //p:arm/arm2 389 // { // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // if(!matchr00_07(&op1)) // { //P:arm/arm2 389 // opcode=0xb400; // n=1<< op1.no; // opcode|=n;emit2(a,opcode);goto DONE; // } // else if((!matchr00_15(&op1))&&(op1.no==14)) // { //p:arm/arm2 389 // opcode=0xe92d;emit2(a,opcode); // opcode=0x4000;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } else if(!matchident(&i,POP)) //p:arm/arm2 387 { ctr=setmsk=0; if((!ident(&op1,&ptr))&&(!matchr00_15(&op1))) { if(!expect(&ptr,COMMA)) { ctr++;setmsk|=(1<< op1.no); while((!ident(&op1,&ptr))&&(!matchr00_15(&op1))) { ctr++;setmsk|=(1<< op1.no); if(expect(&ptr,COMMA)){break;} } if((setmsk&0x8000)&&(setmsk&0x4000)){return ptr-li->text;} if(setmsk&0x2000) {return ptr-li->text;} if(!(setmsk&0x5f00)) { if(setmsk&0x8000){setmsk&=0x7fff;setmsk|=0x100;} opcode=0xbc00+setmsk; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 387 opcode=0xe8bd0000+setmsk; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if(op1.no<8) { //p:arm/arm2 387 opcode=0xbc00+(1<< op1.no); emit2(a,opcode);goto DONE; } else if(op1.no==15) //p:arm/arm2 387 { opcode=0xbd00; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 387 opcode=0xf85d0b04+(op1.no<<12); emit2(a,opcode);goto DONE; } } else {return ptr-li->text;} } else if(!matchident(&i,PUSH)) //p:arm/arm2 389 { ctr=setmsk=0; if((!ident(&op1,&ptr))&&(!matchr00_15(&op1))) { if(!expect(&ptr,COMMA)) { ctr++;setmsk|=(1<< op1.no); while((!ident(&op1,&ptr))&&(!matchr00_15(&op1))) { ctr++;setmsk|=(1<< op1.no); if(expect(&ptr,COMMA)){break;} } if((setmsk&0x8000)&&(setmsk&0x4000)){return ptr-li->text;} if(setmsk&0xa000) {return ptr-li->text;} if(!(setmsk&0xbf00)) { if(setmsk&0x4000){setmsk&=0xff;setmsk|=0x100;} opcode=0xb400+setmsk; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 389 opcode=0xe92d0000+setmsk; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if(op1.no<8) { //p:arm/arm2 387 opcode=0xb400+(1<< op1.no); emit2(a,opcode);goto DONE; } else if(op1.no==14) //p:arm/arm2 387 { opcode=0xb500; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 387 opcode=0xf84d0d04+(op1.no<<12); emit2(a,opcode>>16);emit2(a,opcode+0xffff);goto DONE; } } else {return ptr-li->text;} } else if(!matchident(&i,POP3)) //P:arm/arm2 387 { opcode=0xbc0e;emit2(a,opcode);goto DONE; } else if(!matchident(&i,POP3S)) //P:arm/arm2 387 { opcode=0xbd0e;emit2(a,opcode);goto DONE; } else if(!matchident(&i,PUSH3)) //P:arm/arm2 389 { opcode=0xb40e;emit2(a,opcode);goto DONE; } else if(!matchident(&i,PUSH3S)) //P:arm/arm2 389 { opcode=0xe92d;emit2(a,opcode); opcode=0x400e;emit2(a,opcode);goto DONE; } else if(!matchident(&i,REV)) //p:arm/arm2 402 { if(!ident(&op1,&ptr)) { if(!expect(&ptr,',')) { if(!ident(&op2,&ptr)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 402 opcode=0xba00+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { opcode=0xfa90f080+(op2.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { if(!matchr00_07(&op1)) { //p:arm/arm2 402 opcode=0xba00+(op1.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if(!matchr00_15(&op1)) { opcode=0xfa90f080+(op1.no<<16)+(op1.no<<8)+op1.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } return ptr-li->text; } else if(!matchident(&i,REV16)) //p:arm/arm2 403 { if(!ident(&op1,&ptr)) { if(!expect(&ptr,',')) { if(!ident(&op2,&ptr)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 403 opcode=0xba40+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { opcode=0xfa90f090+(op2.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { if(!matchr00_07(&op1)) { //p:arm/arm2 402 opcode=0xba40+(op1.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if(!matchr00_15(&op1)) { opcode=0xfa90f090+(op1.no<<16)+(op1.no<<8)+op1.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } return ptr-li->text; } else if(!matchident(&i,REVSH)) //p:arm/arm2 404 { if(!ident(&op1,&ptr)) { if(!expect(&ptr,',')) { if(!ident(&op2,&ptr)) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 403 opcode=0xbac0+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { opcode=0xfa90f0b0+(op2.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else { if(!matchr00_07(&op1)) { //p:arm/arm2 402 opcode=0xbac0+(op1.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if(!matchr00_15(&op1)) { opcode=0xfa90f0b0+(op1.no<<16)+(op1.no<<8)+op1.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } return ptr-li->text; } // else if(!matchident(&i,ROR)) //P:arm/arm2 156 // { //P:arm/arm2 158 // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(!ident(&op2,&ptr)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //P:arm/arm2 407 // opcode=0x41c0+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else{return ptr-li->text;} // } // else{return ptr-li->text;} // } // else if(!matchident(&i,STR)) //P:arm/arm2 473 // { // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;}ptr++; //comma expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!='['){return ptr-li->text;}ptr++; //brace expected // if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=']'){return ptr-li->text;}ptr++; //brace expected // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) // { //P:arm/arm2 287 // opcode=0x6000+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // return ptr-li->text; // } else if(!matchident(&i,STR)) //p:arm/arm2 473 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 475 opcode=0x5000+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 475 opcode=0xf8400000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 473 if((op1.no<8)&&(op2.no<8)&&(op3.no>=0)&&(op3.no<0x80)&&(!(op3.no&3))) { opcode=0x6000+(op3.no<<4)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op1.no<8)&&(op2.no==13)&&(op3.no<0x400)&&(!(op3.no&3))) { //p:arm/arm2 473 opcode=0x9000+(op1.no<<8)+(op3.no>>2); emit2(a,opcode);goto DONE; } else if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 473 op3.no=-op3.no; opcode=0xf8400c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 473 opcode=0xf8c00000+(op2.no<<16)+(op1.no<<12)+(op3.no&0xfff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 473 opcode=0x6000+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } } } } return ptr-li->text; } else if(!matchident(&i,STRB)) //p:arm/arm2 477 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 479 opcode=0x5400+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 479 opcode=0xf8000000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 477 if((op1.no<8)&&(op2.no<8)&&(op3.no>=0)&&(op3.no<0x80)&&(!(op3.no&3))) { opcode=0x7000+(op3.no<<4)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 477 op3.no=-op3.no; opcode=0xf8000c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 477 opcode=0xf8800000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 477 opcode=0x7000+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } } } } return ptr-li->text; } else if(!matchident(&i,STRH)) //p:arm/arm2 489 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} offset=0; if(!expect(&ptr,'[')) { if((!ident(&op2,&ptr))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) { if((!ident(&op3,&ptr))&&(!matchr00_15(&op3))&&(!expect(&ptr,']'))) { if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 479 opcode=0x5200+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 479 opcode=0xf8200000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((!imm(&op3,&ptr))&&(!expect(&ptr,']'))) { //p:arm/arm2 489 if((op1.no<8)&&(op2.no<8)&&(op3.no>=0)&&(op3.no<0x80)&&(!(op3.no&3))) { opcode=0x8000+(op3.no<<4)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op3.no>=-256)&&(op3.no<0)) { //p:arm/arm2 489 op3.no=-op3.no; opcode=0xf8200c00+(op2.no<<16)+(op1.no<<12)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((op3.no>-4096)&&(op3.no<4095)) { //p:arm/arm2 489 opcode=0xf8200000+(op2.no<<16)+(op1.no<<12)+(op3.no); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if(!expect(&ptr,']')) { if((!matchr00_07(&op1))&&(!matchr00_07(&op2))) { //p:arm/arm2 477 opcode=0x8000+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; } } } } return ptr-li->text; } // else if(!matchident(&i,SUB)) //P:arm/arm2 495 // { // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected // if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //comma expected // if(*ptr!=','){return ptr-li->text;} //comma expected // ptr++; //skip comma // if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(*ptr!=','){return ptr-li->text;} //comma expected // ptr++; //skip comma // ptrsave=ptr; // if(!imm(&op3,&ptr)) // { // if((!matchr00_07(&op1))&&(!matchr00_07(&op2))&&(op3.no<8)) // { //P:arm/arm2 495 // opcode=0x1e00+(op3.no<<6)+(op2.no<<3)+op1.no;emit2(a,opcode);goto DONE; // } // else {return ptr-li->text;} // } // else {return ptr-li->text;} // } //invalid operands //SUB (immediate) SUBS rd,rn,#imm3 //p:arm/arm2 495 //* // SUB{c} rd,rn,#imm3 //p:arm/arm2 495 //* // SUB{c} rd,#imm8 //p:arm/arm2 495 //* // SUBS{c} rd,#imm8 //p:arm/arm2 495 //* // SUBS{c} Rd,Rn,#tximm //p:arm/arm2 495 //* // SUB{c} Rd,Rn,#tximm //p:arm/arm2 495 //* // SUBS{c} Rd,Rn,#imm12 //p:arm/arm2 495 //* // SUB{c} Rd,Rn,#imm12 //p:arm/arm2 495 //* // (register) SUB{c} rd,rn,rm //p:arm/arm2 497 //* // SUBS{c} rt,rn,rm //p:arm/arm2 497 //* // SUB{c} rn,Rm //p:arm/arm2 497 //* // SUBS{c} rn,Rm //p:arm/arm2 497 //* // SUB{c} Rd,Rm //p:arm/arm2 497 //* // SUB{c} Rd,Rm //p:arm/arm2 497 //* // SUB{c} Rd,Rn,Rm //p:arm/arm2 497 //* // SUBS{c} Rt,Rn,Rm //p:arm/arm2 497 //* // SUB{c} Rt,Rn,Rm{,lsl #imm2} //p:arm/arm2 497 //* // SUBS{c} Rt,Rn,Rm{,lsl #imm2} //p:arm/arm2 497 //* // (SP-imm) SUB{c} SP,SP,#imm7 //p:arm/arm2 499 //* // SUB{c} SP,#imm7 //p:arm/arm2 499 //* else if((!matchident(&i,SUB))||(S=(!matchident(&i,SUBS)))) { //p:arm/arm2 495 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))) { if((op1.no==13)&&(op2.no<0x200)&&(!(op2.no&0x03))) { //p:arm/arm2 499 opcode=0xb080+(op2.no>>2); emit2(a,opcode);goto DONE; } //if immediate follows first comma, src reg= dst reg: op3=op2;op2=op1; goto SUBIMM; } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!expect(&ptr,COMMA))&&(!matchr00_15(&op1))&&(!matchr00_15(&op2))) { ptrsave=ptr; if(!imm(&op3,&ptr)) { SUBIMM: if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 495 opcode=0x1e00+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else if((op1.no<8)&&(op1.no==op2.no)&&(op3.no<0x100)) { //p:arm/arm2 495 opcode=0x3800+(op1.no<<8)+op3.no; emit2(a,opcode);goto DONE; } else if(thumbexpandable(op3.no,&th)) { //p:arm/arm2 495 opcode=0xf1a00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if(op3.no<0x1000) { opcode=0xf2a00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+((op3.no&0x800)<<15)+((op3.no&0x700)<<4)+(op3.no&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } else if((ptr=ptrsave)&&(!ident(&op3,&ptr))&&(!matchr00_15(&op3))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { //p:arm/arm2 223 shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 497 opcode=0xeba00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((op1.no<8)&&(op2.no<8)&&(op3.no<8)) { //p:arm/arm2 497 opcode=0x1a00+(op3.no<<6)+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 497 opcode=0xeba00000+(S<<20)+(op2.no<<16)+(op1.no<<8)+op3.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) {//two-register format, no offset if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 497 opcode=0x1a00+(op2.no<<6)+(op1.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 497 opcode=0xeba00000+(S<<20)+(op1.no<<16)+(op1.no<<8)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } //TEQ (immediate) TEQ{c} Rn,#tximm //p:arm/arm2 519 //* else if(!matchident(&i,TEQ)) { //p:arm/arm2 519 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //p:arm/arm2 519 //if immediate follows first comma, src reg= dst reg: opcode=0xf0900f00+(op1.no<<16)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } //TST (immediate) TST{c} Rn,#tximm //p:arm/arm2 521 //* else if(!matchident(&i,TST)) { //p:arm/arm2 521 if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if((!imm(&op2,&ptr))&&(!matchr00_15(&op1))&&(thumbexpandable(op2.no,&th))) { //p:arm/arm2 521 //if immediate follows first comma, src reg= dst reg: opcode=0xf0100f00+(op1.no<<16)+th;//((th&0x800)<<15)+((th&0x700)<<4)+(th&0xff); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } ptr=ptrsave; //p:arm/arm2 523 if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!matchr00_15(&op1))&&(!matchr00_15(&op2))) { if(!expect(&ptr,COMMA)) {//encode shifted register //p:arm/arm2 180 if(!(ident(&op4,&ptr))&&(!imm(&op5,&ptr))&&(op5.no<32)) { shift=-1; if(!matchident(&op4,LSL)) {shift=0;} else if(!matchident(&op4,LSR)){shift=1;} else if(!matchident(&op4,ASR)){shift=2;} else if(!matchident(&op4,ROR)){shift=3;} if(shift!=-1) { //p:arm/arm2 523 opcode=0xea100f00+(S<<20)+(op1.no<<16)+op2.no+(shift<<4)+((op5.no&0x1c)<<10)+((op5.no&3)<<6); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } } else if((op1.no<8)&&(op2.no<8)) { //p:arm/arm2 523 opcode=0x4200+(op2.no<<3)+op1.no; emit2(a,opcode);goto DONE; } else { //p:arm/arm2 523 opcode=0xea100f00+(op1.no<<16)+op2.no; emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } return ptr-li->text; } else if(!matchident(&i,VADD)) //p:arm/arm2 566 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)) { if((!matchs00_31(&op1))&&(!matchs00_31(&op2))) { opcode=0xee300a00+((op1.no&0x1e)<<11)+((op1.no&0x01)<<22)+ ((op1.no&0x1e)<<15)+((op1.no&0x01)<<7)+ ((op2.no&0x1e)>> 1)+((op2.no&0x01)<<5); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } if(ident(&op3,&ptr)){return ptr-li->text;} //operand expected if((!matchs00_31(&op1))&&(!matchs00_31(&op2))&&(!matchs00_31(&op3))) { //p:arm/arm2 556 opcode=0xee300a00+((op1.no&0x1e)<<11)+((op1.no&0x01)<<22)+ ((op2.no&0x1e)<<15)+((op2.no&0x01)<<7)+ ((op3.no&0x1e)>> 1)+((op3.no&0x01)<<5); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } else if(!matchident(&i,VMOV)) //p:arm/arm2 585 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} ptrsave=ptr; if(!imm(&op2,&ptr)) { //p:arm/arm2 585 if(!matchs00_31(&op1)) { opcode=0xeeb00a00+((op1.no&0x01)<<22)+((op1.no&0x1e)<<11)+((op2.no&0xf0)<<12)+(op2.no&0x0f); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } } ptr=ptrsave; if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((!matchs00_31(&op1))&&(!matchs00_31(&op2))) { //p:arm/arm2 586 // opcode=0xeeb00a40+((op1.no&0x10)<<18)+((op1.no&0x0f)<<12)+((op2.no&0x10)<<1)+(op2.no&0x0f); opcode=0xeeb00a40+((op1.no&0x1e)<<15)+((op1.no&0x01)<<22)+((op2.no&0x1e)>>1)+((op2.no&0x01)<<5); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((!matchs00_31(&op1))&&(!matchr00_15(&op2))) { //p:arm/arm2 589 opcode=0xee000a10+((op1.no&0x01)<<7)+((op1.no&0x1e)<<15)+((op2.no&0x0f)<<12); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } else if((!matchs00_31(&op2))&&(!matchr00_15(&op1))) { //p:arm/arm2 589 opcode=0xee100a10+((op2.no&0x01)<<7)+((op2.no&0x1e)<<15)+((op1.no&0x0f)<<12); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } else if(!matchident(&i,VMRS)) //p:arm/arm2 592 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((op2.len==5)&&(!memicmp(op2.p,"fpcsr",5))&&(!matchr00_15(&op1))) { //p:arm/arm2 593 opcode=0xeef10a10+(op2.no<<12); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } else if(!matchident(&i,VMSR)) //p:arm/arm2 593 { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(expect(&ptr,COMMA)){return ptr-li->text;} if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((op1.len==5)&&(!memicmp(op1.p,"fpcsr",5))&&(!matchr00_15(&op2))) { //p:arm/arm2 593 opcode=0xeee10a10+(op2.no<<12); emit2(a,opcode>>16);emit2(a,opcode&0xffff);goto DONE; } return ptr-li->text; } else if(!matchident(&i,DEFINE)) { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //operand expected if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //immediate expected if(imm(&op2,&ptr)){brk return ptr-li->text;} //immediate operand expected if(mac=getmacro(&op1)) { if(mac->imm.no==op2.no){} //duplicate macro definition, ignore else {brk return ptr-li->text;} } else { addmacro(&op1,&op2,0); } } else if(!matchident(&i,BYTE)) { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //immediate expected // if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected // *a->pc=op1.no;a->edo+=2;goto DONE; // *(UC*)a->pc=strtol(ptr,&ptr,0);a->edo++;goto DONE; emit1(a,strtol(ptr,&ptr,0));goto DONE; } else if(!matchident(&i,WORD)) { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //immediate expected // if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected // *a->pc=op1.no;a->edo+=2;goto DONE; // *a->pc=strtol(ptr,&ptr,0);a->edo+=2;goto DONE; emit2(a,strtol(ptr,&ptr,0));goto DONE; } else if(!matchident(&i,DWORD)) { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //immediate expected // if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected // *a->pc=op1.no;a->edo+=2;goto DONE; // *(UL*)a->pc=strtol(ptr,&ptr,0);a->edo+=4;goto DONE; emit4(a,strtol(ptr,&ptr,0));goto DONE; } else if(!matchident(&i,DATAWORD)) { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //immediate expected // if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected // *a->pc=op1.no;a->edo+=2;goto DONE; // *a->pc=strtol(ptr,&ptr,16);a->edo+=2;goto DONE; emit4(a,strtol(ptr,&ptr,16));goto DONE; } // else if(!matchidentC(&i,cULDATA)) // { // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} //identifier // if(ident(&op1,&ptr)){return ptr-li->text;} //expected // val=0; // while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} // if(!imm(&op2,&ptr)) // { // if(!recurse) // { // if(cortexm0&&(a->edo&2)){emit2(a,0);} //pool data on M0 needs to be word aligned // val=op2.no=strtol(op2.p,0,0); //immediate option // if(addlabel(a,&op1,0x84,stCODE,utbasic(4,0,0,0),val,0)){return ptr-li->text;} // emit4(a,val);cortexm0ok=1;goto DONE; //// *pcd=val;goto DONE; // } // } // else if(!ident(&op2,&ptr)) //identifier option // { // if((lab=getlabel(&op2))&&(lab->no!=-1)) // { // UL* cptr=(UL*)a->pc; // if(!lab->type){lab->no|=1;} //Thumb addresses need bit 0 set //// *cptr=lab->no+flashbase;a->edo+=4;goto DONE; //// emit4(a,lab->no+flashbase);goto DONE; // if(cortexm0&&(a->edo&2)){emit2(a,0);} //pool data on M0 needs to be word aligned // emit4(a,lab->no);cortexm0ok=1;goto DONE; // } // else if(!recurse) // { // if(cortexm0&&(a->edo&2)){emit2(a,0);} //pool data on M0 needs to be word aligned // addbranch(a,a->line,op2,lineoffset,4);emit4(a,0);cortexm0ok=1;goto DONE; // } // else{return ptr-li->text;} // } // else{return ptr-li->text;} // } // else if(!matchidentC(&i,cCHDATA)) // {//constant character data, placed directly in code stream // if(*ptr=='*') // { // ptr++; // if(ident(&op1,&ptr)){return ptr-li->text;} //name expected // if(*ptr==0x22) // { // if(addlabel(a,&op1,0,stCODE,utpointer(utbasic(1,utSIGN,0,0),0,0,0),val,0)){return ptr-li->text;} // ptr++; // while(*ptr!=0x22) // { // if(*ptr=='\\') // { // ptr++; // switch(*ptr) // { // case 'x': // ptr++; // val=strtoul(ptr,&ptr,16); // emit1(a,val); // break; // } // } // else // { // emit1(a,*ptr);ptr++; // } // } // emit1(a,0);//add terminating NULL char // if(a->edo&1){emit1(a,0);} //halfword align on inline data // goto DONE; // } // else {return ptr-li->text;} // } // else // { // if(ident(&op1,&ptr)){return ptr-li->text;} //name expected // val=0; // if(imm(&op2,&ptr)){val=op2.no=strtol(op2.p,0,0);}//immediate optional // if(addlabel(a,&op1,0,stCODE,utbasic(1,utSIGN,0,0),0,0)){return ptr-li->text;} // emit1(a,val); // if(a->edo&1){emit1(a,0);} //halfword align on inline data // goto DONE; // } // return ptr-li->text; // } else if(!matchident(&i,PORT)) { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(imm(&op2,&ptr)){return ptr-li->text;} //immediate operand expected if(mac=getmacro(&op1)){return ptr-li->text;} //duplicate no allowed addmacro(&op1,&op2,1); // brk if(blnk(&ptr)){goto DONE;} if(*ptr=='(') { ptr++; if(blnk(&ptr)){return ptr-li->text;} ctr=31;msk=0x80000000; while(*ptr!=')') { if(*ptr==',') { } else if(*ptr=='-') { ptr++; } else if(!ident(&op2,&ptr)) { addmacro(&op2,&op1,2); mac=getmacro(&op2); mac->imm.no=(1<< ctr); mac->imm.val=ctr; } if(blnk(&ptr)){return ptr-li->text;} if(!ctr) { if(*ptr!=')'){return ptr-li->text;} } else { if(ptr==')') {goto DONE;} else if(*ptr!=','){return ptr-li->text;} ptr++; if(blnk(&ptr)){return ptr-li->text;} ctr--;msk>>=1; } } goto DONE; } else {goto DONE;} } else if(!matchident(&i,PIN)) { if(ident(&op1,&ptr)){return ptr-li->text;} //operand expected if(ident(&op2,&ptr)){return ptr-li->text;} //operand expected if((mac=getmacro(op2))&&(mac->str.dtype==2)) { pmac=mac; addmacro(&op1,&op2,2); mac=getmacro(&op1); mac->imm=pmac->imm; goto DONE; } if(blnk(&ptr)){return ptr-li->text;} if(imm(&op3,&ptr)){return ptr-li->text;} //immediate operand expected if(mac=getmacro(&op1)){return ptr-li->text;} addmacro(&op1,&op2,2); mac=getmacro(&op1); // IDENT* ia=&mac->str; // IDENT* ib=&mac->imm; mac->imm.val=strtoul(op3.p,0,10);//dtype for PIN is 2 mac->imm.no=(1<< mac->imm.val); goto DONE; } else if(!matchident(&i,SET)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple SET syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //code for multiple SET to go here return ptr-li->text; } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0); orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0); goto DONE; } } else if(!matchident(&i,CLR)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple SET syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //code for multiple SET to go here return ptr-li->text; } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0); bicregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0); goto DONE; } } else if(!matchident(&i,ENAP)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple ENAP syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //put code for multiple ENAP in here return ptr-li->text; } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0x00); //PIO_PER is root port orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0x00); //PIO_PER is root port goto DONE; } } else if(!matchident(&i,DISP)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple SETP syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //code for multiple SETP to got here // if(port<0x60) // { // port-=0x20; // //encode IN portreg,port //p:atmel/avr 80 // opcode=0xb000|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // if(setmsk) // { // msk=setmsk; // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // } // if(clrmsk) // { // msk=clrmsk;msk=~msk; // //encode ANDI portreg,~msk //p:atmel/avr 20 // opcode=0x7000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // } // //encode OUT port,portreg //p:atmel/avr 111 // opcode=0xb800|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // goto DONE; // } } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0x04); //PIO_PDR is PIO_ER+0x04 orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0x04); //PIO_PDR is PIO_ER+0x04 goto DONE; // if(port<0x40) // { // port-=0x20; // bit=op1.no>>8; // //encode sbi DDR,bit // opcode=0x9a00|(port<<3)|bit;emit(a,opcode); // goto DONE; // } // else if(port<0x60) // { // port-=0x20; // msk=op1.no&0xff; // //encode IN portreg,port //p:atmel/avr 80 // opcode=0xb000|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // //encode OUT port,portreg //p:atmel/avr 111 // opcode=0xb800|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // goto DONE; // } // else // { // msk=op1.no&0xff; // //encode LDS portreg,port //p:atmel/avr 95 // opcode=0x9000|(portreg<<4);emit(a,opcode);emit(a,port); // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // //encode STS port,portreg //p:atmel/avr 95 // opcode=0x9200|(portreg<<4);emit(a,opcode);emit(a,port); // goto DONE; // } } } else if(!matchident(&i,ENAO)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple ENAP syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //put code for multiple ENAO in here return ptr-li->text; } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0x10); //PIO_OER is PIO_ER+0x10 orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0x10); //PIO_OER is PIO_ER+0x10 goto DONE; } } else if(!matchident(&i,DISO)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple ENAP syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //put code for multiple DISO in here return ptr-li->text; } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0x14); //PIO_ODR is PIO_ER+0x14 orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0x14); //PIO_ODR is PIO_ER+0x14 goto DONE; } } else if(!matchident(&i,SETO)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple SETP syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //code for multiple SETO to got here // if(port<0x60) // { // port-=0x20; // //encode IN portreg,port //p:atmel/avr 80 // opcode=0xb000|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // if(setmsk) // { // msk=setmsk; // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // } // if(clrmsk) // { // msk=clrmsk;msk=~msk; // //encode ANDI portreg,~msk //p:atmel/avr 20 // opcode=0x7000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // } // //encode OUT port,portreg //p:atmel/avr 111 // opcode=0xb800|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // goto DONE; // } } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0x30); //PIO_SODR is PIO_ER+0x30 orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0x30); //PIO_SODR is PIO_ER+0x30 goto DONE; // if(port<0x40) // { // port-=0x20; // bit=op1.no>>8; // //encode sbi DDR,bit // opcode=0x9a00|(port<<3)|bit;emit(a,opcode); // goto DONE; // } // else if(port<0x60) // { // port-=0x20; // msk=op1.no&0xff; // //encode IN portreg,port //p:atmel/avr 80 // opcode=0xb000|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // //encode OUT port,portreg //p:atmel/avr 111 // opcode=0xb800|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // goto DONE; // } // else // { // msk=op1.no&0xff; // //encode LDS portreg,port //p:atmel/avr 95 // opcode=0x9000|(portreg<<4);emit(a,opcode);emit(a,port); // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // //encode STS port,portreg //p:atmel/avr 95 // opcode=0x9200|(portreg<<4);emit(a,opcode);emit(a,port); // goto DONE; // } } } else if(!matchident(&i,CLRO)) { if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} //immediate operand expected if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); port=mac->imm.no; blnk(&ptr); if(*ptr==',') {//multiple SETP syntax setmsk=clrmsk=0; if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} pmac=mac; while(*ptr==',') //gather bits in setmsk and clrmsk { ptr++; if(blnk(&ptr)){return ptr-li->text;} //operand expected comp=0;if(*ptr=='~'){comp=1;ptr++;} if(imm(&op1,&ptr)){return ptr-li->text;} if(op1.dtype!=2){return ptr-li->text;} //PIN dtype 2 wanted mac=getmacro(&op1); if(mac->imm.p!=pmac->imm.p){return ptr-li->text;} if(comp){clrmsk|=op1.no&0xff;} else {setmsk|=op1.no&0xff;} blnk(&ptr); } //code for multiple CLRO to got here // if(port<0x60) // { // port-=0x20; // //encode IN portreg,port //p:atmel/avr 80 // opcode=0xb000|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // if(setmsk) // { // msk=setmsk; // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // } // if(clrmsk) // { // msk=clrmsk;msk=~msk; // //encode ANDI portreg,~msk //p:atmel/avr 20 // opcode=0x7000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // } // //encode OUT port,portreg //p:atmel/avr 111 // opcode=0xb800|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // goto DONE; // } } else { // if(comp){goto CLRPIN;} // brk movregimm32(a,1,port); ldrregmregoff(a,2,1,0x34); //PIO_CODR is PIO_ER+0x34 orrregthumbimm(a,2,2,op1.no); strregmregoff(a,2,1,0x34); //PIO_CODR is PIO_ER+0x34 goto DONE; // if(port<0x40) // { // port-=0x20; // bit=op1.no>>8; // //encode sbi DDR,bit // opcode=0x9a00|(port<<3)|bit;emit(a,opcode); // goto DONE; // } // else if(port<0x60) // { // port-=0x20; // msk=op1.no&0xff; // //encode IN portreg,port //p:atmel/avr 80 // opcode=0xb000|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // //encode OUT port,portreg //p:atmel/avr 111 // opcode=0xb800|(portreg<<4)|((port&0x30)<<5)|port&0x0f;emit(a,opcode); // goto DONE; // } // else // { // msk=op1.no&0xff; // //encode LDS portreg,port //p:atmel/avr 95 // opcode=0x9000|(portreg<<4);emit(a,opcode);emit(a,port); // //encode ORI portreg,msk //p:atmel/avr 110 // opcode=0x6000|((msk&0xf0)<<4)|msk&0x0f;emit(a,opcode); // //encode STS port,portreg //p:atmel/avr 95 // opcode=0x9200|(portreg<<4);emit(a,opcode);emit(a,port); // goto DONE; // } } } else { while(isspace(*ptr)){ptr++;}if(!*ptr){return ptr-li->text;} if(*ptr==':') {//is it a label? ptr++; //skip colon if(!recurse) { if(!cg){allocateivt(a);} UL lsyoff; if(!revsynamematch(i.p,i.len,&lsyoff)) {//avoid duplicate for C codelabel passed in by flushpcos() SY* sl=(SY*)(sy+lsyoff); sl->rtaddr=a->edo+flashbase; } else { if(addsym(i.p,i.len,stCODE,utpointer(0,0),&lsyoff,a->edo+flashbase)) {return ptr-li->text;} } } while(isspace(*ptr)){ptr++;} if(!*ptr) {goto DONE;} if(*ptr==';'){goto DONE;} if(*(UI*)ptr=='//'){return 0;} //skip comment after label goto L01; } else {return ptr-li->text;} } DONE: //28.5.2015 multiassembler implementation //here we spot the semicolon and loop back to process another statement //so long as recurse is zero. //When recurse is 1, the assembler statement to be recompiled starts at //li->text+BRANCH->lnoffset, and ends here so we are done //note that spurious text between a valid assembler statement and the semicolon //will simply return 0, e.g. AVR disassembly output such as bclr 7 (i) ; UC* mptr=calloc(1000,1); if(!mptr){brk;} free(mptr); if((!expect(&ptr,SEMIC))&&(!recurse)) { if(blnk(&ptr)){return 0;} //semicolon at end of line OK, do nothing if(*(UI*)ptr=='//'){return 0;} //ditto for a comment lineoffset=ptr-li->text; a->pc=(UI*)(a->buf+a->hdrlen+a->edo); goto L01; } return 0; brk //nothing should reach here! return 0; } SL asmblock(SF* a,CH** ptr) { //expecting opening brace to start, first assembly statement on a new line if(cexpect(a,ptr,'{')){brk return 1;} a->line++; LINE* li=a->L->line+a->line; UL sedo,lineoffset; while(li) { a->pc=(UI*)(a->buf+a->edo+a->hdrlen); sedo=a->edo;cortexm0ok=0; if(assemble(a,li,0,0)) { li=a->L->line+a->line; clidisplay("|c1200Error at line %4lc1400 {%sc1400} %s",&a->line,a->fname,li->text); return 1; } if(cortexm0&&cortexm0warn&&(a->edo-sedo>2)&&(!cortexm0ok)) { clidisplay("|c1200Cortex-M0 edo advanced more than 2 at line %4lc1400 {%sc1400} %s",&a->line,a->fname,li->text); } a->line++; if(a->line>=a->L->lines){brk return 1;}//break;} li=a->L->line+a->line; *ptr=li->text; if(**ptr) {//if non-blank line if(!cexpect(a,ptr,'}')){break;} } li=a->L->line+a->line; //where cexpect clears comment lines *ptr=li->text; //closing brace at start of new line to finish } return 0; } // UL global; //SL armc(SF* a) //{ // LINE* li=a->L->line; // CH* ptr=li->text; // CH* ptrsave; // UL lsave=a->line; // global=1; // // OPR i; // ////switching between declaration statements and asm{} blocks is a little messy ////SF* really needs a LINE* for the current line instead of using a local LINE* // while(1) // { // ptrsave=ptr; // lsave=a->line; // if(!ident(a,&i,&ptr)) // { // switch(i.key) // { // case kASM: // if(asmblock(a,&ptr)){brk return 1;} // break; // default:ptr=ptrsave;a->line=lsave;break; // } // } // if(cblnk(a,&ptr)){break;} // if(!cexpect(a,&ptr,'{')){return 1;}//break;} //unexpected // memset(&i,0,sizeof(OPR)); // if(declaration(a,&i,&ptr)) // { // showerror(i.cerror,i.p,i.len,i.val);return 1; //// if(!cexpect(a,&ptr,';')){} // } // if(a->line>=a->L->lines){break;} // } // // return 0; //} UL global; SL armc(SF* a) { LINE* li=a->L->line; CH* ptr=li->text; CH* ptrsave; UL lsave=a->line; global=1; OPR i; //switching between declaration statements and asm{} blocks is a little messy //SF* really needs a LINE* for the current line instead of using a local LINE* while(1) { ptrsave=ptr; lsave=a->line; if(cblnk(a,&ptr)){break;} //make sure no white space to confuse rewind if(!ident(a,&i,&ptr)) { switch(i.key) { case kASM: if(asmblock(a,&ptr)){brk return 1;} break; default:ptr-=i.len; //rewind if not asm keyword break; } } if(cblnk(a,&ptr)){break;} if(!cexpect(a,&ptr,'{')){return 1;}//break;} //unexpected memset(&i,0,sizeof(OPR)); if(declaration(a,&i,&ptr)) { showerror(i.cerror,i.p,i.len,i.val);return 1; // if(!cexpect(a,&ptr,';')){} } if(a->line>=a->L->lines){break;} } return 0; } UL patchrls(SF* a,UL type); UL getversion(VD) { UL fsiz,projectver; UL majorver=1; UL compilerrev=1; UC* buf=uploadfile("version",&fsiz); if(!buf){projectver=0;} else {projectver=strtol((CH*)buf,0,10);} projectver++; CH tmp[16];tmp[0]=0; catprint(tmp,"%5l\r\n",&projectver); downloadfile("version",7,tmp); return (majorver<<24)+(compilerrev<<16)+projectver; } SL main(UL argc,CH* argv[]) { if(argc<2){clidisplay("Usage:ARMC armfile");return 1;} CH fname[128]; CH rawfname[128]; CH binfname[128]; strcpy(fname,argv[1]); CH* rptr=strchr(fname,'.'); if(!rptr){strcat(fname,".html");} strcpy(rawfname,fname); strcpy(binfname,fname); rptr=strchr(rawfname,'.'); strcpy(rptr,".raw"); rptr=strchr(binfname,'.'); strcpy(rptr,".bin"); LSEQ* L=loadSEQ(fname); if(!L){clidisplay("File %sc1400 not found",fname);return 1;} SF a;a.edo=0;a.line=0; strcpy(a.fname,fname); // a.buf=calloc(L->lines,4); a.buf=calloc(0x40000,8); if(!a.buf){clidisplay("|c1200Insufficient memory");return 1;} a.pc=(UI*)a.buf; a.L=L; UL flashonsuccess=0,showsymbols=0,showtypes=0; UL argctr=2; while(argctr< argc) { if(!stricmp(argv[argctr],"/f")){flashonsuccess=1;} else if(!stricmp(argv[argctr],"/s")){showsymbols=1;} else if(!stricmp(argv[argctr],"/t")){showtypes=1;} argctr++; } FTRAW* ftr=(FTRAW*)a.buf; ftr->magic='PPTC'; ftr->ftype=ftRAW; ftr->flags=0; ftr->hdrlen=sizeof(FTRAW); strcpy(ftr->sig,"armflsh"); ftr->loadaddress=0x80000; a.hdrlen=ftr->hdrlen; LINE* li; if(armc(&a)) { li=a.L->line+a.line; clidisplay("|c1200Error -|c700 line %4lc1400 {%sc1400} %s",&a.line,a.fname,li->text); return 1; } IDENT* srb; IDENT* sre; UL sram,dsize,syoff; if(!platform) { clidisplay("|c1200Error: No platform directive!");return 1; } else {//finish the .raw image: //complicated by code to patch up .cortexm0 image //where literal pool is used to encode 32-bit integer values //in initialisers and sram data addresses //also generates literals for cortexm0 startup code //in armstartup0.armi, to correctly copy initialisers to sram //along with symbols and macros needed for the default startup code //in armstartup.armi emitliterals(&a); // emptyliteralpool(a); //also aligns edo to 32-bits syundisableall(); generateivt(&a); if(a.edo&2){emit2(&a,0xbe00);} //word align // if(!(a.edo&2)){emit2(&a,0xffff);} // if(a.edo&2){brk;} SY* as; if(!revsymatch(codeend.p,codeend.len,&as)) { as->data=a.edo+flashbase;as->stor=0; } if(!revsymatch(sramend.p,sramend.len,&as)) { if(sramdataaddress&1){sramdataaddress++;} if(sramdataaddress&2){sramdataaddress+=2;} as->data=sramdataaddress;as->stor=0; } // if(addsym(codeend.p,codeend.len,stCODE,utpointer(0,0),&syoff,a.edo+flashbase)){return 1;} // if(cortexm0) // { // codeend.no=a.edo+flashbase;//+4;//add 4 here because // addliteral(a,&codeend); //addliteral adds 4! // } patchrls(&a,0); //patch dataseg before output to file image sram=sramb; UL n,siz; UC* aptr; UC* sptr=sy; SY* s; UC* rptr; for(n=0;n< syms;n++) { s=(SY*)sptr; if(s->stor&stDATA) {//brk siz=utsizeof(s->ut); //s->rtaddr=sram; if(cortexm0) { addliteral(a,s); } sram+=siz; if(inlinedat) { rptr=a.buf+a.hdrlen+s->rtaddr-flashbase; memcpy(rptr,dataseg+s->data,siz); } else { aptr=(UC*)a.pc; memcpy(aptr,dataseg+s->data,siz); if(sramaddressing) { s->rtaddr=sramb+s->data; } else { s->rtaddr=a.edo+flashbase; } a.pc=(UI*)(aptr+siz); a.edo+=siz; } } sptr+=s->namelen+sizeof(SY); } if(sram&2){sram+=2;} // if(addsym(sramend.p,sramend.len,stDATA,utbasic(0,0),&syoff,sram)){return 1;} // // if(cortexm0) // { //// addlabel(&a,&sramend,0,stCODE,0,0,0); // sramend.no=sramend.val=sram; // addliteral(a,&sramend); // //poke the correct value into the image //// *(UL*)(a.pc-2)=sram; // *(UL*)a.pc=sram; // } // else if(!nostartup) // { // } emptypool(&a,0); patchrls(&a,1); //patch pool relocs patchrls(&a,2); //patch pool relocs resolvebranches(&a); } UL err=countunresolved(a); ftr->rawsize=a.edo; ftr->appendix=sizeof(APP); ftr->ivtlen=ivtlen; ftr->loadaddress=flashbase; UC* obuf=calloc(1,ftr->hdrlen+ftr->rawsize+ftr->appendix+utlen+sylen+rlused+frls*4); if(obuf) { doinitialjump(a); memcpy(obuf,a.buf,ftr->hdrlen+ftr->rawsize); ftr=(FTRAW*)obuf;ftr->flags|=FTAPPENDIX; ftr->frl=ftr->hdrlen+ftr->rawsize; ftr->frls=frls; if(ftr->frls){memcpy(obuf+ftr->frl,frl,frls*4);} if(!err){ftr->ver=getversion();} APP* app=(APP*)(obuf+ftr->frl+frls*4); memcpy(app->title,"appendix",8); app->ute=ftr->frl+frls*4+sizeof(APP); app->utlen=utlen; app->utes=utes; if(utlen){memcpy(obuf+app->ute,ut,utlen);} app->sym=app->ute+app->utlen; app->sylen=sylen; app->syms=syms; if(sylen){memcpy(obuf+app->sym,sy,sylen);} app->rlc=app->sym+app->sylen; app->rllen=rlused; app->rlcs=rlcs; if(rlused){memcpy(obuf+app->rlc,rl,rlused);} // downloadfile(rawfname,ftr->hdrlen+ftr->rawsize+ftr->appendix+utlen+sylen,obuf); ftr->fsiz=app->rlc+app->rllen; downloadfile(rawfname,app->rlc+app->rllen,obuf); if(binfile) { // downloadfile(binfname,ftr->rawsize,obuf+ftr->hdrlen); // UL* frptr=frl; // for(n=0;n< frls;n++) // { // UL* tgt=(UL*)(obuf+*frptr); // *tgt+=0x8000; // frptr++; // } ftr->flags&=~FTAPPENDIX; ftr->fsiz=ftr->hdrlen+ftr->rawsize+ftr->frls*4; downloadfile(binfname,ftr->hdrlen+ftr->rawsize+ftr->frls*4,obuf); } free(obuf); n=iaalloc(6); catprint(ia+n,"}\r\n}\r\n"); downloadfile("i86.c",ialen,ia); } else { //brk downloadfile(rawfname,ftr->hdrlen+ftr->rawsize+ftr->appendix,a.buf); } // showpcodes(); if(showtypes){showuts();} if(showsymbols){showsyms();} if(err){clidisplay("|c1200Unresolved branches");} else { // clidisplay("|c1000Seems OK"); // err=MAXLABELS;clidisplay("Symbols %6l",&syms); // err=MAXMACROS;clidisplay("Macros %6l/%6l",¯os,&err); // err=MAXBRANCHES;clidisplay("Branches %6l/%6l",&branches,&err); UL datasiz=0; if(sramaddressing) { datasiz=sram-sramb;//srb->no;//m->imm.no; if(datasiz>=sramsize){clidisplay("|c1200Too much data (%6lc1400)in SRAM (%6lc1400), program will not run!",&datasiz,&sramsize);return 1;} } UL codesiz=a.edo-datasiz; clidisplay("|c1000Seems OK:Code %6lc1400, sram data %6lc1400 (%6lc1300), total %6lc1400 (%6lc1300), seems OK",&codesiz,&datasiz,&sramsize,&a.edo,&flashsize); if(flashonsuccess) { return q_invoke("flashwrite ard %s",argv[1]); } } return 0; }