

int shd            '#show flag
string cmt=chr(39) 'comment mark

function charwidth(int a) as string
===================================
  if cpuw=4
    return "mov dl,"+str(a)+cr  ' +"mov byte [ebx+120],"+str(a)+cr
  else 'cpuw=8
    return "mov r10,"+str(a)+cr ' +"mov byte [rbx+120],"+str(a)+cr
  endif
end function


procedure regnames()
====================

if cpuw=4
    '
  qeax="eax" : peax="[eax]" : pusheax="push eax"+cr : popeax="pop eax"+cr
  qecx="ecx" : pecx="[ecx]"
  qedx="edx"
  qebx="ebx"
  qesp="esp" : pesp="[esp]"
  qebp="ebp"
  qesi="esi" : pesi="[esi]"
  qedi="edi" : pedi="[edi]" : aedi="[edi"
  ledi="lea edi,"
  medi="mov edi,"
  spw1="esp,4"
  spw2="esp,8"
  'CPU
  regn(3)=qesi : regn(4)=qedi
  'FLOATS MUST BE PASSED BYREF
  '
  'REGISTER PARAM MACROS FOR CPU CALLING
  '-------------------------------------
  '
  rgp(0)="mov eax,"
  rgp(1)="mov ecx,"
  rgp(2)="mov edx,"
  rgp(3)="mov esi,"
  rgp(4)="mov edi,"
  rgp(8)="movss xmm0,"
  rgp(9)="movss xmm1,"
  rgp(10)="movss xmm2,"
  rgp(11)="movss xmm3,"
  '
  savestackptr="push ebp"+cr+"mov ebp,esp"+cr
  restorestackptr="mov esp,ebp"+cr+"pop ebp"+cr
  storeregs="push ebx"+cr+"push esi"+cr+"push edi"+cr+"push eax"+cr+"call _mem"+cr
  restoreregs="add esp,4"+cr+"pop edi"+cr+"pop esi"+cr+"pop ebx"+cr
  '
  cpuquad="
  sub esp,8
  fistp qword [esp]
  mov eax,[esp] : mov edx,[esp+4]
  add esp,8
  "
  fpuquad="
  sub esp,8
  mov [esp],eax
  mov [esp+4],edx : fild qword [esp]
  add esp,8
  "
  qwordin="
  fldz : fld st1 : fcomip : fstp st0 : jae fwd _nq
  fadd dword [ebx+712] : fadd dword [ebx+712]
  ._nq
  " 
  qwordout="
  fld dword [ebx+712] : fld st1 : fcomip : fstp st0 : jb fwd _nqh
  fsub dword [ebx+712] : fsub dword [ebx+712]
  ._nqh
  "
  '
else 'cpuw=8 'MS64
    '
  qeax="rax" : peax="[rax]" : pusheax="push rax"+cr : popeax="pop rax"+cr
  qecx="rcx" : pecx="[rcx]"
  qedx="rdx"
  qebx="rbx"
  qesp="rsp" : pesp="[rsp]"
  qebp="rbp"
  qesi="rsi" : pesi="[rsi]"
  qedi="rdi" : pedi="[rdi]" : aedi="[rdi"
  ledi="lea rdi,"
  medi="mov rdi,"
  spw1="rsp,8"
  spw2="rsp,16"
  'CPU
  regn(3)="r8" : regn(4)="r9"
  'FLOATS
  regn(8)="xmm0" : regn(9)="xmm1" : regn(10)="xmm2" : regn(11)="xmm3"
  '
  'REGISTER PARAM MACROS FOR MS64
  '------------------------------
  '
  rgp(0)="mov rax,"
  rgp(1)="mov rcx,"
  rgp(2)="mov rdx,"
  rgp(3)="mov r8,"
  rgp(4)="mov r9,"
  rgp(8)="movss xmm0,"
  rgp(9)="movss xmm1,"
  rgp(10)="movss xmm2,"
  rgp(11)="movss xmm3,"
  '
  savestackptr="push rbp"+cr+"mov rbp,rsp"+cr
  restorestackptr="mov rsp,rbp"+cr+"pop rbp"+cr
  storeregs="push rbx"+cr+"push rsi"+cr+"push rdi"+cr+"push rax"+cr+"lea rip rbx,bssdata"+cr
  restoreregs="add rsp,8"+cr+"pop rdi"+cr+"pop rsi"+cr+"pop rbx"+cr
  '
  cpuquad="
  sub rsp,8
  fistp qword [rsp]
  mov rax,[rsp]
  add rsp,8
  "
  fpuquad="
  sub rsp,8
  mov [rsp],rax
  fild qword [rsp]
  add rsp,8
  "
  qwordin="
  fldz : fld st1 : fcomip : fstp st0 : jae fwd _nq
  fadd dword [rbx+712] : fadd dword [rbx+712]
  ._nq
  " 
  qwordout="
  fld dword [rbx+712] : fld st1 : fcomip : fstp st0 : jb fwd _nq
  fsub dword [rbx+712] : fsub dword [rbx+712]
  ._nq
  "
  '  
endif
  '
regn(0)=qeax : regn(1)=qecx : regn(2)=qedx
'
'O2 LIBRARY / GLOBAL / STATIC REGISTER
'
regss=qebx : regsl=qebp : regs=regss : cpua=qeax
'
end procedure


function accreg(int ty) as string
=================================
ty and=15
select ty
  case 1 : function="al"
  case 2 : function="ax"
  case 4 : function="eax"
  case 8 : function="rax"
end select
end function


function leaedi(string*wr) as string
====================================
  if wr<>pedi
    return ledi+wr+cr
  endif
end function


function addrlabel(string*wr) as string
=======================================
  'ADDRESS OF LABEL
  '
  if cpuw=4
    function="call fwd _h_ : ._h_ : pop edi : sub edi,_h_ : add edi,"+wr+cr
  else 'cpuw=8
    function="lea rip rdi,"+wr+cr
  endif
  '
end function


function rtlo(int p) as string
==============================
  function="call "+memreg(qebx,p)+cr
end function


function requiresimd(int ty) as int
===================================
  if cpuw=8
    if (isfloat(ty)<>0)and(typp<>0x40)and(atf<>0)
      function=-1
    endif
  endif
end function


function loadsimd(string*wr, int ty) as string
==============================================
  string w1="movss xmm0,"+wr+cr
  if (ty and 15)=8
    mid(w1,5)="d" 'double
  endif
  function=wpfx+w1
end function


function fputosimd(int ty) as string
====================================
if (ty and 15)=8
  function="|sp -16"+cr+"fstp qword [rsp]"+cr+"movsd xmm0,[rsp]"+cr+"|sp 16"+cr
else
  function="|sp -16"+cr+"fstp dword [rsp]"+cr+"movss xmm0,[rsp]"+cr+"|sp 16"+cr
endif
end function


function simdtofpu(int ty) as string
====================================
if (ty and 15)=8
  function="|sp -16"+cr+"movsd [rsp],xmm0"+cr+"fld qword [rsp]"+cr+"|sp 16"+cr
else
  function="|sp -16"+cr+"movss [rsp],xmm0"+cr+"fld dword [rsp]"+cr+"|sp 16"+cr
endif
end function


function memregspill(int d, pn) as string
=========================================
  '
  'FOR 64 BIT MODE ONLY
  'SPILL REG PARAMS INTO STACK MEMORY
  '
  int i,a,e,f,g
  string w1,w2,w3
  e=pn
  if e>4
    e=4
  endif
  i=1
  f=1
  while i<=e
    if f>4
      exit while
    endif
    a=typl(i)
    '
    if isfloat(a)
      w3="movss "+memreg(qebp,d)+cm+regn(f+7)+cr
     if (a and 15)=8
       mid(w3,5)="d" 'double
     endif
     w1+=w3
    else
      w1+="mov "+memreg(qebp,d)+cm+regn(f)+cr
    endif
    '
    d+=8
    f++
    '
    'checking for higher types byval
    a=typq[i]
    if a
      g=a>>3 'cpuw/8
      if g*8<a
        g++
      endif
      for a=1 to g
        if f>4
          exit for
        endif
        w1+="mov "+memreg(qebp,d)+cm+regn(f)+cr
        d+=8 
        f++                
      next
    endif
    i++
  end do
  function=w1
end function


function addVTEntry(int w, string*wn) as string
===============================================
  if cpuw=4
    function="o2 e8 00 00 00 00 58 05 gl "+wn+" 83 c0 06 "+cr+_
    "mov [ecx+"+str(w)+"],eax"+cr 'table build (fwd ref )
  else 'cpuw=8
    function="lea rip rax,"+wn+cr+"mov [rcx+"+str(w)+"],rax"+cr
  endif
end function


