mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-30 21:02:27 +00:00 
			
		
		
		
	 e4023c8e02
			
		
	
	
		e4023c8e02
		
			
		
	
	
	
	
		
			
			Enable RISCV AOT support, the supported ABIs are LP64 and LP64D for riscv64, ILP32 and ILP32D for riscv32.
For wamrc:
    use --target=riscv64/riscv32 to specify the target arch of output AOT file,
    use --target-abi=lp64d/lp64/ilp32d/ilp32 to specify the target ABI,
    if --target-abi isn't specified, by default lp64d is used for riscv64, and ilp32d is used for riscv32.
Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
Co-authored-by: wenyongh <wenyong.huang@intel.com>
		
	
			
		
			
				
	
	
		
			149 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2019 Intel Corporation.  All rights reserved.
 | |
|  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * The float abi macros used bellow are from risc-v c api:
 | |
|  * https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #if defined(__riscv_float_abi_soft)
 | |
| #define RV_FPREG_SIZE    0
 | |
| #elif defined(__riscv_float_abi_single)
 | |
| #define RV_OP_LOADFPREG  flw
 | |
| #define RV_OP_STROEFPREG fsw
 | |
| #define RV_FPREG_SIZE    4
 | |
| #elif defined(__riscv_float_abi_double)
 | |
| #define RV_OP_LOADFPREG  fld
 | |
| #define RV_OP_STROEFPREG fsd
 | |
| #define RV_FPREG_SIZE    8
 | |
| #endif
 | |
| 
 | |
| #if __riscv_xlen == 32
 | |
| #define RV_OP_LOADREG  lw
 | |
| #define RV_OP_STOREREG sw
 | |
| #define RV_REG_SIZE    4
 | |
| #define RV_REG_SHIFT   2
 | |
| #define RV_FP_OFFSET   (8 * RV_REG_SIZE)
 | |
| #define RV_INT_OFFSET  0
 | |
| #else
 | |
| #define RV_OP_LOADREG  ld
 | |
| #define RV_OP_STOREREG sd
 | |
| #define RV_REG_SIZE    8
 | |
| #define RV_REG_SHIFT   3
 | |
| #define RV_FP_OFFSET   0
 | |
| #define RV_INT_OFFSET  (8 * RV_FPREG_SIZE)
 | |
| #endif
 | |
| 
 | |
|         .text
 | |
|         .align  2
 | |
| #ifndef BH_PLATFORM_DARWIN
 | |
|         .globl invokeNative
 | |
|         .type  invokeNative, function
 | |
| invokeNative:
 | |
| #else
 | |
|         .globl _invokeNative
 | |
| _invokeNative:
 | |
| #endif /* end of BH_PLATFORM_DARWIN */
 | |
| 
 | |
| /*
 | |
|  * Arguments passed in:
 | |
|  *
 | |
|  * a0 function ptr
 | |
|  * a1 argv
 | |
|  * a2 nstacks
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * sp (stack pointer)
 | |
|  *    |- sd/sw to store 64/32-bit values from register to memory
 | |
|  *    |- ld/lw to load from stack to register
 | |
|  * fp/s0 (frame pointer)
 | |
|  * a0-a7 (8 integer arguments)
 | |
|  *    |- sd/sw to store
 | |
|  *    |- ld/lw to load
 | |
|  * fa0-a7 (8 float arguments)
 | |
|  *    |- fsd/fsw to store
 | |
|  *    |- fld/fsw to load
 | |
|  * t0-t6 (temporaries regisgers)
 | |
|  *    |- caller saved
 | |
|  */
 | |
| 
 | |
|         /* reserve space on stack to save return address and frame pointer */
 | |
|         addi             sp, sp, - 2 * RV_REG_SIZE
 | |
|         RV_OP_STOREREG   fp, 0 * RV_REG_SIZE(sp)    /* save frame pointer */
 | |
|         RV_OP_STOREREG   ra, 1 * RV_REG_SIZE(sp)    /* save return address */
 | |
| 
 | |
|         mv               fp, sp                     /* set frame pointer to bottom of fixed frame */
 | |
| 
 | |
|         /* save function ptr, argv & nstacks */
 | |
|         mv               t0, a0                     /* t0 = function ptr */
 | |
|         mv               t1, a1                     /* t1 = argv array address */
 | |
|         mv               t2, a2                     /* t2 = nstack */
 | |
| 
 | |
| #ifndef __riscv_float_abi_soft
 | |
|         /* fill in fa0-7 float-registers*/
 | |
|         RV_OP_LOADFPREG  fa0, RV_FP_OFFSET + 0 * RV_FPREG_SIZE(t1) /* fa0 */
 | |
|         RV_OP_LOADFPREG  fa1, RV_FP_OFFSET + 1 * RV_FPREG_SIZE(t1) /* fa1 */
 | |
