summaryrefslogtreecommitdiff
path: root/vm/mterp/x86/OP_EXECUTE_INLINE.S
blob: 1eca6e20a19587f4b222299e962e88ea56585728 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
%verify "executed"
%verify "exception handled"
    /*
     * Execute a "native inline" instruction.
     *
     * We will be calling through a function table:
     *
     * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
     *
     */
    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
    GET_GLUE(%ecx)
    EXPORT_PC()
    movzwl    2(rPC),%eax               # eax<- BBBB
    leal      offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
    movl      %ecx,OUT_ARG4(%esp)
    sarl      $$12,rINST_FULL           # rINST_FULL<- arg count (0-4)
    SPILL(rPC)
    call      .L${opcode}_continue      # make call; will return after
    UNSPILL(rPC)
    testl     %eax,%eax                 # successful?
    FETCH_INST_WORD(3)
    je        common_exceptionThrown    # no, handle exception
    ADVANCE_PC(3)
    GOTO_NEXT
%break

.L${opcode}_continue:
    /*
     * Extract args, call function.
     *  ecx = #of args (0-4)
     *  eax = call index
     *  @esp = return addr
     *  esp is -4 from normal
     *
     *  Go ahead and load all 4 args, even if not used.
     */
    movzwl    4(rPC),rPC

    movl      $$0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $$4,rPC
    movl      %ecx,4+OUT_ARG0(%esp)

    movl      $$0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $$4,rPC
    movl      %ecx,4+OUT_ARG1(%esp)

    movl      $$0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $$4,rPC
    movl      %ecx,4+OUT_ARG2(%esp)

    movl      $$0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $$4,rPC
    movl      %ecx,4+OUT_ARG3(%esp)

    sall      $$4,%eax      # index *= sizeof(table entry)
    jmp       *gDvmInlineOpsTable(%eax)
    # will return to caller of .L${opcode}_continue