Fixed inline assembler for Linux.

This commit is contained in:
jbo_85 2008-03-09 00:45:18 +00:00
parent 1c529a52e7
commit 1aba6fec1d
2 changed files with 92 additions and 76 deletions

View File

@ -319,10 +319,13 @@ static void count(u32 opcode, int cond_res)
#define EMIT1(op,arg) #op" "arg"; " #define EMIT1(op,arg) #op" "arg"; "
#define EMIT2(op,src,dest) #op" "src", "dest"; " #define EMIT2(op,src,dest) #op" "src", "dest"; "
#define CONST(val) "$"#val #define CONST(val) "$"#val
#define VAR(var) "_"#var #define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
#define VARL(var) "_"#var #define ASMVAR2(prefix,cvar) STRING (prefix) cvar
#define REGREF1(index) "_reg("index")" #define STRING(x) #x
#define REGREF2(index,scale) "_reg(,"index","#scale")" #define VAR(var) ASMVAR(#var)
#define VARL(var) ASMVAR(#var)
#define REGREF1(index) ASMVAR("reg("index")")
#define REGREF2(index,scale) ASMVAR("reg(,"index","#scale")")
#define LABEL(n) #n": " #define LABEL(n) #n": "
#define LABELREF(n,dir) #n#dir #define LABELREF(n,dir) #n#dir
#define al "%%al" #define al "%%al"
@ -695,7 +698,7 @@ static void count(u32 opcode, int cond_res)
: "0" (offset), "c" (shift)); : "0" (offset), "c" (shift));
#define RRX_OFFSET \ #define RRX_OFFSET \
asm("btl $0, _C_FLAG;" \ asm(EMIT2(btl,CONST(0),VAR(C_FLAG)) \
"rcr $1, %0" \ "rcr $1, %0" \
: "=r" (offset) \ : "=r" (offset) \
: "0" (offset)); : "0" (offset));

View File