|         RV_OP_LOADFPREG  fa2, RV_FP_OFFSET + 2 * RV_FPREG_SIZE(t1) /* fa2 */
 | |
|         RV_OP_LOADFPREG  fa3, RV_FP_OFFSET + 3 * RV_FPREG_SIZE(t1) /* fa3 */
 | |
|         RV_OP_LOADFPREG  fa4, RV_FP_OFFSET + 4 * RV_FPREG_SIZE(t1) /* fa4 */
 | |
|         RV_OP_LOADFPREG  fa5, RV_FP_OFFSET + 5 * RV_FPREG_SIZE(t1) /* fa5 */
 | |
|         RV_OP_LOADFPREG  fa6, RV_FP_OFFSET + 6 * RV_FPREG_SIZE(t1) /* fa6 */
 | |
|         RV_OP_LOADFPREG  fa7, RV_FP_OFFSET + 7 * RV_FPREG_SIZE(t1) /* fa7 */
 | |
| #endif
 | |
| 
 | |
|         /* fill in a0-7 integer-registers*/
 | |
|         RV_OP_LOADREG    a0, RV_INT_OFFSET + 0 * RV_REG_SIZE(t1)    /* a0 */
 | |
|         RV_OP_LOADREG    a1, RV_INT_OFFSET + 1 * RV_REG_SIZE(t1)    /* a1 */
 | |
|         RV_OP_LOADREG    a2, RV_INT_OFFSET + 2 * RV_REG_SIZE(t1)    /* a2 */
 | |
|         RV_OP_LOADREG    a3, RV_INT_OFFSET + 3 * RV_REG_SIZE(t1)    /* a3 */
 | |
|         RV_OP_LOADREG    a4, RV_INT_OFFSET + 4 * RV_REG_SIZE(t1)    /* a4 */
 | |
|         RV_OP_LOADREG    a5, RV_INT_OFFSET + 5 * RV_REG_SIZE(t1)    /* a5 */
 | |
|         RV_OP_LOADREG    a6, RV_INT_OFFSET + 6 * RV_REG_SIZE(t1)    /* a6 */
 | |
|         RV_OP_LOADREG    a7, RV_INT_OFFSET + 7 * RV_REG_SIZE(t1)    /* a7 */
 | |
| 
 | |
|         /* t1 points to stack args */
 | |
| 
 | |
|         /* RV_FPREG_SIZE is zero when __riscv_float_abi_soft defined */
 | |
|         addi             t1, t1, RV_REG_SIZE * 8 + RV_FPREG_SIZE * 8
 | |
| 
 | |
|         /* directly call the function if no args in stack,
 | |
|            x0 always holds 0 */
 | |
|         beq              t2, x0, call_func
 | |
| 
 | |
|         /* reserve enough stack space for function arguments */
 | |
|         sll              t3, t2, RV_REG_SHIFT       /* shift left 3 bits. t3 = n_stacks * 8 */
 | |
|         sub              sp, sp, t3
 | |
| 
 | |
|         /* make 16-byte aligned */
 | |
|         li               t3, 15
 | |
|         not              t3, t3
 | |
|         and              sp, sp, t3
 | |
| 
 | |
|         /* save sp in t4 register */
 | |
|         mv               t4, sp
 | |
| 
 | |
|         /* copy left arguments from caller stack to own frame stack */
 | |
| loop_stack_args:
 | |
|         beq              t2, x0, call_func
 | |
|         RV_OP_LOADREG    t5, 0(t1)                  /* load stack argument, t5 = argv[i] */
 | |
|         RV_OP_STOREREG   t5, 0(t4)                  /* store t5 to reseved stack, sp[j] = t5 */
 | |
|         addi             t1, t1, RV_REG_SIZE        /* move to next stack argument */
 | |
|         addi             t4, t4, RV_REG_SIZE        /* move to next stack pointer */
 | |
|         addi             t2, t2, -1                 /* decrease t2 every loop, nstacks = nstacks -1 */
 | |
|         j loop_stack_args
 | |
| 
 | |
| call_func:
 | |
|         jalr             t0
 | |
| 
 | |
|         /* restore registers pushed in stack or saved in another register */
 | |
| return:
 | |
|         mv               sp, fp                     /* restore sp saved in fp before function call */
 | |
|         RV_OP_LOADREG    fp, 0 * RV_REG_SIZE(sp)    /* load previous frame poniter to fp register */
 | |
|         RV_OP_LOADREG    ra, 1 * RV_REG_SIZE(sp)    /* load previous return address to ra register */
 | |
|         addi             sp, sp, 2 * RV_REG_SIZE    /* pop frame, restore sp */
 | |
|         jr               ra
 |