📄 jit-arm.def
字号:
/* * jit-arm.def * ARM instruction definition. * * Copyright (c) 1996, 1997, 1999 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#ifdef KAFFE_VMDEBUGint jit_debug;#define debug(x) (jit_debug ? dprintf("%x:\t", CODEPC), dprintf x : 0)#else#define debug(x)#endif#include "icode.h"/* * The information in this file was extracted from the ARM * Architecture Reference, Document ARM DDI 0100A. * * The page and section numbers correspond to this document. */#define R0 0 /* arg0 + int return */#define R1 1 /* arg2 */#define R2 2 /* arg3 */#define R3 3 /* arg4 */#define R4 4#define R5 5#define R6 6#define R7 7#define R8 8#define R9 9#define R10 10#define R11 11#define R12 12#define R13 13#define R14 14#define R15 15#define F0 0 /* float return */#define F1 1#define F2 2#define F3 3#define F4 4#define F5 5#define F6 6#define F7 7#define Reg_F0 (R15 + 1 + F0)#define Reg_F1 (R15 + 1 + F1)#define Reg_F2 (R15 + 1 + F2)#define Reg_F3 (R15 + 1 + F3)#define Reg_F4 (R15 + 1 + F4)#define Reg_F5 (R15 + 1 + F5)#define Reg_F6 (R15 + 1 + F6)#define Reg_F7 (R15 + 1 + F7)/* * The bits for each register - used for pushing and popping. */#define BR0 (1<<R0)#define BR1 (1<<R1)#define BR2 (1<<R2)#define BR3 (1<<R3)#define BR4 (1<<R4)#define BR5 (1<<R5)#define BR6 (1<<R6)#define BR7 (1<<R7)#define BR8 (1<<R8)#define BR9 (1<<R9)#define BR10 (1<<R10)#define BR11 (1<<R11)#define BR12 (1<<R12)#define BR13 (1<<R13)#define BR14 (1<<R14)#define BR15 (1<<R15)/* * Some register aliases. */#define FP R11#define IP R12#define SP R13#define LR R14#define PC R15#define BFP BR11#define BIP BR12#define BSP BR13#define BLR BR14#define BPC BR15/* * Define condition codes, see 3.2 pg 3-3 */#define CC_EQ ( 0 << 28) /* Equal */#define CC_NE ( 1 << 28) /* Not Equal */#define CC_CS ( 2 << 28) /* Carry Set/Unsigned Higher or Same */#define CC_CC ( 3 << 28) /* Carry Clear/Unsigned Lower */#define CC_MI ( 4 << 28) /* Minus/Negative */#define CC_PL ( 5 << 28) /* Plus/Positive or Zero */#define CC_VS ( 6 << 28) /* Overflow */#define CC_VC ( 7 << 28) /* No Overflow */#define CC_HI ( 8 << 28) /* Unsigned Higher */#define CC_LS ( 9 << 28) /* Unsigned Lower or Same */#define CC_GE (10 << 28) /* Signed Greater Than or Equal */#define CC_LT (11 << 28) /* Signed Less Than */#define CC_GT (12 << 28) /* Signed Greater Than */#define CC_LE (13 << 28) /* Signed Less Than or Equal */#define CC_AL (14 << 28) /* Always (unconditional) */#define CC_NV (15 << 28) /* Never *//* * Selection of operand modes, see 3.6.2 pg 3-12 */#define ALU_OP_REG (0 << 25) /* operand is in register */#define ALU_OP_IMMED (1 << 25) /* operand is 8bit+shifted immediate *//* * Define ALU operations. */#define ALU_SETCC ( 1 << 20) /* Set condition codes for this op */#define ALU_AND ( 0 << 21) /* And */#define ALU_EOR ( 1 << 21) /* Exclusive OR */#define ALU_SUB ( 2 << 21) /* Subtract */#define ALU_RSB ( 3 << 21) /* Reverse subtract */#define ALU_ADD ( 4 << 21) /* Add */#define ALU_ADC ( 5 << 21) /* Add carry */#define ALU_SBC ( 6 << 21) /* Subtract carry */#define ALU_RSC ( 7 << 21) /* Reverser subtract carry */#define ALU_TST ( 8 << 21) /* Test (uses AND) */#define ALU_TEQ ( 9 << 21) /* Test Equivalence (uses EOR) */#define ALU_CMP (10 << 21) /* Compare */#define ALU_CMPN (11 << 21) /* Compared negated */#define ALU_ORR (12 << 21) /* Logical inclusive OR */#define ALU_MOV (13 << 21) /* Move */#define ALU_BIC (14 << 21) /* Bit Clear */#define ALU_MVN (15 << 21) /* Move Not *//* * Define Shift operations. * The "C" form use an immediate constant as opposed to a register. * See 3.6.2 pg 3-12 and up. */#define SFT_LSLC ( 0 << 8)#define SFT_LSL ( 1 << 8)#define SFT_LSRC ( 2 << 8)#define SFT_LSR ( 3 << 8)#define SFT_ASRC ( 4 << 8)#define SFT_ASR ( 5 << 8)#define SFT_RORC ( 6 << 8)#define SFT_ROR ( 7 << 8)/* * Memory operations. *//* * A. Load and Store Word or Unsigned Byte Addressing Modes 3.11 pg 3-55 * B. Load and Store Halfword or Load Signed Byte Addr. Modes 3.13 pg 3-76 */#define MEM_LOAD 0x00100000 /* load or store */#define MEM_STORE 0x00000000/* NB: A only */#define MEM_UBYTE 0x00400000 /* unsigned byte or word */#define MEM_WORD 0x00000000#define MEM_ADDOFF 0x00800000 /* add or subtract offset */#define MEM_SUBOFF 0x00000000#define MEM_PREIDX 0x01000000 /* pre-indexing or post-indexing */#define MEM_POSTIDX 0x00000000#define MEM_WRTBCK 0x00200000 /* update register with addr or not *//* NB: B. only */#define MEM_SGN 0x00000040 /* signed or unsigned halfword access */#define MEM_USGN 0x00000000/* NB: B. only */#define MEM_HALF 0x00000020 /* halfword or byte */#define MEM_BYTE 0x00000000/* * Multiple load/store operations. See 3.15 pg 3-88 */#define MULTI_STORE 0x00000000#define MULTI_LOAD 0x00100000#define MULTI_DA 0x00000000 /* Decrement After */#define MULTI_DB 0x01000000 /* Decrement Before */#define MULTI_IA 0x00800000 /* Increment After */#define MULTI_IB 0x01800000 /* Increment Before *//* * Multiply operations. * Not implemented in Architecture Version 1 */#define MUL_MUL 0x00000000 /* Multiply */#define MUL_MULLADD 0x00200000 /* Multiply Accumulate *//* * Floating point operations. *//* * Dyadic operations */#define FLT_ADF 0x00000000#define FLT_MUF 0x00100000#define FLT_SUF 0x00200000#define FLT_RSF 0x00300000#define FLT_DVF 0x00400000#define FLT_RDF 0x00500000#define FLT_POW 0x00600000#define FLT_RPW 0x00700000#define FLT_RMF 0x00800000 /* remainder */#define FLT_FML 0x00900000 /* fast multiply */#define FLT_FDV 0x00A00000 /* fast divide */#define FLT_FRD 0x00B00000 /* reverse fast divide */#define FLT_POL 0x00C00000 /* polar arc (arctan2) */#define FLT_MVF 0x00008000 /* Fd := Fm */#define FLT_MNF 0x00108000 /* Fd := -Fm */#define FLT_RND 0x00308000 /* Fd := integer value of Fm (NOTE: float-to-float operation!) *//* * Floating point coprocessor register transfer */#define FLT_FLT 0x00000110 /* Fn := Rd */#define FLT_FIX 0x00100110 /* Rd := Fm */#define FLT_CMP 0x0090F110 /* Compare Fn, Fm */#define FLT_CMPE 0x00D0F110 /* Compare Fn, Fm *//* * Floating point precision (arith). */#define FLT_PREC_SINGLE 0x00000000#define FLT_PREC_DOUBLE 0x00000080#define FLT_PREC_EXTEND 0x00080000/* * Floating point precision (load/store). * Notice that we also include the 0x100 to force this * to be a floating point Ld/St. */#define FLT_MPREC_SINGLE 0x00000000#define FLT_MPREC_DOUBLE 0x00008000#define FLT_MPREC_EXTEND 0x00400000/* * For ld/st of single values */#define FLT_MEMOP_SINGLE 0x00000100/* * for ld/st of multiple values */#define FLT_MEMOP_MULTIPLE 0x00000200/* * Floating point rounding modes */#define FLT_RND_NEAREST 0x00000000#define FLT_RND_PLUSINF 0x00000020#define FLT_RND_MININF 0x00000040#define FLT_RND_ZERO 0x00000060/* * Define general instruction forms. * * We use the following conventions: * NB: Rd is called DST * Rn is called SRC1 * Rm is called SRC2 * * A constant is encoded as an 8-bit immediate IMM shifted left by * a shift IMMSFT. *//* register := register x register */#define op_rrr(CC,ALU,SFT,SFTVAL,DST,SRC1,SRC2) \ LOUT(0x00000000|(CC)|(ALU)|(SFT)|((SFTVAL)<<7)|((DST)<<12)|((SRC1)<<16)|(SRC2))/* register := register x constant */#define op_rrc(CC,ALU,DST,SRC1,IMM,IMMSFT) \ LOUT(0x02000000|(CC)|(ALU)|((DST)<<12)|((SRC1)<<16)|((IMMSFT)<<8)|((IMM)&0xFF))/* register := register x register */#define op_muladd_rrr(CC,MULOP,DST,SRC1,SRC2) \ LOUT(0x00000090|(CC)|(MULOP)|((DST)<<16)|(SRC1)|((SRC2)<<8))/* Not used or debugged: see 3.8.5#define op_muladd_rrrr(CC,MULOP,DST,SRC1,SRC2,SRC3) \ LOUT(0x00200090|(CC)|(MULOP)|((DST)<<16)|(SRC1)|((SRC2)<<8)|((SRC3)<<12))*/#define op_branch(CC,DST) \ LOUT(0x0A000000|(CC)|(((DST)>>2)&0x00FFFFFF))#define op_branch_linked(CC,DST) \ LOUT(0x0B000000|(CC)|(((DST)>>2)&0x00FFFFFF))/* Load/Store Word or Unsigned Byte, see 3.11 * ldr REG, [IDX, +/- IDX2] or * str REG, [IDX, +/- IDX2] */#define op_mem_rrr(CC,MEM,SFT,SFTVAL,REG,IDX,IDX2) \ LOUT(0x04000000|(CC)|(MEM)|(SFT)|((SFTVAL)<<7)|((IDX)<<16)|((REG)<<12)|(IDX2))/* Load/Store Word or Unsigned Byte, see 3.11 * ldr REG, [IDX +/- OFF] * str REG, [IDX +/- OFF] */#define op_mem_rrc(CC,MEM,REG,IDX,OFF) \ LOUT(0x04000000|(CC)|(MEM)|((REG)<<12)|((IDX)<<16)|((OFF)&0xFFF))/* Load and Store Halfword or Load Signed Byte with an immediate 8-bit offset * ldr{h|sh|sb} REG, [IDX +/- OFF] * str{h|sh|sb} REG, [IDX +/- OFF] * * See 3.13 pg 3-76 * NB: you cannot use this instruction to store a byte. */#define op_mem_hb_rrc(CC,MEM,SGN,SIZE,REG,IDX,OFF) \ LOUT(0x00400090|(CC)|(MEM)|(SGN)|(SIZE)|((IDX)<<16)|((REG)<<12)|((OFF)&0xF)|(((OFF)&0xF0)<<4))#define op_f_rrr(CC,FALU,PREC,RND,DST,SRC1,SRC2) \ LOUT(0x0E000100|(CC)|(FALU)|(PREC)|(RND)|(((DST)&0x07)<<12)|(((SRC1)&0x07)<<16)|((SRC2)&0x07))#define op_f_rrc(CC,FALU,PREC,RND,DST,SRC1,SRC2) \ LOUT(0x0E000100|(CC)|(FALU)|(PREC)|(RND)|(((DST)&0x07)<<12)|(((SRC1)&0x07)<<16)|(SRC2))/* * The FLT instruction has a non-obvious encoding in that the * "destination" register is really the source integer register */#define op_cvt_i2f(F,R) op_f_rrr(CC_AL, FLT_FLT, FLT_PREC_SINGLE, FLT_RND_ZERO, R, F, 0)#define op_cvt_i2d(F,R) op_f_rrr(CC_AL, FLT_FLT, FLT_PREC_DOUBLE, FLT_RND_ZERO, R, F, 0)#define op_cvt_f2i(R,F) op_f_rrr(CC_AL, FLT_FIX, FLT_PREC_SINGLE, FLT_RND_ZERO, R, 0, F)#define op_cvt_d2i(R,F) op_f_rrr(CC_AL, FLT_FIX, FLT_PREC_DOUBLE, FLT_RND_ZERO, R, 0, F)/* * Floating point memory operation */#define op_fmem_rrc(CC,MEM,MPREC,REG,IDX,OFF) \ LOUT(0x0C000100|(CC)|(MEM)|(MPREC)|(((REG)&0x07)<<12)|((IDX)<<16)|((OFF)&0xFF))#define op_push_m(T,BITS) \ LOUT(0x08000000|CC_AL|MULTI_STORE|MULTI_DB|((T)<<16)|(BITS))/* * Redefine push to use auto index & writeback (like C calling convention) */#define op_push_prologue(T,BITS) \ LOUT(0x08000000|CC_AL|MULTI_STORE|MULTI_DB|MEM_WRTBCK|((T)<<16)|(BITS))/* * Note that this generates the same opcode as used in the normal C * linkage convention. The T register should always be FP for * this particular usage. */#define op_pop_epilogue(T,BITS) \ LOUT(0x08000000|CC_AL|MULTI_LOAD|MULTI_DB|((T)<<16)|(BITS))/* * A pop that decrements the SP. This would normally match an op_push * (which used a MULTI_DB). Note that it's different than the normal * epilogue pop. */#define op_pop_m(T,BITS) \ LOUT(0x08000000|CC_AL| MULTI_LOAD | MULTI_IA | MEM_WRTBCK |((T)<<16)|(BITS))/* * Define the instruction macros for later use. * * NB: We must use ALU_SETCC to set the condition code as the result of * this operation. We obviously need this for the CMP operation (in fact, * Dirk says the processor will SIGILL us otherwise) * * We must also set it for op_add and op_sub because we need the carry * to construct a 64-bit add and sub via add/adc. */#define op_mov(T,F) op_rrr(CC_AL,ALU_MOV,SFT_LSLC,0,T,0,F)/* NB: this will rotate right V by S bits before using it! */#define op_mov_c(T,V,S) op_rrc(CC_AL,ALU_MOV,T,0,V,((S)>>1))#define op_add(T,F1,F2) op_rrr(CC_AL,ALU_ADD | ALU_SETCC,SFT_LSLC,0,T,F1,F2)#define op_add_const(T,F1,I8) op_rrr(CC_AL,ALU_ADD | ALU_SETCC | ALU_OP_IMMED, SFT_LSLC, 0, T, F1, I8 & 0xff)#define op_adc(T,F1,F2) op_rrr(CC_AL,ALU_ADC,SFT_LSLC,0,T,F1,F2)#define op_sub(T,F1,F2) op_rrr(CC_AL,ALU_SUB | ALU_SETCC,SFT_LSLC,0,T,F1,F2)#define op_sub_const(T,F1,I8) op_rrr(CC_AL,ALU_SUB | ALU_SETCC | ALU_OP_IMMED, SFT_LSLC, 0, T, F1, I8 & 0xff)#define op_sbc(T,F1,F2) op_rrr(CC_AL,ALU_SBC,SFT_LSLC,0,T,F1,F2)#define op_add_c(T,F,V,S) op_rrc(CC_AL,ALU_ADD,T,F,V,((S)>>1))#define op_sub_c(T,F,V,S) op_rrc(CC_AL,ALU_SUB,T,F,V,((S)>>1))#define op_and(T,F1,F2) op_rrr(CC_AL,ALU_AND,SFT_LSLC,0,T,F1,F2)#define op_and_const(T,F1,I8) op_rrr(CC_AL,ALU_AND | ALU_OP_IMMED, SFT_LSLC, 0, T, F1, I8 & 0xff)#define op_or(T,F1,F2) op_rrr(CC_AL,ALU_ORR,SFT_LSLC,0,T,F1,F2)#define op_or_const(T,F1,I8) op_rrr(CC_AL,ALU_OR | ALU_OP_IMMED, SFT_LSLC, 0, T, F1, I8 & 0xff)#define op_eor(T,F1,F2) op_rrr(CC_AL,ALU_EOR,SFT_LSLC,0,T,F1,F2)#define op_eor_const(T,F1,I8) op_rrr(CC_AL,ALU_EOR | ALU_OP_IMMED, SFT_LSLC, 0, T, F1, I8 & 0xff)/* * * These use the register-specified shift forms. * * F2 = register containing number of locations to shift * F1 = source register * T = destination register */#define op_lshl(T,F1,F2) op_rrr(CC_AL,ALU_MOV,0,0,T,0,((F2) << 8) | 0x10 | F1)#define op_lshr(T,F1,F2) op_rrr(CC_AL,ALU_MOV,0,0,T,0,((F2) << 8) | 0x30 | F1)#define op_ashr(T,F1,F2) op_rrr(CC_AL,ALU_MOV,0,0,T,0,((F2) << 8) | 0x50 | F1)#define op_mul(T,F1,F2) op_muladd_rrr(CC_AL,MUL_MUL,T,F1,F2)#define op_not(T,F) op_rrr(CC_AL,ALU_MVN,SFT_LSLC,0,T,0,F)#define op_cmp(F1,F2) op_rrr(CC_AL,ALU_CMP | ALU_SETCC,SFT_LSLC,0,0,F1,F2)#define op_cmp_const(F1,I8) op_rrr(CC_AL,ALU_CMP | ALU_SETCC | ALU_OP_IMMED,SFT_LSLC,0,0,F1,I8 & 0xff)#define op_fmov(T,F) op_f_rrr(CC_AL,FLT_MVF,FLT_PREC_SINGLE,FLT_RND_ZERO,T,0,F)#define op_fmov_const(T,F) op_f_rrc(CC_AL,FLT_MVF,FLT_PREC_SINGLE,FLT_RND_ZERO,T,0,F)#define op_fmovl(T,F) op_f_rrr(CC_AL,FLT_MVF,FLT_PREC_DOUBLE,FLT_RND_ZERO,T,0,F)#define op_fmovl_const(T,F) op_f_rrc(CC_AL,FLT_MVF,FLT_PREC_DOUBLE,FLT_RND_ZERO,T,0,F)#define op_fadd(T,F1,F2) op_f_rrr(CC_AL,FLT_ADF,FLT_PREC_SINGLE,FLT_RND_ZERO,T,F1,F2)#define op_fsub(T,F1,F2) op_f_rrr(CC_AL,FLT_SUF,FLT_PREC_SINGLE,FLT_RND_ZERO,T,F1,F2)#define op_fmul(T,F1,F2) op_f_rrr(CC_AL,FLT_MUF,FLT_PREC_SINGLE,FLT_RND_ZERO,T,F1,F2)#define op_fdiv(T,F1,F2) op_f_rrr(CC_AL,FLT_DVF,FLT_PREC_SINGLE,FLT_RND_ZERO,T,F1,F2)#define op_faddl(T,F1,F2) op_f_rrr(CC_AL,FLT_ADF,FLT_PREC_DOUBLE,FLT_RND_ZERO,T,F1,F2)#define op_fsubl(T,F1,F2) op_f_rrr(CC_AL,FLT_SUF,FLT_PREC_DOUBLE,FLT_RND_ZERO,T,F1,F2)#define op_fmull(T,F1,F2) op_f_rrr(CC_AL,FLT_MUF,FLT_PREC_DOUBLE,FLT_RND_ZERO,T,F1,F2)#define op_fdivl(T,F1,F2) op_f_rrr(CC_AL,FLT_DVF,FLT_PREC_DOUBLE,FLT_RND_ZERO,T,F1,F2)/* * fixz == float->int or double -> int */#define op_fixz(R,F) op_f_rrr(CC_AL, FLT_ADF, FLT_PREC_SINGLE, FLT_RND_FTOI, R, F, 0)/* * Floating compare - we only use CMPE. Precision doesn't matter */#define op_fcmp(Fn,Fm) op_f_rrr(CC_AL, FLT_CMPE, FLT_PREC_SINGLE, FLT_RND_NEAREST, 0xf, Fn, Fm)/* * We only encode positive offset constants. * If the offset is negative, we negate it and subtract it. */#define op_load_offset(R,A,O) \ if ((O) < 0) \ op_mem_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,R,A,-(O)); \ else \ op_mem_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,R,A,O)#define op_load_ub_offset(R,A,O) \ if ((O) < 0) \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,MEM_USGN,MEM_BYTE,R,A,-(O)); \ else \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,MEM_USGN,MEM_BYTE,R,A,O)#define op_load_uh_offset(R,A,O) \ if ((O) < 0) \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,MEM_USGN,MEM_HALF,R,A,-(O)); \ else \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,MEM_USGN,MEM_HALF,R,A,O)#define op_load_sb_offset(R,A,O) \ if ((O) < 0) \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,MEM_SGN,MEM_BYTE,R,A,-(O)); \ else \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,MEM_SGN,MEM_BYTE,R,A,O)#define op_load_sh_offset(R,A,O) \ if ((O) < 0) \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,MEM_SGN,MEM_HALF,R,A,-(O)); \ else \ op_mem_hb_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,MEM_SGN,MEM_HALF,R,A,O)/*************************************************************************** * * NOTE: Floating loads and stores treat the offset as a *word* index, * not a BYTE index as in the regular ld/st. We don't compensate * for this here, we do it in the individual memory operations. * For this reason, we should have the rangecheck actually be * larger than an I8 rangecheck, but I haven't done that yet. * ***************************************************************************/#define op_fload_offset(R,A,O) \ if ((O) < 0) \ op_fmem_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,FLT_MPREC_SINGLE,R,A,-(O)); \ else \ op_fmem_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,FLT_MPREC_SINGLE,R,A,O)#define op_floadl_offset(R,A,O) \ if ((O) < 0) \ op_fmem_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_SUBOFF,FLT_MPREC_DOUBLE,R,A,-(O)); \ else \ op_fmem_rrc(CC_AL,MEM_LOAD|MEM_PREIDX|MEM_ADDOFF,FLT_MPREC_DOUBLE,R,A,O)#define op_store_offset(R,A,O) \ if ((O) < 0) \ op_mem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_SUBOFF,R,A,-(O)); \ else \ op_mem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_ADDOFF,R,A,O)/* Do not use op_mem_hb_rrc here because that does not store bytes */#define op_store_b_offset(R,A,O) \ if ((O) < 0) \ op_mem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_SUBOFF|MEM_UBYTE,R,A,-(O)); \ else \ op_mem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_ADDOFF|MEM_UBYTE,R,A,O)#define op_store_h_offset(R,A,O) \ if ((O) < 0) \ op_mem_hb_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_SUBOFF,MEM_USGN,MEM_HALF,R,A,-(O)); \ else \ op_mem_hb_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_ADDOFF,MEM_USGN,MEM_HALF,R,A,O)#define op_fstore_offset(R,A,O) \ if ((O) < 0) \ op_fmem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_SUBOFF,FLT_MPREC_SINGLE,R,A,-(O)); \ else \ op_fmem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_ADDOFF,FLT_MPREC_SINGLE,R,A,O)#define op_fstorel_offset(R,A,O) \ if ((O) < 0) \ op_fmem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_SUBOFF,FLT_MPREC_DOUBLE,R,A,-(O)); \ else \ op_fmem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_ADDOFF,FLT_MPREC_DOUBLE,R,A,O)#define op_push(T,R) op_mem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_WRTBCK,R,T,4)/* * Remember to left shift the offset since it's a WORD, not a BYTE offset. */#define op_fpush(T,R) op_fmem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_WRTBCK,FLT_MPREC_SINGLE,R,T,(4 >> 2));#define op_fpushl(T,R) op_fmem_rrc(CC_AL,MEM_STORE|MEM_PREIDX|MEM_WRTBCK,FLT_MPREC_DOUBLE,R,T,(8 >> 2))/* Define convenience macros for load/store instructions with offset zero */ #define op_load(R,A) op_load_offset(R,A,0)#define op_load_ub(R,A) op_load_ub_offset(R,A,0)#define op_load_sb(R,A) op_load_sb_offset(R,A,0)#define op_load_uh(R,A) op_load_uh_offset(R,A,0)#define op_load_sh(R,A) op_load_sh_offset(R,A,0)#define op_fload(R,A) op_fload_offset(R,A,0)#define op_floadl(R,A) op_floadl_offset(R,A,0)#define op_store(R,A) op_store_offset(R,A,0)#define op_store_b(R,A) op_store_b_offset(R,A,0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -