//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;

}