function addTableSection(int k,a,ao) as string
==============================================
  string w1
  w1=mrcso(k,1)
  if cpuw=4
    function="'ADD TABLE SECTION:"+cr+_
    "lea edx,"+memreg(regss,ao)+cr+"lea edi,"+w1+cr+"mov ecx,"+str(drc(a).e)+cr+_
    "("+cr+"mov eax,[edi]"+cr+"mov [edx],eax"+cr+"add edi,4"+cr+"add edx,4"+cr+_
    "dec ecx"+cr+"ja repeat"+cr+")"+cr
  else
    function="'ADD TABLE SECTION:"+cr+_
    "lea rdx,"+memreg(regss,ao)+cr+"lea rdi,"+w1+cr+"mov ecx,"+str(drc(a).e)+cr+_
    "("+cr+"mov rax,[rdi]"+cr+"mov [rdx],rax"+cr+"add rdi,8"+cr+"add rdx,8"+cr+_
    "dec ecx"+cr+"ja repeat"+cr+")"+cr
  endif
end function


procedure decidecop(int *qp, tp)
================================
  if tp>=0x20
    select qp
    case 0x1c : qp=0x12
    case 0x1d : qp=0x13
    case 0x1e : qp=0x16
    case 0x1f : qp=0x17
   end select
  endif
end procedure


function linkadd(string*wsig,*rg) as string
===========================================
  '
  'PROVIDE ADDRESS FOR HOST VARIABLE
  '
  '
  if cpuw=4
    function="call fwd _h_ : ._h_ : pop "+rg+" : sub "+rg+",_h_ : add "+rg+","+wsig+cr
    'function=sq+"o2 e8 hl0 58 05 gl "+wsig+" 83 c0 06 "+cr
  else 'cpuw=8
    function="lea rip "+rg+","+wsig+cr
  endif
  '
end function



function stodat(string*wr, int le) as string
============================================
  int a,b
  string w1,w2
  if cpuw=8
    w2=" 48" 'pointer returned in 64 bit rax instead of 32 bit eax
  endif
  '
  '
  'PSEUDO-BSTRING STORED IN THE DATA SECTION AND REFERENCED
  '
  if nstod=0
    datc++
    w1=hex(datc)   'ID SERIAL
    apdat "/+4 gd "'DATA MARK
    apdat w1       'ID
    apdat hexl(le) 'LENGTH FIELD
    apdat " "
    apdat wr 'MACHINE SCRIPT CONTENT
    apdat cr
    function="o2"+w2+" 8D 83 gc "+w1+cr 
    'eventually mov eax/rax,[ebx/rbx-????]
  endif
end function



function stodata(string*wr) as string
=====================================
  int q,le
  if nsto
    exit function
  endif
  q=asc(wr)
  q=isq(q)
  le=len(wr)
  if q
    le-=2
    wr+=" hw0"
  endif
  function=stodat(wr,le)
end function


function identypes(int tp) as string
====================================
  '
  int l
  string wr
  l=tp and 15
  select l
  case  1 : wr="byte  "
  case  2 : wr="word  "
  case  4 : wr="dword "
  case  8 : wr="qword "
  case 10 : wr="eword "
  case 12 : wr="eword "
  end select
  function=wr
  '
