Implement x86 das instruction.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12
ret
+/* Do %al = DAS(%al). Note that the passed param has %AL as the least
+ significant 8 bits, since it was generated with GETB %AL,
+ some-temp. Fortunately %al is the least significant 8 bits of
+ %eax anyway, which is why it's safe to work with %eax as a
+ whole.
+
+ On entry:
+ value of %eax
+ RA <- %esp
+*/
+.global VG_(helper_DAS)
+VG_(helper_DAS):
+ pushl %eax
+ movl 8(%esp), %eax
+ das
+ movl %eax, 8(%esp)
+ popl %eax
+ ret
+
+
+
/* Bit scan forwards/reverse. Sets flags (??).
On entry:
value, replaced by result
src
dst
RA <- %esp
+
+ NOTE all these are basically misimplemented, since for memory
+ operands it appears the index value can be arbitrary, and the
+ address should be calculated accordingly. Here, we assume (by
+ forcing the register- and memory- versions to be handled by
+ the same helper) that the offset is always in the range
+ 0 .. word-size-1, or to be more precise by implementing the
+ client's memory- version of this using the register- version,
+ we impose the condition that the offset is used
+ modulo-wordsize. This is just plain wrong and should be
+ fixed.
*/
.global VG_(helper_bt)
VG_(helper_bt):
#define FlagsSZACP ( FlagS | FlagZ | FlagA | FlagC | FlagP)
#define FlagsSZAP ( FlagS | FlagZ | FlagA | FlagP)
#define FlagsOC (FlagO | FlagC )
+#define FlagsAC ( FlagA | FlagC )
#define FlagsALL (FlagsOSZACP | FlagD)
#define FlagsEmpty (FlagSet)0
extern void VG_(helper_fstsw_AX);
extern void VG_(helper_SAHF);
+extern void VG_(helper_DAS);
extern void VG_(helper_value_check4_fail);
extern void VG_(helper_value_check2_fail);
extern Int VGOFF_(helper_fstsw_AX);
extern Int VGOFF_(helper_SAHF);
+extern Int VGOFF_(helper_DAS);
extern Int VGOFF_(helper_value_check4_fail);
extern Int VGOFF_(helper_value_check2_fail);
Int VGOFF_(helper_bsr) = INVALID_OFFSET;
Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
+Int VGOFF_(helper_DAS) = INVALID_OFFSET;
Int VGOFF_(helper_value_check4_fail) = INVALID_OFFSET;
Int VGOFF_(helper_value_check2_fail) = INVALID_OFFSET;
Int VGOFF_(helper_value_check1_fail) = INVALID_OFFSET;
= alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
VGOFF_(helper_SAHF)
= alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
+ VGOFF_(helper_DAS)
+ = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
VGOFF_(helper_request_normal_exit)
= alloc_BaB_1_set( (Addr) & VG_(helper_request_normal_exit) );
if (dis) VG_(printf)("leave");
break;
+ /* ---------------- Misc wierd-ass insns --------------- */
+
+ case 0x2F: /* DAS */
+ t1 = newTemp(cb);
+ uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t1);
+ /* Widen %AL to 32 bits, so it's all defined when we push it. */
+ uInstr1(cb, WIDEN, 4, TempReg, t1);
+ LAST_UINSTR(cb).extra4b = 1;
+ LAST_UINSTR(cb).signed_widen = False;
+ uInstr0(cb, CALLM_S, 0);
+ uInstr1(cb, PUSH, 4, TempReg, t1);
+ uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_DAS) );
+ uFlagsRWU(cb, FlagsAC, FlagsOSZACP, FlagsEmpty);
+ uInstr1(cb, POP, 4, TempReg, t1);
+ uInstr0(cb, CALLM_E, 0);
+ uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, R_AL);
+ if (dis) VG_(printf)("das\n");
+
/* ------------------------ CWD/CDQ -------------------- */
case 0x98: /* CBW */
ret
+/* Do %al = DAS(%al). Note that the passed param has %AL as the least
+ significant 8 bits, since it was generated with GETB %AL,
+ some-temp. Fortunately %al is the least significant 8 bits of
+ %eax anyway, which is why it's safe to work with %eax as a
+ whole.
+
+ On entry:
+ value of %eax
+ RA <- %esp
+*/
+.global VG_(helper_DAS)
+VG_(helper_DAS):
+ pushl %eax
+ movl 8(%esp), %eax
+ das
+ movl %eax, 8(%esp)
+ popl %eax
+ ret
+
+
+
/* Bit scan forwards/reverse. Sets flags (??).
On entry:
value, replaced by result
src
dst
RA <- %esp
+
+ NOTE all these are basically misimplemented, since for memory
+ operands it appears the index value can be arbitrary, and the
+ address should be calculated accordingly. Here, we assume (by
+ forcing the register- and memory- versions to be handled by
+ the same helper) that the offset is always in the range
+ 0 .. word-size-1, or to be more precise by implementing the
+ client's memory- version of this using the register- version,
+ we impose the condition that the offset is used
+ modulo-wordsize. This is just plain wrong and should be
+ fixed.
*/
.global VG_(helper_bt)
VG_(helper_bt):
#define FlagsSZACP ( FlagS | FlagZ | FlagA | FlagC | FlagP)
#define FlagsSZAP ( FlagS | FlagZ | FlagA | FlagP)
#define FlagsOC (FlagO | FlagC )
+#define FlagsAC ( FlagA | FlagC )
#define FlagsALL (FlagsOSZACP | FlagD)
#define FlagsEmpty (FlagSet)0
extern void VG_(helper_fstsw_AX);
extern void VG_(helper_SAHF);
+extern void VG_(helper_DAS);
extern void VG_(helper_value_check4_fail);
extern void VG_(helper_value_check2_fail);
extern Int VGOFF_(helper_fstsw_AX);
extern Int VGOFF_(helper_SAHF);
+extern Int VGOFF_(helper_DAS);
extern Int VGOFF_(helper_value_check4_fail);
extern Int VGOFF_(helper_value_check2_fail);
Int VGOFF_(helper_bsr) = INVALID_OFFSET;
Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
+Int VGOFF_(helper_DAS) = INVALID_OFFSET;
Int VGOFF_(helper_value_check4_fail) = INVALID_OFFSET;
Int VGOFF_(helper_value_check2_fail) = INVALID_OFFSET;
Int VGOFF_(helper_value_check1_fail) = INVALID_OFFSET;
= alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
VGOFF_(helper_SAHF)
= alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
+ VGOFF_(helper_DAS)
+ = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
VGOFF_(helper_request_normal_exit)
= alloc_BaB_1_set( (Addr) & VG_(helper_request_normal_exit) );
if (dis) VG_(printf)("leave");
break;
+ /* ---------------- Misc wierd-ass insns --------------- */
+
+ case 0x2F: /* DAS */
+ t1 = newTemp(cb);
+ uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t1);
+ /* Widen %AL to 32 bits, so it's all defined when we push it. */
+ uInstr1(cb, WIDEN, 4, TempReg, t1);
+ LAST_UINSTR(cb).extra4b = 1;
+ LAST_UINSTR(cb).signed_widen = False;
+ uInstr0(cb, CALLM_S, 0);
+ uInstr1(cb, PUSH, 4, TempReg, t1);
+ uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_DAS) );
+ uFlagsRWU(cb, FlagsAC, FlagsOSZACP, FlagsEmpty);
+ uInstr1(cb, POP, 4, TempReg, t1);
+ uInstr0(cb, CALLM_E, 0);
+ uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, R_AL);
+ if (dis) VG_(printf)("das\n");
+
/* ------------------------ CWD/CDQ -------------------- */
case 0x98: /* CBW */