Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. ; Macroinstructions for defining and calling procedures (x64 version)
  3.  
  4. macro invoke proc,[arg]
  5.  { common fastcall [proc],arg }
  6.  
  7. macro fastcall proc,[arg]
  8.  { common local stackspace,argscount,counter
  9.     if argscount < 4
  10.      stackspace = 4*8
  11.     else if argscount and 1
  12.      stackspace = (argscount+1)*8
  13.     else
  14.      stackspace = argscount*8
  15.     end if
  16.     counter = 0
  17.     if stackspace
  18.      if defined current@frame
  19.       if current@frame<stackspace
  20.        current@frame = stackspace
  21.       end if
  22.      else
  23.       if stackspace
  24.         sub     rsp, stackspace
  25.       end if
  26.      end if
  27.     end if
  28.    forward
  29.     counter = counter + 1
  30.     define type@param
  31.     define definition@param arg
  32.     match =float value,definition@param
  33.     \{ define definition@param value
  34.        define type@param float \}
  35.     match =addr value,definition@param
  36.     \{ define definition@param value
  37.        define type@param addr \}
  38.     match any=,any,definition@param
  39.     \{ \local ..string,..continue
  40.         jmp     ..continue
  41.        align sizeof.TCHAR
  42.        ..string TCHAR definition@param,0
  43.        ..continue:
  44.        define definition@param ..string
  45.        define type@param addr \}
  46.     match any,definition@param
  47.     \{ match \`any,any
  48.        \\{ \\local ..string,..continue
  49.         jmp     ..continue
  50.            align sizeof.TCHAR
  51.            ..string TCHAR definition@param,0
  52.            ..continue:
  53.            define definition@param ..string
  54.            define type@param addr \\} \}
  55.     match param,definition@param
  56.     \{ local opcode,origin
  57.        size@param = 0
  58.        if param eqtype 0 | param eqtype 0f | type@param eq addr
  59.         size@param = 8
  60.        else if param eqtype byte 0 | param eqtype byte 0f
  61.         match prefix value,definition@param
  62.          \\{ if prefix eq qword
  63.               size@param = 8
  64.              else if prefix eq dword
  65.               size@param = 4
  66.              else if prefix eq word
  67.               size@param = 2
  68.              else if prefix eq byte
  69.               size@param = 1
  70.              end if \\}
  71.        else if ~ param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
  72.         virtual
  73.          origin = $
  74.         inc     param
  75.          load opcode byte from origin
  76.          if opcode = 67h | opcode = 41h
  77.           load opcode byte from origin+1
  78.          end if
  79.          if opcode and 0F8h = 48h
  80.           size@param = 8
  81.          else if opcode = 66h
  82.           size@param = 2
  83.          else if opcode = 0FFh
  84.           size@param = 4
  85.          else
  86.           size@param = 1
  87.          end if
  88.         end virtual
  89.        end if
  90.        if counter = 1
  91.         if type@param eq float
  92.          if ~ param eq xmm0
  93.           if size@param = 4
  94.            if param eqtype byte 0 | param eqtype byte 0f
  95.         mov     eax, param
  96.         movd    xmm0, eax
  97.            else
  98.         movd    xmm0, param
  99.            end if
  100.           else
  101.            if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
  102.         mov     rax, param
  103.         movq    xmm0, rax
  104.            else
  105.         movq    xmm0, param
  106.            end if
  107.           end if
  108.          end if
  109.          if vararg@fastcall & ~ param eq rcx
  110.         movq    rcx, xmm0
  111.          end if
  112.         else if type@param eq addr
  113.          if ~ param eq rcx
  114.         lea     rcx, [param]
  115.          end if
  116.         else if size@param = 8
  117.          if ~ param eq rcx
  118.         mov     rcx, param
  119.          end if
  120.         else if size@param = 4
  121.          if ~ param eq ecx
  122.         mov     ecx, param
  123.          end if
  124.         else if size@param = 2
  125.          if ~ param eq cx
  126.         mov     cx, param
  127.          end if
  128.         else if size@param = 1
  129.          if ~ param eq cl
  130.         mov     cl, param
  131.          end if
  132.         end if
  133.        else if counter = 2
  134.         if type@param eq float
  135.          if ~ param eq xmm1
  136.           if size@param = 4
  137.            if param eqtype byte 0 | param eqtype byte 0f
  138.         mov     eax, param
  139.         movd    xmm1, eax
  140.            else
  141.         movd    xmm1, param
  142.            end if
  143.           else
  144.            if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
  145.         mov     rax, param
  146.         movq    xmm1, rax
  147.            else
  148.         movq    xmm1, param
  149.            end if
  150.           end if
  151.          end if
  152.          if vararg@fastcall & ~ param eq rdx
  153.         movq    rdx, xmm1
  154.          end if
  155.         else if type@param eq addr
  156.          if ~ param eq rdx
  157.         lea     rdx, [param]
  158.          end if
  159.         else if size@param = 8
  160.          if ~ param eq rdx
  161.         mov     rdx, param
  162.          end if
  163.         else if size@param = 4
  164.          if ~ param eq edx
  165.         mov     edx, param
  166.          end if
  167.         else if size@param = 2
  168.          if ~ param eq dx
  169.         mov     dx, param
  170.          end if
  171.         else if size@param = 1
  172.          if ~ param eq dl
  173.         mov     dl, param
  174.          end if
  175.         end if
  176.        else if counter = 3
  177.         if type@param eq float
  178.          if ~ param eq xmm2
  179.           if size@param = 4
  180.            if param eqtype byte 0 | param eqtype byte 0f
  181.         mov     eax, param
  182.         movd    xmm2, eax
  183.            else
  184.         movd    xmm2, param
  185.            end if
  186.           else
  187.            if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
  188.         mov     rax, param
  189.         movq    xmm2, rax
  190.            else
  191.         movq    xmm2, param
  192.            end if
  193.           end if
  194.          end if
  195.          if vararg@fastcall & ~ param eq r8
  196.         movq    r8, xmm2
  197.          end if
  198.         else if type@param eq addr
  199.          if ~ param eq r8
  200.         lea     r8, [param]
  201.          end if
  202.         else if size@param = 8
  203.          if ~ param eq r8
  204.         mov     r8, param
  205.          end if
  206.         else if size@param = 4
  207.          if ~ param eq r8d
  208.         mov     r8d, param
  209.          end if
  210.         else if size@param = 2
  211.          if ~ param eq r8w
  212.         mov     r8w, param
  213.          end if
  214.         else if size@param = 1
  215.          if ~ param eq r8b
  216.         mov     r8b, param
  217.          end if
  218.         end if
  219.        else if counter = 4
  220.         if type@param eq float
  221.          if ~ param eq xmm3
  222.           if size@param = 4
  223.            if param eqtype byte 0 | param eqtype byte 0f
  224.         mov     eax, param
  225.         movd    xmm3, eax
  226.            else
  227.         movd    xmm3, param
  228.            end if
  229.           else
  230.            if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
  231.         mov     rax, param
  232.         movq    xmm3, rax
  233.            else
  234.         movq    xmm3, param
  235.            end if
  236.           end if
  237.          end if
  238.          if vararg@fastcall & ~ param eq r9
  239.         movq    r9, xmm3
  240.          end if
  241.         else if type@param eq addr
  242.          if ~ param eq r9
  243.         lea     r9, [param]
  244.          end if
  245.         else if size@param = 8
  246.          if ~ param eq r9
  247.         mov     r9, param
  248.          end if
  249.         else if size@param = 4
  250.          if ~ param eq r9d
  251.         mov     r9d, param
  252.          end if
  253.         else if size@param = 2
  254.          if ~ param eq r9w
  255.         mov     r9w, param
  256.          end if
  257.         else if size@param = 1
  258.          if ~ param eq r9b
  259.         mov     r9b, param
  260.          end if
  261.         end if
  262.        else
  263.          if type@param eq addr
  264.         lea     rax, [param]
  265.         mov     [rsp+(counter-1)*8], rax
  266.          else if param eqtype [0] | param eqtype byte [0]
  267.           if size@param = 8
  268.         mov     rax, param
  269.         mov     [rsp+(counter-1)*8], rax
  270.           else if size@param = 4
  271.         mov     eax, param
  272.         mov     [rsp+(counter-1)*8], eax
  273.           else if size@param = 2
  274.         mov     ax, param
  275.         mov     [rsp+(counter-1)*8], ax
  276.           else
  277.         mov     al, param
  278.         mov     [rsp+(counter-1)*8], al
  279.           end if
  280.          else if size@param = 8
  281.           virtual
  282.            origin = $
  283.         mov     rax, param
  284.            load opcode byte from origin+1
  285.           end virtual
  286.           if opcode = 0B8h
  287.         mov     rax, param
  288.         mov     [rsp+(counter-1)*8], rax
  289.           else
  290.         mov     qword [rsp+(counter-1)*8], param
  291.           end if
  292.          else if param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
  293.         movq    [rsp+(counter-1)*8], param
  294.          else
  295.         mov     [rsp+(counter-1)*8], param
  296.          end if
  297.        end if \}
  298.    common
  299.     argscount = counter
  300.         call    proc
  301.     if stackspace & ~defined current@frame
  302.         add     rsp, stackspace
  303.     end if }
  304.  
  305. macro proc [args]
  306.  { common
  307.     match name params, args>
  308.     \{ define@proc name,<params \} }
  309.  
  310. prologue@proc equ prologuedef
  311.  
  312. macro prologuedef procname,flag,parmbytes,localbytes,reglist
  313.  { local loc,fill,counter
  314.    loc = (localbytes+15) and (not 15)
  315.    parmbase@proc equ rbp+16
  316.    localbase@proc equ rbp-loc
  317.         push    rbp
  318.         mov     rbp, rsp
  319.    if loc+fill
  320.         sub     rsp, loc+fill
  321.    end if
  322.    counter = 0
  323.    irps reg, reglist \{ push reg
  324.                         counter = counter+1 \}
  325.    fill = 8*(counter and 1) }
  326.  
  327. epilogue@proc equ epiloguedef
  328.  
  329. macro epiloguedef procname,flag,parmbytes,localbytes,reglist
  330.  { irps reg, reglist \{ reverse pop reg \}
  331.         leave
  332.         retn    }
  333.  
  334. close@proc equ
  335.  
  336. macro define@proc name,statement
  337.  { local params,flag,regs,parmbytes,localbytes,current
  338.    if used name
  339.    name:
  340.    match =stdcall args, statement \{ params equ args
  341.                                      flag = 11b \}
  342.    match =stdcall, statement \{ params equ
  343.                                 flag = 11b \}
  344.    match =c args, statement \{ params equ args
  345.                                flag = 10001b \}
  346.    match =c, statement \{ params equ
  347.                           flag = 10001b \}
  348.    match =params, params \{ params equ statement
  349.                             flag = 10000b \}
  350.    match =uses reglist=,args, params \{ regs equ reglist
  351.                                         params equ args \}
  352.    match =regs =uses reglist, regs params \{ regs equ reglist
  353.                                              params equ \}
  354.    match =regs, regs \{ regs equ \}
  355.    match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
  356.    virtual at parmbase@proc
  357.    match =,args, params \{ defargs@proc args \}
  358.    match =args@proc args, args@proc params \{ defargs@proc args \}
  359.    parmbytes = $-(parmbase@proc)
  360.    end virtual
  361.    name # % = parmbytes/8
  362.    all@vars equ
  363.    current = 0
  364.    macro locals
  365.    \{ virtual at localbase@proc+current
  366.       macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
  367.       struc db [val] \\{ \common deflocal@proc .,db,val \\}
  368.       struc du [val] \\{ \common deflocal@proc .,du,val \\}
  369.       struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
  370.       struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
  371.       struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
  372.       struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
  373.       struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
  374.       struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
  375.       struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
  376.       struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
  377.       struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
  378.       struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
  379.       struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
  380.    macro endl
  381.    \{ purge label
  382.       restruc db,du,dw,dp,dd,dt,dq
  383.       restruc rb,rw,rp,rd,rt,rq
  384.       current = $-(localbase@proc)
  385.       end virtual \}
  386.    macro ret operand
  387.    \{ match any, operand \\{ retn operand \\}
  388.       match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
  389.    macro finish@proc
  390.    \{ localbytes = current
  391.       match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
  392.       end if \} }
  393.  
  394. macro defargs@proc [arg]
  395.  { common
  396.     if ~ arg eq
  397.    forward
  398.      local ..arg,current@arg
  399.      match argname:type, arg
  400.       \{ current@arg equ argname
  401.          label ..arg type
  402.          argname equ ..arg
  403.          if qqword eq type
  404.            dq ?,?,?,?
  405.          else if dqword eq type
  406.            dq ?,?
  407.          else if tbyte eq type
  408.            dq ?,?
  409.          else
  410.            dq ?
  411.          end if \}
  412.      match =current@arg,current@arg
  413.       \{ current@arg equ arg
  414.          arg equ ..arg
  415.          ..arg dq ? \}
  416.    common
  417.      args@proc equ current@arg
  418.    forward
  419.      restore current@arg
  420.    common
  421.     end if }
  422.  
  423. macro deflocal@proc name,def,[val] { name def val }
  424.  
  425. macro deflocal@proc name,def,[val]
  426.  { common
  427.     match vars, all@vars \{ all@vars equ all@vars, \}
  428.     all@vars equ all@vars name
  429.    forward
  430.     local ..var,..tmp
  431.     ..var def val
  432.     match =?, val \{ ..tmp equ \}
  433.     match any =?, val \{ ..tmp equ \}
  434.     match any (=?), val \{ ..tmp equ \}
  435.     match =label, def \{ ..tmp equ \}
  436.     match tmp : value, ..tmp : val
  437.      \{ tmp: end virtual
  438.         initlocal@proc ..var,def value
  439.         virtual at tmp\}
  440.    common
  441.     match first rest, ..var, \{ name equ first \} }
  442.  
  443. struc label type { label . type }
  444.  
  445. macro initlocal@proc name,def
  446.  { virtual at name
  447.     def
  448.     size@initlocal = $ - name
  449.    end virtual
  450.    position@initlocal = 0
  451.    while size@initlocal > position@initlocal
  452.     virtual at name
  453.      def
  454.      if size@initlocal - position@initlocal < 2
  455.       current@initlocal = 1
  456.       load byte@initlocal byte from name+position@initlocal
  457.      else if size@initlocal - position@initlocal < 4
  458.       current@initlocal = 2
  459.       load word@initlocal word from name+position@initlocal
  460.      else if size@initlocal - position@initlocal < 8
  461.       current@initlocal = 4
  462.       load dword@initlocal dword from name+position@initlocal
  463.      else
  464.       load qword@initlocal qword from name+position@initlocal
  465.       if ( qword@initlocal > 0 & qword@initlocal < 80000000h ) | ( qword@initlocal < 0 & qword@initlocal >= -80000000h )
  466.        current@initlocal = 8
  467.       else
  468.        current@initlocal = 4
  469.        dword@initlocal = qword@initlocal and 0FFFFFFFFh
  470.       end if
  471.      end if
  472.     end virtual
  473.     if current@initlocal = 1
  474.         mov     byte [name+position@initlocal], byte@initlocal
  475.     else if current@initlocal = 2
  476.         mov     word [name+position@initlocal], word@initlocal
  477.     else if current@initlocal = 4
  478.         mov     dword [name+position@initlocal], dword@initlocal
  479.     else
  480.         mov     qword [name+position@initlocal], qword@initlocal
  481.     end if
  482.     position@initlocal = position@initlocal + current@initlocal
  483.    end while }
  484.  
  485. macro endp
  486.  { purge ret,locals,endl
  487.    finish@proc
  488.    purge finish@proc
  489.    restore regs@proc
  490.    match all,args@proc \{ restore all \}
  491.    restore args@proc
  492.    match all,all@vars \{ restore all \} }
  493.  
  494. macro local [var]
  495.  { common
  496.     locals
  497.    forward done@local equ
  498.     match varname[count]:vartype, var
  499.     \{ match =BYTE, vartype \\{ varname rb count
  500.                                 restore done@local \\}
  501.        match =WORD, vartype \\{ varname rw count
  502.                                 restore done@local \\}
  503.        match =DWORD, vartype \\{ varname rd count
  504.                                  restore done@local \\}
  505.        match =PWORD, vartype \\{ varname rp count
  506.                                  restore done@local \\}
  507.        match =QWORD, vartype \\{ varname rq count
  508.                                  restore done@local \\}
  509.        match =TBYTE, vartype \\{ varname rt count
  510.                                  restore done@local \\}
  511.        match =DQWORD, vartype \\{ label varname dqword
  512.                                   rq count*2
  513.                                   restore done@local \\}
  514.        match =QQWORD, vartype \\{ label varname qqword
  515.                                   rq count*4
  516.                                   restore done@local \\}
  517.        match =XWORD, vartype \\{ label varname xword
  518.                                  rq count*2
  519.                                  restore done@local \\}
  520.        match =YWORD, vartype \\{ label varname yword
  521.                                  rq count*4
  522.                                  restore done@local \\}
  523.        match , done@local \\{ virtual
  524.                                varname vartype
  525.                               end virtual
  526.                               rb count*sizeof.\#vartype
  527.                               restore done@local \\} \}
  528.     match :varname:vartype, done@local:var
  529.     \{ match =BYTE, vartype \\{ varname db ?
  530.                                 restore done@local \\}
  531.        match =WORD, vartype \\{ varname dw ?
  532.                                 restore done@local \\}
  533.        match =DWORD, vartype \\{ varname dd ?
  534.                                  restore done@local \\}
  535.        match =PWORD, vartype \\{ varname dp ?
  536.                                  restore done@local \\}
  537.        match =QWORD, vartype \\{ varname dq ?
  538.                                  restore done@local \\}
  539.        match =TBYTE, vartype \\{ varname dt ?
  540.                                  restore done@local \\}
  541.        match =DQWORD, vartype \\{ label varname dqword
  542.                                   dq ?,?
  543.                                   restore done@local \\}
  544.        match =QQWORD, vartype \\{ label varname qqword
  545.                                   dq ?,?,?,?
  546.                                   restore done@local \\}
  547.        match =XWORD, vartype \\{ label varname xword
  548.                                  dq ?,?
  549.                                  restore done@local \\}
  550.        match =YWORD, vartype \\{ label varname yword
  551.                                  dq ?,?,?,?
  552.                                  restore done@local \\}
  553.        match , done@local \\{ varname vartype
  554.                               restore done@local \\} \}
  555.     match ,done@local
  556.     \{ var
  557.        restore done@local \}
  558.    common
  559.     endl }
  560.  
  561. macro frame
  562.  { local size,current
  563.    if size
  564.         sub     rsp, size
  565.    end if
  566.    current = 0
  567.    current@frame equ current
  568.    size@frame equ size }
  569.  
  570. macro endf
  571.  { size@frame = current@frame
  572.    if size@frame
  573.         add     rsp, size@frame
  574.    end if
  575.    restore size@frame,current@frame }
  576.  
  577. macro static_rsp_prologue procname,flag,parmbytes,localbytes,reglist
  578.  { local counter,loc,frame,current
  579.    counter = 0
  580.    irps reg, reglist \{ push reg
  581.                         counter = counter+1 \}
  582.    loc = (localbytes+7) and (not 7)
  583.    if frame & (counter+loc shr 3+1) and 1
  584.     loc = loc + 8
  585.    end if
  586.    framebytes@proc equ frame+loc
  587.    if framebytes@proc
  588.         sub     rsp, framebytes@proc
  589.    end if
  590.    localbase@proc equ rsp+frame
  591.    regsbase@proc equ rsp+frame+loc
  592.    parmbase@proc equ rsp+frame+loc+counter*8+8
  593.    current = 0
  594.    current@frame equ current
  595.    size@frame equ frame }
  596.  
  597. macro static_rsp_epilogue procname,flag,parmbytes,localbytes,reglist
  598.  { if framebytes@proc
  599.         add     rsp, framebytes@proc
  600.    end if
  601.    irps reg, reglist \{ reverse pop reg \}
  602.         retn    }
  603.  
  604. macro static_rsp_close procname,flag,parmbytes,localbytes,reglist
  605.  { size@frame = current@frame
  606.    restore size@frame,current@frame }
  607.  
  608.         stdcall fix fastcall
  609.  
  610. macro cinvoke proc,[arg]
  611.  { common ccall [proc],arg }
  612.  
  613. macro ccall proc,[arg]
  614.  { common vararg@fastcall = 1
  615.           fastcall proc,arg
  616.           vararg@fastcall = 0 }
  617.  
  618. vararg@fastcall = 0
  619.