end function


  'RUNTIME CALL VECTORS
  '====================

  'mboxs     ' 2048  800h  display string in message box
  'noof      ' 2056  808h
  'addlist   ' 2064  810h  add to list
  'delist    ' 2072  818h  delete
  'delchain  ' 2080  820h  delete chain of lists
  'strinstl  ' 2088  828h  check string instance local
  'strinstg  ' 2096  830h  check string instance global
  'deltmp    ' 2104  838h  free temp strings
  'delloc    ' 2112  840h  local strings 
  'noof      ' 2120  848h
  'compnnul  ' 2128  850h  compare null terminated string
  'noof      ' 2136  858h
  'sysdelbufs' 2144  860h  del system buffs
  'catbufprp ' 2152  868h  clear concat string lists
  'badcatl   ' 2160  870h  add byref bstr to cat list [640]
  'sadcatl   ' 2168  878h  add byval bstr to list (bstr params passed byva
  'zadcatl   ' 2176  880h  add z string to cat list   [640]
  'joins     ' 2184  888h  join strings: copy into one
  'comps     ' 2192  890h  compare bstring
  'compz     ' 2200  898h  compare zstrings
  'assglo    ' 2208  8A0h  assign to global bstr list [ebx+664]
  'assloc    ' 2216  8A8h  assign to local bstr list [ebp-4]
  'asstmp    ' 2224  8B0h  assign to temp bstr list [ebp-8]
  'compw     ' 2232  8B8h  compare wzstrings
  'asstrl    ' 2240  8C0h  assign string [local list ]
  'asstrg    ' 2248  8C8h  assign string [global list]
  'trbstr    ' 2256  8D0h  transfer bstr
  'noof      ' 2264  8D8h
  'noof      ' 2272  8E0h
  'compis    ' 2280  8E8h  compare with bstr byref with byval
  'compris   ' 2288  8F0h  compare with bstr byref with byval
  'deref0    ' 2296  8F8h  dereference if possible or return 0
  'compn     ' 2304  900h  compare n bytes
  'ltrims    ' 2312  908h  ltrim string
  'rtrims    ' 2320  910h  rtrim string
  'lcases    ' 2328  918h  lcase string
  'ucases    ' 2336  920h  ucase string
  'lefts     ' 2344  928h  left string
  'midbufz   ' 2352  930h  midbuf for zstring
  'mids      ' 2360  938h  mid string
  'ascs      ' 2368  940h  asc string
  'lens      ' 2376  948h  len string
  'chrs      ' 2384  950h  chr string
  'midz      ' 2392  958h  mid for asciiz for null terminated strings
  'leftz     ' 2400  960h  left for null terminated strings (zstring
  'lenz      ' 2408  968h  length of zstring and wzstring
  'mids2     ' 2416  970h  2 param mid
  'midz2     ' 2424  978h  2 param mid for asciiz
  'ascs1     ' 2432  980h  1 param asc
  'bindls    ' 2440  988h  bind imported libs and procs
  'freels    ' 2448  990h  free libs
  'midbuf    ' 2456  998h  mid(s,i=t
  'stringa   ' 2464  9A0h  string byte
  'stringz   ' 2472  9A8h  string string bytes asciiz
  'strings   ' 2480  9B0h  string zstring
  'spaces    ' 2488  9B8h  space zstring
  'prints    ' 2496  9C0h  print string
  'instrs2   ' 2504  9C8h  2 parm instr(s,u
  'getfile2  ' 2512  9D0h  getfile "t.txt",f
  'strs      ' 2520  9D8h  convert float to string
  'unics     ' 2528  9E0h  unicode (wide string)
  'unics1    ' 2536  9E8h  1 param unicode (wide string)
  'wchrs     ' 2544  9F0h  wide chr
  'numform   ' 2552  9F8h  numeric format (numberformat)
  'numformd  ' 2560  A00h  numeric format default (numberformat)


  'REFERENCED IN COMPILER
  =======================
  
  % getmemsa 8
  % getmemsc "GetMemory"

  % freememsa 16
  % freememsc "FreeMemory"

  % allocsa 160
  % allocsc "AllocString"

  % freesa 168
  % freesc "FreeString"

  % atofa 192
  % atofc "ascii to float"

  % ftoaa 200
  % ftoac "float to ascii"

  % mboxa 2048
  % mboxc "display string in message box"
  
  % addlista 2064
  % addlistc "add mem to list"

  % delista 2072
  % delistc "delete mem list"

  % delchaina 2080
  % delchainc "delete chain of lists"

  % strinstla 2088
  % strinstlc "check string instance local"

  % strinstga   2096
  % strinstgc "check string instance global"

  % deltmpa 2104
  % deltmpc "free temp strings"

  % delloca 2112
  % dellocc "free local strings"

  % compnnula 2128
  % compnnulc "compare null-terminated strings"

  % sysdelbufsa 2144
  % sysdelbufsc "del system buffs"

  % catbufprpa 2152
  % catbufprpc "clear string lists"

  % badcatla 2160
  % badcatlc "add byref bstr to cat list [ebx+640]"

  % sadcatla 2168
  % sadcatlc "add byval bstr to list"

  % zadcatla 2176
  % zadcatlc "add zstring to cat list   [ebx+640]"

  % joinsa 2184
  % joinsc "join strings: copy into one"

  % compsa 2192
  % compsc "compare bstring"

  % compza 2200
  % compzc "compare zstrings"

  % assgloa 2208
  % assgloc "assign to global bstr list [ebx+664]"

  % assloca 2216
  % asslocc "assign to local bstr list [ebp-4]"

  % asstmpa 2224
  % asstmpc "assign to temp bstr list [ebp-8]"

  % compwa 2232
  % compwc "compare wzstrings"

  % asstrla 2240
  % asstrlc "assign bstring [local list]"

  % asstrga 2248
  % asstrgc "assign bstring [global list]"

  % trbstra 2256
  % trbstrc "transfer bstr"

  % madcatla 2264
  % madcatlc "add z string to cat list [ebp-12]"

  % midstra 2272
  % midstrc "char* in eax and length in ecx"

  % compisa 2280
  % compisc "compare with bstr byref with byval"

  % comprisa 2288
  % comprisc "compare with bstr byref with byval"

  % deref0a 2296
  % deref0c "dereference if possible or return 0"

  % compna 2304
  % compnc "compare n bytes"

  % ltrimsa 2312
  % ltrimsc "ltrim string"

  % rtrimsa 2320
  % rtrimsc "rtrim string"

  % lcasesa 2328
  % lcasesc "lcase string"

  % ucasesa 2336
  % ucasesc "ucase string"

 % leftsa 2344
 % leftsc "left string"

  % midbufza 2352
  % midbufzc "mid patch string: mid(z,i)=t"

  % midsa 2360
  % midsc "mid string"

  % ascsa 2368
  % ascsc "asc string"

  % lensa 2376
  % lensc "len string"

  % chrsa 2384
  % chrsc "chr"

  % midza 2392
  % midzc "928 mid for asciiz string literals"

  % leftza 2400
  % leftzc "left for asciiz"

  % lenza 2408
  % lenzc "len for zstring and wzstring"

  % mids2a 2416
  % mids2c "2 param mid"

  % midz2a 2424
  % midz2c "2 param mid for asciiz"

  % ascs1a 2432
  % ascs1c "1 param asc"

  % bindlsa 2440
  % bindlsc "bind imported libs and procs"

  % freelsa 2448
  % freelsc "free dlls"

  % midbufa 2456
  % midbufc "mid(s,i)=t"

  % stringaa 2464
  % stringac "string byte"

  % stringza 2472
  % stringzc "string ztring"

  % stringsa 2480
  % stringsc "string string"

  % spacesa 2488
  % spacesc "space incl zstring"

  % printsa 2496
  % printsc "print string"

  % instrs2a 2504
  % instrs2c "2 parm instr(s,u)"

  % getfile2a 2512
  % getfile2c "getfile "t.txt",f"

  % strsa 2520
  % strsc "convert float to string"

  % unicsa 2528
  % unicsc "unicode (wide string)"

  % unics1a 2536
  % unics1c "1 param unicode (wide string)"

  % wchrsa 2544
  % wchrsc "wide chr"

  % numforma 2552
  % numformc "numeric format (numberformat)"

  % numformda 2560
  % numformdc "numeric format default (numberformat)"

  ======================================================



  'CONDITIONAL JUMP ENCODING
  '=========================
  '
  string cops=
  "       jb  jae jz  jnz jbe ja                  jl  jge jle jg  "
  '       2   3   4   5   6   7                   C   D   E   F   '  
  '       8   12  16  20  24  28                  48  52  56  60  '


  'DATA TYPES
  '==========
  '
  'BASE DATA TYPES
  '===============

  'also used for reverse dictionary to obtain type name from type code

  string idtype="
  void 10,
  sbyte 1,
  short 2,
  long 4,
  sys 8,
  byte 21,
  ubyte 21,
  word 22,
  dword 24,
  usys  28,
  quad 48,
  qword 58,
  single 64,
  double 68,
  extended 6A,
  cpu 20,
  fpu 40,
  char A1,
  wchar A2,
  zstring A1,
  wzstring A2,
  bstring C1,
  wbstring C2,
  string E1,
  wstring E2,
  "

function typename(int n) as string
==================================
  if n<typh
    return revdic(idtype,n)
  else
    return mrcso(n-typh,0)
  endif
end function


'
' ######## OPER  #########
' #      #=======#       #
' ########       #########
'                #       #
'                #########
'                #       #
'                #########
'                #       #
'                #########
'                #       #
'                #########
'                #       #
'                #########
'
'
'
'
'X86 INSTRUCTION CODE

function oper(int qp,tp, string*wk) as string
=============================================
  '
  int a,b,c,l,m,v,w,boo
  int p
  string w1,w2,w3,wr,wi,rg,rg2,wp,wv,f,wq
  wv=wk
  select qp
  case 0  : qp=1
  case -1 : exit function
  end select
  '
  if tp>=typh
    'exit function 'IGNORE
    tp=cpuw        'ASSUME VALUE IS IN ACCUM
  endif
  c=asc(wv)
  '
  'if tp=0
  '  tp=cpuw
  'endif
  '
  '
  'TYPE EXCLUDING LENGTH BITS
  '--------------------------
  '
  b=tp and 0x1e0
  '
  'TYPE LENGTH
  '-----------
  '
  l=tp and 15
  '
  '
  'IMPLICIT OPERAND SIZE
  '---------------------
  '
  '
  if tp=0x6a
    l=12 : wr="eword" 'STACK SPACE FOR FPU EXTENDED TYPE
  endif
  '
  '
  '=========
  'CPU TYPES
  '=========
  '
  '
  if b<0x40
    '
    if c=127
      wv=pesp
    endif
    '
    'QUAD(64bit mode) LONG SHORT & BYTE
    '----------------------------------
    '
    if l=0
      l=cpuw
    endif
    '
    if l<4
      if (qp>=4)and(qp<=6)
        l=4
      endif
    endif
    '
    select l 'sizeofregs
    case 1 : rg=" al" : rg2="cl"
    case 2 : rg=" ax" : rg2="cx"
    case 4 : rg="eax" : rg2="ecx"
    case 8 : rg="rax" : rg2="rcx"
    end select
    '
    if c=129
      wv=rg2
    endif
    '
    'NUMBERS
    '-------
    '
    if isn(c)
      select qp
      case 4,8   : wi="push "+wv : goto xop
      case 42    : goto xopd
      case 47,92 : qp=47 : goto xopd
      end select
    endif
    '
    if wv=""
      wv=rg
    endif
    '
/*
if tp=4
  'DIRECT CODING CANDIDATES
  string co,cc,rm
  int a,v
  if qp=1
    cc=" 8b"
  elseif qp=2
    cc=" 89"
  endif
  if cc
    v=valat(strptr(wk)+4)
    if instr(wk,",")
      'immed num
    elseif instr(3,wk,"bx")
      rm=" 83 "
    elseif instr(3,wk,"bp")
      rm=" 85 "
    endif
    if rm
      co="o2"+cc+rm+" nl"+str(v)+cr
      return co
      'print wk+cr+co
    else
      'print "|op "+hex(qp)+" "+hex(tp)+" "+wk+cr
    endif
  endif 
endif
*/
    select qp
    case 01 : wi="mov "      : goto xopv        ' load
    case 02 : wi="mov "      : goto xopr        ' store
    case 3 to 15
      select qp
      case 03 : wi="cmp "      : goto xopv  ' compare
      case 04 : wi="push "+wv  : goto xop   'push
      case 05 : wi="add "+spw1 : goto xop   'dump
      case 06 : wi="pop "+wv   : goto xop   'pop
      case 07 : wi="neg "+rg   : goto xop   'negate accum
      case 08 : wi="add "      : goto xopr  ' +=
      case 09 : wi="sub "      : goto xopr  ' -=
      case 10 : wi="xchg " :   : goto xopv  ' stack accum swap
      case 11 : wi="not "      : goto xopw  ' not
      case 12 : wi="inc "      : goto xopw  ' inc var
      case 13 : wi="dec "      : goto xopw  ' dec var
      case 14 : wi="mov "      : goto xopr  ' multi store
      end select
    case 16 to 31   : goto compv
    case 128 to 143 : goto compv
    case 32 : wr=identypes(l)
      int ta=asc(wv)
      if isn(ta)
        wi="mov eax"+cm+wv+cr : wv="eax"
      else
        wi=""
      endif
      wi+="cmp "+wr+wv+",0" : goto xop   ' cmp 0
    case 33 : wi="and "      : goto xopv        ' and
    case 34 : wi="or  "      : goto xopv        ' or
    case 35 : wi="xor "      : goto xopv        ' xor
    case 43 : wi="add "      : goto xopv        ' add
    case 45 : wi="sub "      : goto xopv        ' subtract
    case 42, 47              : goto xopd        ' multiply or divide
    case 65 : wi="and "      : goto xopr        ' and=
    case 66 : wi="or  "      : goto xopr        ' or=
    case 67 : wi="xor "      : goto xopr        ' xor=
    case 71 : wi="and "      : goto boolev      ' logical and
    case 72 : wi="or  "      : goto boolev      ' logical or
    case 73 : wi="xor "      : goto boolev      ' logical xor
    case 74 to 77
      select qp
      case 74 : wp="shl " ' shift left
      case 75 : wp="shr " ' shift right
      case 76 : wp="rol " ' rotate left
      case 77 : wp="ror " ' rotate right
      end select
      if isn(c)
        wi=wp :goto xopv
      else
        wi="mov cl,"+wv+cr+wp+rg+",cl"
        goto xop
      endif
    case 80 : wi="test "     : goto xopv        ' bitwise 'and' compare
    case 92 : qp=47 : goto xopd                 ' explicit integer divide
    
    end select
    '
'    case 14 to 15
'    if b<0x20
'      f="i"
'      if qp=15
'        f="cwd"+cr+f
'      endif
'    endif
'    if qp=14
'      wi=f+"mul "+wv+cr+"xchg "  ' *=
'    endif
'    if qp=15
'      wi="xchg "+rg+cm+wv+cr+f+"div "+wv+cr+"xchg " ' /=
'    endif
'    goto xopv
    '
    '
    ' itr ^ 94
    goto xop
    '
    '
    subroutine checkliteral
    =======================
    if isn(c)
      if (cpuw=4)or(l<>8)
        if qp<>42 and qp<>47 '*' '/'
          exit subroutine
        else
          wi="mov "+rg2+cm+wv+cr+wi
          wv=rg2
          exit subroutine
        endif
      endif
      '
      '64bit l=8 quad
      w1=left(wv,2)
      if w1="&h" or w1="0x"
        wv=mid(wv,3)
        w1="hq"
      else
        w1="nq"
      endif
      wi="o2 48 b9 "+w1+wv+cr+wi 'load to rcx
      wv=rg2
    endif
    end subroutine

    '
    xopd: ' multiply or divide
    '====
    wi=""
    gosub checkliteral
    if b<0x20
      f="i"
    endif
    if qp=47
      f="cwd"+cr+f
    endif
    wr=identypes(l)
    if qp=42
      wi+=f+"mul "+wr+wv : goto xop
    else
      wi+=f+"div "+wr+wv : goto xop
    endif

    '----
    xopv:
    '====
    '
    gosub checkliteral
    wi+=rg+cm+wv : goto xop
   
    '----
    xopw:
    '====
    '
    if wv<>rg
      wi+=identypes(l)+wv
    else
      wi+=wv
    endif
    goto xop
   
    '----
    xopr:
    '====
    '
    if instr(wv,cm)
      wi+=wv       'COMPOUND
    else
      wi+=wv+cm+rg 'NORMAL
    endif
    goto xop
    '
    '-----
    compv:
    '=====
    '
    if instr(wv,cm)
      'composite wv
      wi="cmp "+wv   'comparators
    else
      wi="cmp "+wv+cm+rg 'comparators
    endif
    goto boole
    '
    '
  endif 'CPU INTEGERS
  '
  '
  '
  '=========
  'FPU TYPES

  fputypes:
  '========
  '
  m=0
  rg=qeax : rg2=qecx
  if b=0x40
    f="fi" : m=1 'INTEGER
  endif
  if b=0x60
    f="f"  : m=2 'FLOAT
  endif
  wr=identypes(l)
  '
  if m
    '
    if l<cpuw
      l=cpuw
    elseif l=10
      l=cpuw+8
    endif
    '
    'toto logical
    'downgrade acc : load saveint and/or/xor eax,[esp]
    '
    if isn(c)
      '
      'NUMBERS FOR FPU
      '
      if dv=0
        wp="fldz"
        if c=45
          wp+=cr+"fchs" 'negative zero
        endif
        goto fln
      endif
      if dv=1
        wp="fld1" : goto fln
      endif
      if dv=2
        wp="fld1"+cr+"fadd st0,st0" : goto fln
      endif
      if dv=4
        wp="fld1"+cr+"fadd st0,st0"+cr+"fadd st0,st0" : goto fln
      endif
      '
      a=dtf
      '
      'if a=0
      '  itr test for sci notation
      'endif
      '
      if a=0
        if (abs(dv)<=0x7fffffff)
          wp="push "+str(dv)+cr+"fild dword "+pesp+cr+"add "+spw1
          goto fln
        endif
      endif
      '
      'SPLIT INTO 2 PARTS
      '
      'double precision floating point
      '
      if a 
        '
        lea rax,[dv]
        mov ecx,[rax]
        mov [v],ecx
        mov ecx,[rax+4]
        mov [w],ecx
        '
        w1="fld"
      else
        int q[1]
        ascii_to_float(strptr wv)
        fistp qword q
        w=q[1] : v=q
        w1="fild"
      endif
      '
      if cpuw=4
        wp="push "+str(w)+cr+"push "+str(v)+cr+w1+" qword "+pesp+cr+"add "+spw2 'quad
      else
        wp="sub "+spw2+cr+"mov dword [rsp+4],"+str(w)+cr+_
        "mov dword [rsp],"+str(v)+cr+_
        w1+" qword [rsp]"+cr+"add "+spw2 'quad
      endif
      '
      '---
      fln:
      '---
      '
      c=128 'SET FLAG FOR NUMBERS
      '
      xfln:
      '
    endif 'numbers
    '
    if c>=127
      f="f" 'TREAT AS FLOAT
    endif
    '
    'itr convert fpu for logical ops
    '
    if wv
      if c<>128
        wp=f+"ld "+wr+wv 'NON-NUMBERS
      endif
      wq=f+"stp "+wr+wv
    else
      wp=""
      wq=""
    endif
    '
    a=0
    '
    select qp
    '-------------
    '
    case 1 : 'LOAD
      '
      if c=129
        exit function 'NO FURTHER ACTION
      endif
      wi=wp+cr 
      if tp=0x58
        wi+=qwordin
      endif
      goto xop
    case 02 :  'STORE
      if tp=0x58
        wi=qwordout+wq
      else
        wi=wq
      endif
      goto xop
    case 03 : wi=wp+cr+"fxch : fcomi st1 : fxch"+cr+
              "fstp st0"+cr : goto xop
    case 04
      if wp
        if l=cpuw
          if c<>128
            wi="push "+wv : goto xop 'not numbers
          endif
        endif
        wp+=cr
      endif
      wi="sub "+qesp+cm+str(l)+cr+wp+f+"stp "+wr+pesp
      goto xop
    case 05
      wi="add "+qesp+cm+str(l)
      goto xop
    case 06
      wi=f+"ld "+wr+pesp+cr+"add "+qesp+cm+str(l)
      goto xop
    case 07
      wi="fchs" : goto xop 'negate accum
    case 10
      wi=f+"ld "+wr+pesp+cr+"fxch"+cr+f+"stp "+wr+" "+pesp : goto xop ' xchg with stack
    '
'    case 11
'      if wv=pesp
'        a=11 : wi=wp+cr else a=0 : wi=""
'      endif
'      'BOOLEAN IMPLEMENTATION
'      wi+="fldz"+cr+"fcomip"+cr+"fstp st0"+cr+"fldz"+cr+_
'      "jnz fwd _cc"+cr+"fstp st0"+cr+"fld1"+cr+"fchs"+cr+"._cc"+cr
'      'BITWISE IMPLEMENTAION
'      'wi+="fld1 : faddp st1,st0 : fchs"
'      if a
'        wi+=cr+wq
'      endif
'      goto xop        'NOT (via 2s complement)
'    '
    case 12 : wi=wp+cr+"fld1"+cr+"faddp st1"+cr+wq : goto xop 'inc
    case 13 : wi=wp+cr+"fld1"+cr+"fsubp st1"+cr+wq : goto xop 'dec
    case 14 : wi=wq : mid(wi,instr(wi,"p"))=" " : goto xop 'STORE & LEAVE ON STACK
    '
    '
    '
    '
    end select
    '
    '
    'FPU ARITHMETIC
    '==============
    '
    '
    'QUAD / QWORD OPERAND
    '
    if (tp=0x48)or(tp=0x58)
      '
      if c=128
        wi=wp+cr 'number
      else
        wi="fild qword "+wv+cr
      endif
      '
      'QWORD OPERANDS
      'add complement to negative value
      if tp=0x58
        wi+=qwordin
      endif
      '
      select qp
      case 42 : wi+="fmulp st1" : goto xop
      case 43 : wi+="faddp st1" : goto xop
      case 45 : wi+="fsubp st1" : goto xop
      case 47 : wi+="fdivp st1" : goto xop
      case 92
        '
        'INTEGER DIVISION
        '
        wi+="sub "+spw1+" : fstcw "+pesp+" : fstcw ["+qesp+"+2] : or "+pesp+",0xc00 : fldcw "+pesp+cr+_
        "fdivp st1,st0 : frndint : fldcw ["+qesp+"+2] : add "+spw1
        goto xop
      end select
    endif
    '
    '
    'ALL OTHER OPERANDS
    '
    select qp
    case 42
      wi=f+"mul"
    case 43
      wi=f+"add"
    case 45
      wi=f+"sub"
    case 47
      wi="fdiv"
      if (c<127)or(c>129)
        c=128 'always use float div
      endif
    case 92
      '
      'INTEGER DIVISION '\'
      if c=129
        wi=""
      else
        wi=wp+cr 'PRE-LOADED ON STACK OR NOT
      endif
      wi+="fdivp st1,st0"+cr
      '
      'TRUNCATE FRACTION
      '
      wi="sub "+spw1+cr+_
      "fstcw "+pesp+cr+_
      "fstcw ["+qesp+"+2]"+cr+_
      "or "+pesp+",0xc00"+cr+_
      "fldcw "+pesp+cr+_
      wi+"frndint"+cr+_
      "fldcw ["+qesp+"+2]"+cr+_
      "add "+spw1
      goto xop
    '
    '
    case 32
      wi="fldz"+cr+wp+cr+"fcomip st1"+cr+"fstp st0" : goto xop 'FOR TRUE/FALSE COMPARE
    '
    'case 74..77 'shl..ror 'not for floats
    case 93
      wi=wp+cr+"fxch st1 : fprem : fstp st1"+cr
      goto xop
    case 94
      a=lookupm("pow")
      wi=wp+cr+mrcso(a,1) : goto xop '^ POWER
    end select
    '
    if ((qp>=0x10)and(qp<0x20))or((qp>=0x80)and(qp<0x90))
      'wp=f+"ld "+wr+pesp
      wi="fxch"+cr+"fcomip st1"+cr+"fstp st0"
      'wq="add "+qesp+cm+str(l)+cr
      wq=""
      goto boole
    endif
    '
    'USUAL COMPLETION OF OPERATION
    '-----------------------------
    '
    if wi
      if (tp=0x6a)and(c<>127)
        c=128 'PRELOAD EXTENDED VARIABLE
      endif
      if (c>=127)and(c<=129)
        if c=128
          wi=wp+cr+wi 'NUMBERS
        endif
        wi+="p st1,st0"
        goto xop
      endif
      wi+=" "+wr+wv
      goto xop
    endif
    '
    '
  endif
  '
  '
  '========
  ' STRINGS
  '========
  '
  if (tp>0xa0)and(tp<0x100)
    '
    rg=qeax : rg2=qecx
    '
    'LOADING AND APPENDING
    '=====================
    '
    if qp=33
      qp=43 'INTERPRET & AS CONCAT
    endif
    '
    if (qp<2)or(qp=33)or(qp=43)or(qp=45)
      '
      a=tp and 15 : b=tp-a
      w1=charwidth(a)
      w3=""
      '
      select b
      case 0xa0 : a=zadcatla : w3=zadcatlc
      case 0xb0 : a=madcatla : w3=madcatlc
      case 0xc0 : a=sadcatla : w3=sadcatlc
      case 0xe0 : a=badcatla : w3=badcatlc
      end select
      '
      if shd
        w1+=cmt+w3+cr
      else
        w3=""
      endif
      w1+=rtlo(a)
      '
      if (b<0xc0)and(wv<>rg)
        w2="lea " 
      else
        w2="mov "
      endif
      '
      if qp<02
        if wv
          w3=w2+rg+cm+wv+cr
        else
          w3=""
        endif
        if shd
          w3+=cmt+catbufprpc+cr
        endif
        wi=w3+rtlo(catbufprpa)+w1
        goto xop 'get
      else
        if wv=""
          wi=w1 : goto xop ' add
        endif
        wi=w2+rg+cm+wv+cr+w1 : goto xop
      endif
      '
    endif
    '
    'ASSIGNING
    '=========
    '
    if (qp=2)or(qp=14)
      '
      w1=""
      'jn=0
      '
      'INDIRECT BSTR BYREF
      '-------------------
      '
      '
      if tp>0xe0
        '
        wi=w1+"lea "+rg2+cm+wv+cr
        goto xop
        '
      endif
      '
      'BSTR BYVAL
      '----------
      '
      if tp>0xc0
        '
        'destroy old bstr before assign
        '
        if cpuw=4
          wi="push "
        else
          wi="mov rcx,"
        endif
        if shd
          w2=cmt+freememsc+cr
        else
          w2=""
        endif
        wi=w2+w1+pusheax+
          wi+wv+cr+rtlo(freememsa)+
          cr+popeax+"mov "+wv+cm+rg
        if cpuw=8
          wi="|sp -8"+cr+wi+cr+"|sp 8"+cr
        endif
        goto xop 'FREEMEM
      endif
      '
      '
      'DIRECT ZSTRING ETC
      '--------------------------
      '
      '
      a=tp and 15
      wi=""
      if shd
        wi+=cmt+joinsc+cr
      endif
      wi+="lea "+rg+cm+wv+cr+charwidth(a)+rtlo(joinsa)
      goto xop
      '
    endif 'qp=2
    '
    '
    'JOINING STRINGS
    '===============
    '
    'used for joining unassigned strings (params)
    '
    if qp=96
      'jn=0
      a=tp and 15
      wi=""
      if shd
        wi+=cmt+joinsc+cr
      endif
      wi+=charwidth(a)+"xor "+rg+cm+rg+cr+rtlo(joinsa)
      goto xop
    endif
    '
    '
    'COMPARING STRINGS
    '=================
    '
    a=0
    if qp=3
      a=1
    elseif (qp>=0x10)and(qp<=0x20)
      a=1 'compare left with right
    elseif (qp>=0x80)and(qp<0x90)
      a=1 'compare left with right
    endif
    if a
      if cpuw=4
        if qp<>0x20 
          w1="push "+wv+cr+pusheax
        else
          w1="push "+wv+cr+"push 0"+cr
        endif
      else 'cpuw=8
        if qp<>0x20 
          w1="mov rdx,"+wv+cr+"mov rcx,rax"+cr
        else
          w1="mov rdx,"+wv+cr+"mov rcx,0"+cr
        endif
      endif
      '
      a=tp and 0x7fffffe0
      '
      w2=""
      if a=0xa0
        if tp=0xa1
          if shd
            w2+=cmt+compzc+cr
          endif
          w2+=rtlo(compza)
        else
          if shd
            w2+=cmt+compwc+cr
          endif
          w2+=rtlo(compwa)
        endif
      else
        if shd
          w2+=cmt+compsc+cr
        endif
        w2+=rtlo(compsa)
      endif
      '
      '
      'DYNAMIC STRING
      '
      if tp=0xe1
        if qp=0x20
          w2=""
          if shd
            w2+=cmt+compisc+cr
          endif
          w2+=rtlo(compisa)
        endif
      endif
      if qp=0x20
        wi=pusheax+w1+w2+"pop "+qeax
      endif
      wi=w1+w2
      if qp=0x20
        goto xop
      else
        goto boole
      endif
    endif
    '
    'OTHER
    '=====
    '
    if qp=04
      wi="push "+rg   ' push used only for left side compare
    elseif qp=05
      wi="add "+spw1  ' dump not used
    elseif qp=06
      wi="pop "+rg    ' pop not used
    endif
    goto xop
    '
  endif 'STRINGS
  '
  goto xop
  '
  '======
  boolev: 'BOOLEAN OPERATIONS && || ^^ 
  '======
  '
  w1="or "+rg+cm+rg+cr+"setnz al"+cr+
  "and "+qeax+",1"+cr+"neg "+qeax+cr
  wi=w1+"mov "+qedx+cm+qeax+cr+_
  "mov "+rg+cm+wv+cr+w1+_
  wi+qeax+cm+qedx
  goto xop
  '
  '==============
  boole: '
  '==============
  '
  encrlf(wi)
  '
  if qp>=128
    qp-=112 '0x70
    decidecop(qp,tp)
    return wi+mid(cops,qp*4-64,4)
  else
    decidecop(qp,tp)
    return wi+"set"+mid(cops,qp*4-63,3)+
    "al"+cr+"and "+qeax+",1"+cr+
    "neg "+qeax+cr
'    return wi+"set"+mid(cops,qp*4-63,3)+
'"al
'and eax,1
'neg eax
'"
  endif
  exit function
  
  '
  '------------------------------
  xop: 'RESOLVED OPERATOR OPERAND
  '==============================
  '
  if wi=""
    if (parx=0)or(op>1)
      'allow load or push 
      if (qp<>4)and(qp<>6)
        ert=150
        if tp=0x10
          ers="operation with void variable"+cr
        else
          ers=""
        endif
        ers+="unidentified operation ("+identops(qp)+") for this type ("+typename(tp)+")"
        'wi="nop"
      endif
    endif
  else
    encrlf(wi)
  endif
  '
  return wi
  '
end function


' 
'                       #      #########
'  ########    CONVERT   ##    #       #
'  #      #  ################  #       #
'  ########              ##    #       #
'                       #      #########
' 


function cpufpu(int pp,*typb, string*wr) as string
==================================================
  '
  int b,tb
  string w1
  '
  tb=typb
  b=0
  '
  'SMALL TYPES
  '-----------
  '
  if typb=0x01
    b=1 'SIGNED BYTE
  endif
  if typb=0x21
    b=1 'UNSIGNED BYTE TO SHORT
  endif
  if typb=0x02
    b=2 'SHORT TO SHORT
  endif
  if typb=0x22
    b=4  'UNSIGNED WORD TO LONG
    if pp<0
      w1="and "+qeax+",0xffff"+cr
    endif
  endif
  '
  if b
    b+=0x40
    if pp>=0
      w1+="xor "+qeax+cm+qeax+cr+oper(1,typb,wr)
    else
      pp=1
    endif
    if b=0x41
      b=0x42
      if typb=0x1
        w1+="movsx eax,al"+cr
      else
        w1+="movzx eax,al"+cr
      endif
    endif
    w1+=pusheax+oper(pp,b,pesp)+"add "+spw1+cr
    typb=b : goto xcv
  endif
  '
  if pp<0
    pp=1
  endif
  '
  'UNSIGNED DWORD
  if typb=0x24
    typb=0x48
    w1+="push 0"+cr+
    "push "+wr+cr+oper(pp,typb,pesp)+"add "+spw2+cr
    goto xcv
  endif
  '
  'SIMPLE CONVERSION
  '-----------------
  '
  if typb<=8
    '
    'REGISTERS
    '
    typb+=0x40
    if asc(wr)<>91
      w1+="push "+wr+cr+oper(pp,typb,pesp)+"add "+spw1+cr
      goto xcv
    endif
      '
  endif
    '
  if typb=0x01
    typb=0x42 : goto ncv ' BYTE TO SHORT
  endif
  if typb=0x02
    typb=0x42 : goto ncv ' SHORT TO SHORT
  endif
  if typb=0x04
    typb=0x44 : goto ncv ' LONG TO LONG
  endif
  '
  '
  'UNSIGNED QWORD
  '--------------
  '
  if typb=0x28
    typb=0x58
    if cpuw=8
      w1+="push "+wr+cr+oper(pp,typb,pesp)+"add "+spw1+cr
    else
      'itr unsupported
      w1+="push 0"+cr+
      "push "+wr+cr+oper(pp,typb,pesp)+"add "+spw2+cr
    endif
    w1+=qwordin
    goto xcv
  endif

  '
  'DEFAULT
  '-------
  '
  ncv:
  '
  w1+=oper(pp,typb,wr) ' no operand conversion
  '
  xcv:
  '
  function=w1
  '
end function


function cvta(int typa,typb) as string
======================================
  '
  ' FOR ACCUMULATOR
  ' CONVERT FROM TYPE A TO TYPE B

  ' bytes are treated as unsigned
  '
  int a,b,la,lb,ta,tb
  string tc,w1,w2,w3,w4
  '
  '
  'EXCLUDE MATCHING OR UNKNOWN TYPES
  '
  if (typa=typb)or(typa=0)or(typb=0)
    goto xcvt
  endif
  '
  '
  'HIGHER TYPE CHECK
  '=================
  '
  if (typa>=typh)or(typb>=typh)
    if typb<>typa
      'ers="type mismatch " : ert=98
      'ASSUME NO CONVERSION REQUIRED
    endif
    goto xcvt
  endif
  '
  '
  'GET LENGTH OF PRIMITIVE
  '
  la=typa and 15
  lb=typb and 15
  ta=typa and 0x7fffffc0
  tb=typb and 0x7fffffc0
  '
  '
  if typa=0
    typa=cpuw
  endif
  if typb=0
    typb=cpuw
  endif
  '
  '
  'CONVERSION FROM NUMBER TO BSTRING
  '=================================
  '
   if (tb=0xc0)or(tb=0x80)
     if typa<0xa0
      '
      if vew>0
        w1=";CONVERT VAL TO STRING"
      endif
      '
      'UPGRADE NUMBER TYPE FIRST (CVTA RECURSIVE)
      '
      tc=cvta(typa,0x68) 'CONVERT NUMBER TO FLOAT
      if shd
        tc+=cmt+strsc+cr
      endif
      if cpuw=4
        tc+=rtlo(strsa)
      else
        tc+="sub rsp,32"+cr+rtlo(strsa)+"add rsp,32"+cr
      endif
      goto xcvt
    endif
  endif
  '
  '
  'CONVERSION FROM BSTRING TO NUMBER
  '=================================
  '
  if (ta=0xc0)or(ta=0x80)
    if typb<0xa0
      '
      if vew>0
        w1=";CONVERT STRING TO VAL"
      endif
      '
      tc=""
      if shd
        tc+=cmt+atofc+cr
      endif
      if cpuw=4
        tc+=pusheax+rtlo(atofa)
      else
        tc+="sub rsp,32"+cr+"mov rcx,rax"+cr+rtlo(atofa)+"add rsp,32"+cr
      endif
      '
      typa=0x6a : ta=0x40
      '
      'continue with conversion
      '
      goto fpucpu
      '
    endif
  endif
  '
  '
  'STRING CONVERSIONS
  '==================
  '
  a=0
  if tb=0xc0
    if ta=0x80
      a=1
    endif
    if (ta=tb)and(la<>lb)
      a=1
    endif
  elseif tb=0x80
    'if ta=0xc0
    '  a=1
    'endif
    'if (ta=tb)and(la<>lb)
    '  a=1
    'endif
    if la<>lb
      a=1
    endif
  endif
  if a
    convs or=2
    w1="STRING"
    goto xcvt
  endif
  
  '
  '
  'CPU to CPU RESIZE
  '=================
  '
  ' UNSIGNED AND SIGNED
  '
  'SOURCE SHORTS AND LONGS WILL BE SIGN EXTENDED BUT NOT BYTES
  '
  if ta+tb=0
    '
    if lb=1
      tc="and "+qeax+",0xff"+cr 'MASK UPPER BITS
    elseif lb=2
      if typb=2 'CONVERT TO SHORT INT
        if typa=1
           tc="movsx ax,al"+cr
        elseif typa=0x21
           tc="movzx eax,al"+cr
        endif
      else 'typb=0x22
        if la=1
          tc="movzx eax,al"+cr
        endif
      endif
    endif
    '
    if lb=4
      '
      if la=1
        if (typb=4)and(typa=1)
          tc="movsx eax,al"+cr
        else
          tc="movzx eax,al"+cr
        endif
      elseif la=2
        if (typb=4)and(typa=2)
          tc="movsx eax,ax"+cr
        else
          tc="movzx eax,ax"+cr
        endif
      elseif la=4
      elseif la=8
        goto xcvt 'no conversion required
      endif
 
    endif
    '
    if lb=8
      if cpuw=4
        if la=1
          if (typa=1)and(typb=8)
            tc="movsx eax,al"+cr+"cwd"+cr
          else
            tc="movzx eax,al"+cr+"cwd"+cr
          endif
        elseif la=2
          if (typa=2)and(typb=8)
            tc="movsx eax,ax"+cr+"cwd"+cr
          else
            tc="movzx eax,ax"+cr+"cwd"+cr
          endif
        elseif la=4
          if (typa=4)and(typb=8)
            tc="cwd"+cr
          else
            tc="xor "+qedx+cm+qedx+cr
          endif
        endif
      else 'cpuw=8
        if la=1
          if (typa=1)and(typb=8)
            tc="movsx rax,al"+cr
          else
            tc="movzx rax,al"+cr
          endif
        elseif la=2
          if (typa=2)and(typb=8)
            tc="movsx rax,ax"+cr
          else
            tc="movzx rax,ax"+cr
          endif
        elseif la=4
          if (typa=4)and(typb=8)
            tc="movsxd rax,eax"+cr
          else
            'tc="and rax,0xffffffff"+cr
            tc=""
          endif
        endif
      endif
    endif
    '
    '
    if vew>0
      if typa>typb
        w1="CPU DOWNSIZE"
      else
        w1="CPU UPSIZE"
      endif
    endif
    '
    goto xcvt
  endif
  '
  'if floats differ in type
  '  prevent compat sig shortcut
  'endif
  '
  if (ta=0x40)and(tb=0x40)
    convs or=2 : goto xcvt
  endif
  '
  'FPU to CPU
  '==========
  '
  fpucpu:
  '
  if tb=0
    if ta=0x40
      'if lb=8
      '  tc+="sub "+spw1+cr+"fistp qword "+pesp+cr+popeax
      'endif
      'if lb<=4
      '  tc+="sub "+spw1+cr+"fistp dword "+pesp+cr+popeax
      'endif
      tc+="sub "+qesp+",8"+cr+"fistp qword "+pesp+cr+"mov "+qeax+cm+pesp+cr+"add "+qesp+",8"+cr
      if lb=2
        tc+="and "+qeax+",0xffff"+cr
      endif
      if lb=1
        tc+="and "+qeax+",0xff"+cr
      endif
      if vew>0
        w1="FPU TO CPU"
      endif
      goto xcvt
    endif
  endif
  '
  'CPU to FPU
  '==========
  '
  if (typa<0x40)and(isfpu(typb)<>0)
    if vew>0
      w1="CPU TO FPU"
    endif
    tc=cpufpu(-1,typa,qeax)
  endif
  '
  xcvt:
  '
  if tc
    convs or=1
  endif
  if vew>0
    if convs
      tc="'CONVERT "+W1+cr+tc
    endif
  endif
  function=tc
  '
end function




'  BINDING:
'  ########    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
'       ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
'      ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
'     ##====##====##====##====##====##----##----##----##----##----##----##----##----##----##
'    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
'   ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
'  ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ########



function bindlprocs() as string
===============================
  '
  int a,k
  string wa
  string w1
  '
  if impo=0
    return ""
  endif
  '
  '---------------------
  'BUILD BIND PROCEDURES
  '---------------------
  '
  a=dlb
  k=j
  string wt1
  wa=cr+stodata(wt1) 'set gc and gd index
  do
    if a>=libe
      exit do
    endif
    '
    'PROCESS PROC ADDRESSES FOR EACH LIBRARY
    '---------------------------------------
    '
    if libu(a)
      '
      'ONLY PROCS THAT HAVE BEEN INVOKED ARE TO BE LINKED
      '--------------------------------------------------
      '
      'LOAD LIBRARY MODULE
      '
      apdat(cr+"01 `"+libs(a)+"` 00"+cr)
      '
      'LOAD PROC LIST
      '
      apdat(left(libl(a),libu(a) ))
      '
      'CLEAR PROC LIST
      '
      libu(a)=0 ' recycle space in buffer
      '
    endif
    '
    'NEXT LIB
    '
    a++
    '
  loop
  '
  'CLEAR LIBRARY LIST
  '------------------
  '
  libe=dlb
  dlb=1
  '
  '
  'TERMINATION CODE
  '----------------
  '
  if cpuw=4
    w1="03 hl0"
  else
    w1="03 hq0"
  endif
  '
  apdat(w1+cr)
  '
  'CALL RUNTIME DLL BINDER
  '
  impo=0
  w1=""
  if shd
    w1+=cmt+bindlsc+cr
  endif
  return w1+wa+rtlo(bindlsa)+
  "cmp al,100"+cr+
  "jge fwd _error_"+cr 'ERROR QUIT
  '
end function


'=>




'ABSTRACT OP WITH INTEGER TO FLOAT CONVERSION

function regparams(string*s, int*i) as string
=============================================
'lr'
'ms 64bit
int b,c,k,m,p
string w1,w3
c=hexval(s,i) 'lowest unused reg
p=hexval(s,i) 'highest used reg
b=c
do
  if asc(s,i)<=13
    exit do
  endif
  k=hexval(s,i)   
  if isfloat(k)
    m=7 'use simd register for direct float
  else
    m=0
  endif
  if k=0x40
    w3=""
  else
    if (m>0)or(b>p)
      w3=rgp(b+m)+memreg(qesp,b*8-8)+cr
    else
      w3="" 'not required
    endif
    if m 'floats
      if (k and 15)=8
        mid(w3,5)="d" 'double precision
      endif
    endif
  endif
  w1+=w3
  b++
loop
return w1
end function



function itran(string*s) as string
==================================
int a,b,c,d,m,p,wb,le,st,c1,c2
string wr,w1,w2,w3
string we
string wnp,wni
b=1
wb=b
do
  if ert
    w1=findlinek(b,s,"'_",2)
    w2=findlinek(b,s,"'_"+qu,2)
    ers="Error:"+cr+"line "+w2+w1+ers
    exit do 'catch first err only
  endif
  b=instr(b,s,"|") 'FIND NEXT INSTRUCTION
int pp=b
  if b=0 
    exit do
  endif
  if asc(s,b+3)>32
    b++ : continue do
  endif
  a=b-wb
  if a
    tbuf(mid(s,wb,a),st)
  endif
  c=b+4
  d=instr(c,s,cr)+2
  if d<=2
    d=len(s)
  endif
  w1=""
  c1=asc(s,b+1)
  c2=asc(s,b+2)
  '
  select c1
  '
  case 0x6F 'o'
    '
    select c2
    '
    case 0x70 'op' operation
    '
    op=hexval(s,c)
    typ=hexval(s,c)
    a=asc(s,c)
    if a>32
      a=instr(c,s,chr(13))
      w1=mid(s,c,a-c) : c=a 'COMPOUND
    endif
    dtf=instr(w1,".")
    a=asc(w1)
    if isn(a)
      wordval(w1,1,1)
    endif
    if typ=15
      typ=cpuw
    endif
    w1=oper(op,typ,w1)
    '
    end select
  '
  case 0x76 'v'
    '
    select c2
    '
    case 0x61 'va' variable list
    '
    w1=""
    '
    end select
    '
  case 0x61 'a'
    '
    select c2
    '
    case 0x62 'ab' resolve label address
    '
    string wnp
    hexval(s,c) 'dump pls
    w1=addrlabel(yword(s,c))
    wnp=yword(s,c)
    wni=yword(s,c)
    if wnp<>wni
      'insert transient namespaces
      w1="o2 k"+wnp+cr+w1+"o2 k"+wni+cr
    endif
    '
    case 0x6C 'al' align (hex)
    '
    w1="o2 !"+yword(s,c)+cr
    '
    end select
    '
  case 0x6D 'm'
    '
    select c2
    '
    case 0x6B 'mk' move statics
    '
    st=asc(s,c)-48
    '
    end select
    '
  case 0x63 'c'
    '
    select c2
    '
    case 0x68 'ch' set char width
    '
    w1=charwidth(asc(s,c)-48)
    '
    case 0x76 'cv' convert accum
    '
    a=hexval(s,c)
    p=hexval(s,c)
    w1=cvta(a,p)
    '
    end select
    '
  case 0x71 'q'
    '
    select c2
    '
    case 0x75 'qu' store string data
    '
    w1=tword(s,c)
    a=asc(w1,2)
    if (a=iqq) or (a=iqq-1)
      a=val yword(w1,3)
      m=cv4(utfs,a) 'length
      a+=4 'start of string quote
      w1=" "+BinScript(utfs,a,m)+" hl0" 'with terminating nulls
      w1=stodat(w1,m)
    else
      w1=stodata(w1)
    endif
    d=c+2
    '
    end select
    '
  case 0x73 's'
    '
    select c2
    '
    case 0x69 'si' initialise space on stack
    '
    a=hexval(s,c)
    w1="mov "+qecx+cm+str(-a)+cr+"._z_"+cr+_
    "mov ["+qebp+"+"+qecx+"],0"+cr+_
    "add "+qecx+cm+str(cpuw)+cr+_
    "jl _z_"+cr
    '
    case 0x70 'sp' adjust stack pointer
    '
    w1=stackpointadj(s,c)
    d=c
    '
    end select
    '
  case 0x67 'g'
    '
    select c2
    '
    case 0x6F 'go' 0 call / 1 jump / 2 jz / 3 jnz
      c+=2
      select asc(s,c-2)
      case 48 :
        if asc(s,c)<>91
          w3=yword(s,c) 'dump pls
          w3=yword(s,c)+cr 'name
          if w3="fwd"
            w3+=" "+yword(s,c)
          endif
          wnp=yword(s,c)+cr 'nsp
          wni=yword(s,c)+cr 'nsi
          w1="call "+w3+cr
          if asc(wnp)<>48
            'insert transient namespaces
            w1="o2 k"+wnp+cr+w1+"o2 k"+wni+cr
          endif
        else
          w1="call "+mid(s,c,d-c)
        endif
      case 52 :
        w3=yword(s,c)  'dump pls
        w3=yword(s,c)+cr 'name
        if w3="fwd"
          w3+=" "+yword(s,c)
        endif
        w1="call "+w3+cr
      end select
      '
    end select
    '
  case 0x74 't'
    '
    select c2
    '
    case 0x64 'td' dll proc tables etc
    '
    a=hexval(s,c)
    apdat(mid(s,c+1,a)) 'outer quotes excluded
    d=c+a+4 'skip outer quotes + cr
    '
    case 0x65 'te' virtual table entry
    '
    w3=yword(s,c)
    a=hexval(s,c)
    w1=addVTEntry(a,w3)
    'print w1
    '
    end select
    '
  case 0x75 'u'
    '
    select c2
    '
    case 0x65 'ue' virtual table section
    '
    p=hexval(s,c)
    a=hexval(s,c)
    w1=addTableSection(p,a,hexval(s,c))
    'print w1
    '
    end select
    '
  end select
  '
  tbuf(w1,st)
  wb=d
  b=d 'itr not recursive
loop
tbuf(mid(s,wb,len(s)-wb+1),st)
tbuf(w1,-2) 'EXTRACT STATIC VAR INIT
tbuf(wr,-1) 'EXTRACT MAIN
'
b=instr(wr,"._statics_")
if b
  b+=9+len(cr)
  w2=left(wr,b)
  wr=mid(wr,b+1)
else
  w2=""
endif
'
return w2+w1+wr ' RTL | DLL VECTORS | STATICS | MAIN
'
end function



procedure revskipquote(string*s, int*i, q)
==========================================
while asc(s,i)<>q
  i--
wend
end procedure


function instrevnskf(int i, string*s,*wr) as int
================================================
  static int a,b,c,d,le
  if i<0
    i=len(s)+1 '-1 indicates start from right
  endif
  if i<=1
    exit function
  endif
  le=len(wr)
  a=asc(wr,2)
  b=0
  do
    i--
    if i<1
      i=0 : exit do
    endif
    select asc(s,i)
    case hasa
      c=asc(s,i+1)
      d=asc(s,i+2)
      if (b=0)and(c=a)and(le>0)and(asc(s,i+le)<33)and(wr=mid(s,i,le))
        exit do 'word match
      elseif d=0x70
        select c 'block skip
        case 0x78
          b++ : i=instrevn(i,s,")") 'skip multiple '|xp bottom boundary
        case 0x79
          b--
          if b<0
            i=0 : exit do          '|yp top boundary
          endif
        end select
      endif
    case 34 : revskipquote(s,i,34)
    case 96 : revskipquote(s,i,96)
    end select
  loop
  '
  return i
  '
end function



procedure markused(string*s, int*i)
===================================
int a,b,c,d,e,f,g,j,k,p,lk
string wr,wk
k=i
do
  p++
  select p
  case 1 : wk="|go 0" : lk=6 'general procedure calls 'itr namespace
  case 2 : wk="|go 4" : lk=6 'method calls
  case 3 : wk="|ab"   : lk=4 'label addresses
  case 4 : exit do
  end select
  i=k
  do
    if i<1
      exit do
    endif
    i=instrevnskf(i,s,wk) 'LOCATE NEXT CALL ETC
    if i=0
      exit do
    endif
    b=i+lk
    i--
    a=asc(s,b)
    if a<>91
      j=hexval(s,b) 'LOCATION IN PROCLIST (PLS)
      if j=0
        wr=yword(s,b) 'hexval has skipped leading char ','
        a=colom(strptr(wr),len(wr))
        if a
          wr=mid(wr,a+1) 'REMOVE NAMESPACE PREFIX
        endif
        if p=2
          nextspace(s,b) : b++ 'SKIP METHOD VECTOR
        endif
        a=hexval(s,b) 'nsp
        c=hexval(s,b) 'nsi
        e=plistend
        do 'SEARCH NAMESPACES
          j=instrevn(e,proclist," "+wr+" ")
          if j=0
            exit do
          endif
          f=j+len(wr)+3
          d=hexval(proclist, f)
          if a
            if a=d
              exit do  'nsp match
            endif
          else
            if d=0
              exit do  'root namespace
            endif
            if c=d
              exit do  'nsi match
            endif
          endif
          e=j-1 'TRY ANOTHER TO GET NAMESPACE MATCH
        loop 'SEARCH NAMESPACES
        if j=0
          continue do 'NOT FOUND IN PROCLIST
        else
          j-- 'LOCATE START OF RECORD
        endif
      endif
      if asc(proclist,j)<>32
        mid(proclist,j)=" " 'REMOVE DELETION / RECURSION FLAG
        j+=2
        wr=yword(proclist,j)
        hexval(proclist,j)   'SKIP NAMESPACE
        g=hexval(proclist,j) 'LOCATION OF PROCEDURE IN THE CODE
        j=instrevn(g,s,")")
        markused(s,j) 'RECURSE WITHIN PROCEDURE
      endif
    endif
  loop
loop
end procedure

int cnstr
'
function cnsterr() as int
=========================
  if cnstr
    ers="consts are read-only" : ert=126
    return 1
  endif
end function


function operi(int qp, tp, string*wk) as string
===============================================
'op
string w1,w2
if qp=0 
  qp=1
endif
if (cpoint<>0)and(ind<>0)
  if qp=12
    cnsterr()
    return "add "+wk+cm+str(lent)+cr '++
  endif
  if qp=13
    cnsterr()
    return "sub "+wk+cm+str(lent)+cr '--
  endif
endif
if isstr(tp)
  lcl=1
  select qp
  case 1,33,43,45
    jn=nst+1
  case 2
    jn=0
    if isbstr(tp)
      if left(wk,5)="[ebp+"
        if instr(8,wk,"-")=0
          ert=1004
          ers="Must not assign to a direct string param"
        endif
      endif
    endif
  case 96
    jn=0 : dcs=1
    if funi
      lcl=1 ' lcl for cat buf
    endif
  end select
endif
'
w1="|op "+hex(qp)+" "+hex(tp)+" "+wk+cr
if shd '#show
  w2=ow
  if asc(w2)=127
    w2="temp_"+mid(w2,2)
  endif
  w1="'"+w2+cr+w1 'insert as preceding comment
endif
return w1
end function


procedure extractaddr(string*wr)
================================
  int a,b
  a=instrevn(-1,wpfx,medi)
  if a
     b=instr(a,wpfx,"]"+cr) 'for whole operand
    if b
      'len(med)=8
      a+=8 : b++
      wr=mid(wpfx,a,b-a)  '[ebp+...]
      wpfx=left(wpfx,a-9) 'prior dereferencing
    endif
  elseif instr(wpfx,qedi) 'itr members
    wr=qedi
  else
    ert=726
    ers="unable to extract address"
  endif
end procedure


procedure makestrptr(string*wr)
===============================
  string w2
  ascw=asc(wr)
  if isq(ascw)
    wpfx="|qu "+wr+cr
    wr=qeax : goto nmakestr
  elseif isn(ascw)
    goto nmakestr
  elseif wr="null"
    wr="0"
    goto nmakestr
  elseif (typ<0x40)
    wpfx+="mov "+qedi+cm+wr+cr
  elseif (typ<0x80)
    wpfx+=operi(1,typ,wr)+_
    "sub rsp,8"+cr+"fstp qword [rsp]"+cr+"mov rdi,[rsp]"+cr+"add rsp,8"+cr
  elseif (typ<0xc0) 'CHAR*
    if newline
      extractaddr(wr)
      goto nmakestr
    endif
    wpfx+="lea "+qedi+cm+wr+cr
  elseif typ>0xe0
    if newline
      ert=432
      ers="cant assign strptr for dynamic string " owa
      exit sub
    endif
    'CHECK FOR NULL DYNAMIC STRING
    wpfx+="mov "+qedi+cm+wr+cr+"cmp "+qedi+",0"+cr+_
    "jz fwd ndr"+cr+"mov "+qedi+cm+pedi+cr+".ndr"+cr
  elseif typ<0xe0
    goto nmakestr 'BSTRINGS
  endif
  '
  wr=qedi
  '
  nmakestr:
  '
  typ=cpuw
  wpfx="._direct_"+cr+wpfx
end procedure


function makestrptrfun(string*wr) as string
===========================================
string wt
makestrptr(wr)
wt=wpfx
if wr<>qeax
  wt+="mov "+qeax+cm+wr+cr
  wr=qeax
endif
return wt
end function


function refaddr(string*s) as int
=================================
  int a
  string w1
  a=instrevn(-1,s,medi)
  if a
    w1=mid(s,a)
    if instr(w1,medi+pedi)
      'excise mov edi,[edi]
      w1=""
    else
       mid(w1,1)="lea"
       'RETURN ADDRESS ONLY
    endif
    s=left(s,a-1)+w1  'REMOVE ONE LEVEL FROM RIGHT
  else
    return 0
  endif
  return 1
end function


procedure varaddr(string*wr, int*da)
====================================
  int e
  if wr=pedi
    if wpfx
      if da  ' @@ &&
        da=0
        if not refaddr(wpfx) 'DEPOINTER
          ert=725 : ers="unable to get address"
          exit sub
        endif
      endif
      extractaddr(wr)
    else 'no wpfx
      wr=qedi
    endif
  else 'wr<>pedi
    wpfx+=leaedi(wr)
    wr=qedi
  endif
  typ=cpuw
  varf=1
end sub