@ -319,98 +319,110 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
V_FLAG = (Flags >> 26) & 1; \ V_FLAG = (Flags >> 26) & 1; \
} }
#else #else
#define EMIT1(op,arg) #op" "arg"; "
#define EMIT2(op,src,dest) #op" "src", "dest"; "
#define CONST(val) "$"#val
#define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
#define ASMVAR2(prefix,cvar) STRING (prefix) cvar
#define STRING(x) #x
#define VAR(var) ASMVAR(#var)
#define REGREF1(index) ASMVAR("reg("index")")
#define REGREF2(index,scale) ASMVAR("reg(,"index","#scale")")
#define eax "%%eax"
#define ecx "%%ecx"
#define edx "%%edx"
#define ADD_RN_O8(d) \ #define ADD_RN_O8(d) \
asm ("andl $0xFF, %%eax;"\ asm ("andl $0xFF, %%eax;"\
"addl %%eax, %0;"\ "addl %%eax, %0;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: "=m" (reg[(d)].I)); : "=m" (reg[(d)].I));
#define CMN_RD_RS \ #define CMN_RD_RS \
asm ("add %0, %1;"\ asm ("add %0, %1;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: \ : \
: "r" (value), "r" (reg[dest].I):"1"); : "r" (value), "r" (reg[dest].I):"1");
#define ADC_RD_RS \ #define ADC_RD_RS \
asm ("bt $0, _C_FLAG;"\ asm (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
"adc %1, %%ebx;"\ "adc %1, %%ebx;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: "=b" (reg[dest].I)\ : "=b" (reg[dest].I)\
: "r" (value), "b" (reg[dest].I)); : "r" (value), "b" (reg[dest].I));
#define SUB_RN_O8(d) \ #define SUB_RN_O8(d) \
asm ("andl $0xFF, %%eax;"\ asm ("andl $0xFF, %%eax;"\
"subl %%eax, %0;"\ "subl %%eax, %0;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setncb _C_FLAG;"\ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: "=m" (reg[(d)].I)); : "=m" (reg[(d)].I));
#define MOV_RN_O8(d) \ #define MOV_RN_O8(d) \
asm ("andl $0xFF, %%eax;"\ asm ("andl $0xFF, %%eax;"\
"movb $0, _N_FLAG;"\ EMIT2(movb,CONST(0),VAR(N_FLAG)) \
"movl %%eax, %0;"\ "movl %%eax, %0;"\
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
: "=m" (reg[(d)].I)); : "=m" (reg[(d)].I));
#define CMP_RN_O8(d) \ #define CMP_RN_O8(d) \
asm ("andl $0xFF, %%eax;"\ asm ("andl $0xFF, %%eax;"\
"cmpl %%eax, %0;"\ "cmpl %%eax, %0;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setncb _C_FLAG;"\ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: \ : \
: "m" (reg[(d)].I)); : "m" (reg[(d)].I));
#define SBC_RD_RS \ #define SBC_RD_RS \
asm volatile ("bt $0, _C_FLAG;"\ asm volatile (EMIT2(bt,CONST(0),VAR(C_FLAG)) \
"cmc;"\ "cmc;"\
"sbb %1, %%ebx;"\ "sbb %1, %%ebx;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setncb _C_FLAG;"\ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: "=b" (reg[dest].I)\ : "=b" (reg[dest].I)\
: "r" (value), "b" (reg[dest].I) : "cc", "memory"); : "r" (value), "b" (reg[dest].I) : "cc", "memory");
#define LSL_RD_RS \ #define LSL_RD_RS \
asm ("shl %%cl, %%eax;"\ asm ("shl %%cl, %%eax;"\
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
: "=a" (value)\ : "=a" (value)\
: "a" (reg[dest].I), "c" (value)); : "a" (reg[dest].I), "c" (value));
#define LSR_RD_RS \ #define LSR_RD_RS \
asm ("shr %%cl, %%eax;"\ asm ("shr %%cl, %%eax;"\
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
: "=a" (value)\ : "=a" (value)\
: "a" (reg[dest].I), "c" (value)); : "a" (reg[dest].I), "c" (value));
#define ASR_RD_RS \ #define ASR_RD_RS \
asm ("sar %%cl, %%eax;"\ asm ("sar %%cl, %%eax;"\
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
: "=a" (value)\ : "=a" (value)\
: "a" (reg[dest].I), "c" (value)); : "a" (reg[dest].I), "c" (value));
#define ROR_RD_RS \ #define ROR_RD_RS \
asm ("ror %%cl, %%eax;"\ asm ("ror %%cl, %%eax;"\
"setcb _C_FLAG;"\ EMIT1(setcb, VAR(C_FLAG)) \
: "=a" (value)\ : "=a" (value)\
: "a" (reg[dest].I), "c" (value)); : "a" (reg[dest].I), "c" (value));
#define NEG_RD_RS \ #define NEG_RD_RS \
asm ("neg %%ebx;"\ asm ("neg %%ebx;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setncb _C_FLAG;"\ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: "=b" (reg[dest].I)\ : "=b" (reg[dest].I)\
: "b" (reg[source].I)); : "b" (reg[source].I));
#define CMP_RD_RS \ #define CMP_RD_RS \
asm ("sub %0, %1;"\ asm ("sub %0, %1;"\
"setsb _N_FLAG;"\ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;"\ EMIT1(setzb, VAR(Z_FLAG)) \
"setncb _C_FLAG;"\ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;"\ EMIT1(setob, VAR(V_FLAG)) \
: \ : \
: "r" (value), "r" (reg[dest].I):"1"); : "r" (value), "r" (reg[dest].I):"1");
#define IMM5_INSN(OP,N) \ #define IMM5_INSN(OP,N) \
@ -418,75 +430,76 @@ static INSN_REGPARM void thumbBreakpoint(u32 opcode)
"shrl $1,%%eax;" \ "shrl $1,%%eax;" \
"andl $7,%%ecx;" \ "andl $7,%%ecx;" \
"andl $0x1C,%%eax;" \ "andl $0x1C,%%eax;" \
"movl _reg(%%eax),%%edx;" \ EMIT2(movl, REGREF1(eax), edx) \
OP \ OP \
"setsb _N_FLAG;" \ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;" \ EMIT1(setzb, VAR(Z_FLAG)) \
"movl %%edx,_reg(,%%ecx,4);" \ EMIT2(movl, edx, REGREF2(ecx,4)) \
: : "i" (N)) : : "i" (N))
#define IMM5_INSN_0(OP) \ #define IMM5_INSN_0(OP) \
asm("movl %%eax,%%ecx;" \ asm("movl %%eax,%%ecx;" \
"shrl $1,%%eax;" \ "shrl $1,%%eax;" \
"andl $7,%%ecx;" \ "andl $7,%%ecx;" \
"andl $0x1C,%%eax;" \ "andl $0x1C,%%eax;" \
"movl _reg(%%eax),%%edx;" \ EMIT2(movl, REGREF1(eax), edx) \
OP \ OP \
"setsb _N_FLAG;" \ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;" \ EMIT1(setzb, VAR(Z_FLAG)) \
"movl %%edx,_reg(,%%ecx,4);" \ EMIT2(movl, edx, REGREF2(ecx,4)) \
: : ) : : )
#define IMM5_LSL \ #define IMM5_LSL \
"shll %0,%%edx;"\ "shll %0,%%edx;"\
"setcb _C_FLAG;" EMIT1(setcb, VAR(C_FLAG))
#define IMM5_LSL_0 \ #define IMM5_LSL_0 \
"testl %%edx,%%edx;" "testl %%edx,%%edx;"
#define IMM5_LSR \ #define IMM5_LSR \
"shrl %0,%%edx;"\ "shrl %0,%%edx;"\
"setcb _C_FLAG;" EMIT1(setcb, VAR(C_FLAG))
#define IMM5_LSR_0 \ #define IMM5_LSR_0 \
"testl %%edx,%%edx;"\ "testl %%edx,%%edx;"\
"setsb _C_FLAG;"\ EMIT1(setsb, VAR(C_FLAG)) \
"xorl %%edx,%%edx;" "xorl %%edx,%%edx;"
#define IMM5_ASR \ #define IMM5_ASR \
"sarl %0,%%edx;"\ "sarl %0,%%edx;"\
"setcb _C_FLAG;" EMIT1(setcb, VAR(C_FLAG))
#define IMM5_ASR_0 \ #define IMM5_ASR_0 \
"sarl $31,%%edx;"\ "sarl $31,%%edx;"\
"setsb _C_FLAG;" EMIT1(setsb, VAR(C_FLAG))
#define THREEARG_INSN(OP,N) \ #define THREEARG_INSN(OP,N) \
asm("movl %%eax,%%edx;" \ asm("movl %%eax,%%edx;" \
"shrl $1,%%edx;" \ "shrl $1,%%edx;" \
"andl $0x1C,%%edx;" \ "andl $0x1C,%%edx;" \
"andl $7,%%eax;" \ "andl $7,%%eax;" \
"movl _reg(%%edx),%%ecx;" \ EMIT2(movl, REGREF1(edx), ecx) \
OP(N) \ OP(N) \
"setsb _N_FLAG;" \ EMIT1(setsb, VAR(N_FLAG)) \
"setzb _Z_FLAG;" \ EMIT1(setzb, VAR(Z_FLAG)) \
"movl %%ecx,_reg(,%%eax,4)"::) EMIT2(movl, ecx, REGREF2(eax,4)) \
: : )
#define ADD_RD_RS_RN(N) \ #define ADD_RD_RS_RN(N) \
"add (_reg+"#N"*4),%%ecx;" \ EMIT2(add,VAR(reg)"+"#N"*4",ecx) \
"setcb _C_FLAG;" \ EMIT1(setcb, VAR(C_FLAG)) \
"setob _V_FLAG;" EMIT1(setob, VAR(V_FLAG))
#define ADD_RD_RS_O3(N) \ #define ADD_RD_RS_O3(N) \
"add $"#N",%%ecx;" \ "add $"#N",%%ecx;" \
"setcb _C_FLAG;" \ EMIT1(setcb, VAR(C_FLAG)) \
"setob _V_FLAG;" EMIT1(setob, VAR(V_FLAG))
#define ADD_RD_RS_O3_0(N) \ #define ADD_RD_RS_O3_0(N) \
"movb $0,_C_FLAG;" \ EMIT2(movb,CONST(0),VAR(C_FLAG)) \
"add $0,%%ecx;" \ "add $0,%%ecx;" \
"movb $0,_V_FLAG;" EMIT2(movb,CONST(0),VAR(V_FLAG))
#define SUB_RD_RS_RN(N) \ #define SUB_RD_RS_RN(N) \
"sub (_reg+"#N"*4),%%ecx;" \ EMIT2(sub,VAR(reg)"+"#N"*4",ecx) \
"setncb _C_FLAG;" \ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;" EMIT1(setob, VAR(V_FLAG))
#define SUB_RD_RS_O3(N) \ #define SUB_RD_RS_O3(N) \
"sub $"#N",%%ecx;" \ "sub $"#N",%%ecx;" \
"setncb _C_FLAG;" \ EMIT1(setncb, VAR(C_FLAG)) \
"setob _V_FLAG;" EMIT1(setob, VAR(V_FLAG))
#define SUB_RD_RS_O3_0(N) \ #define SUB_RD_RS_O3_0(N) \
"movb $1,_C_FLAG;" \ EMIT2(movb,CONST(1),VAR(C_FLAG)) \
"sub $0,%%ecx;" \ "sub $0,%%ecx;" \
"movb $0,_V_FLAG;" EMIT2(movb,CONST(0),VAR(V_FLAG))
#endif #endif
#else // !__GNUC__ #else // !__GNUC__
#define ADD_RD_RS_RN(N) \ #define ADD_RD_RS_RN(N) \