mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-02-17 17:19:35 +08:00
Initial support for generating DREX suffixes
Initial support for generating DREX suffixes. Not used yet. No disassembler support yet, and no support for "operand X must match operand Y."
This commit is contained in:
parent
8f94f988f0
commit
401c07e20d
64
assemble.c
64
assemble.c
@ -39,9 +39,16 @@
|
||||
* \150..\153 - an immediate dword or signed byte for operand 0..3
|
||||
* \154..\157 - or 2 (s-field) into next opcode byte if operand 0..3
|
||||
* is a signed byte rather than a dword.
|
||||
* \160..\163 - this instruction uses DREX rather than REX, with the
|
||||
* OC0 field set to 0, and the dest field taken from
|
||||
* operand 0..3.
|
||||
* \164..\167 - this instruction uses DREX rather than REX, with the
|
||||
* OC0 field set to 1, and the dest field taken from
|
||||
* operand 0..3.
|
||||
* \170 - encodes the literal byte 0. (Some compilers don't take
|
||||
* kindly to a zero byte in the _middle_ of a compile time
|
||||
* string constant, so I had to put this hack in.)
|
||||
* \171 - placement of DREX suffix in the absence of an EA
|
||||
* \2ab - a ModRM, calculated on EA in operand a, with the spare
|
||||
* field equal to digit b.
|
||||
* \30x - might be an 0x67 byte, depending on the address size of
|
||||
@ -843,9 +850,25 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits,
|
||||
codes += 2;
|
||||
length++;
|
||||
break;
|
||||
case 0160:
|
||||
case 0161:
|
||||
case 0162:
|
||||
case 0163:
|
||||
length++;
|
||||
ins->rex |= REX_D;
|
||||
break;
|
||||
case 0164:
|
||||
case 0165:
|
||||
case 0166:
|
||||
case 0167:
|
||||
length++;
|
||||
ins->rex |= REX_D|REX_OC;
|
||||
break;
|
||||
case 0170:
|
||||
length++;
|
||||
break;
|
||||
case 0171:
|
||||
break;
|
||||
case 0300:
|
||||
case 0301:
|
||||
case 0302:
|
||||
@ -945,7 +968,14 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits,
|
||||
}
|
||||
|
||||
ins->rex &= rex_mask;
|
||||
if (ins->rex & REX_REAL) {
|
||||
|
||||
if (ins->rex & REX_D) {
|
||||
if (ins->rex & REX_H) {
|
||||
errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
|
||||
return -1;
|
||||
}
|
||||
length++;
|
||||
} else if (ins->rex & REX_REAL) {
|
||||
if (ins->rex & REX_H) {
|
||||
errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
|
||||
return -1;
|
||||
@ -964,7 +994,7 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits,
|
||||
}
|
||||
|
||||
#define EMIT_REX() \
|
||||
if((ins->rex & REX_REAL) && (bits == 64)) { \
|
||||
if (!(ins->rex & REX_D) && (ins->rex & REX_REAL) && (bits == 64)) { \
|
||||
ins->rex = (ins->rex & REX_REAL)|REX_P; \
|
||||
out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
|
||||
ins->rex = 0; \
|
||||
@ -1320,12 +1350,33 @@ static void gencode(int32_t segment, int32_t offset, int bits,
|
||||
offset++;
|
||||
break;
|
||||
|
||||
case 0160:
|
||||
case 0161:
|
||||
case 0162:
|
||||
case 0163:
|
||||
case 0164:
|
||||
case 0165:
|
||||
case 0166:
|
||||
case 0167:
|
||||
ins->drexdst = regval(&ins->oprs[c & 3]);
|
||||
break;
|
||||
|
||||
case 0170:
|
||||
bytes[0] = 0;
|
||||
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
|
||||
offset += 1;
|
||||
break;
|
||||
|
||||
case 0171:
|
||||
bytes[0] =
|
||||
(ins->drexdst << 4) |
|
||||
(ins->rex & REX_OC ? 0x08 : 0) |
|
||||
(ins->rex & (REX_R|REX_X|REX_B));
|
||||
ins->rex = 0;
|
||||
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
|
||||
offset++;
|
||||
break;
|
||||
|
||||
case 0300:
|
||||
case 0301:
|
||||
case 0302:
|
||||
@ -1487,6 +1538,15 @@ static void gencode(int32_t segment, int32_t offset, int bits,
|
||||
if (ea_data.sib_present)
|
||||
*p++ = ea_data.sib;
|
||||
|
||||
/* DREX suffixes come between the SIB and the displacement */
|
||||
if (ins->rex & REX_D) {
|
||||
*p++ =
|
||||
(ins->drexdst << 4) |
|
||||
(ins->rex & REX_OC ? 0x08 : 0) |
|
||||
(ins->rex & (REX_R|REX_X|REX_B));
|
||||
ins->rex = 0;
|
||||
}
|
||||
|
||||
s = p - bytes;
|
||||
out(offset, segment, bytes, OUT_RAWDATA + s,
|
||||
NO_SEG, NO_SEG);
|
||||
|
5
nasm.h
5
nasm.h
@ -540,6 +540,8 @@ enum ccode { /* condition code names */
|
||||
/*
|
||||
* REX flags
|
||||
*/
|
||||
#define REX_OC 0x0200 /* DREX suffix has the OC0 bit set */
|
||||
#define REX_D 0x0100 /* Instruction uses DREX instead of REX */
|
||||
#define REX_H 0x80 /* High register present, REX forbidden */
|
||||
#define REX_P 0x40 /* REX prefix present/required */
|
||||
#define REX_L 0x20 /* Use LOCK prefix instead of REX.R */
|
||||
@ -622,7 +624,8 @@ typedef struct { /* an instruction itself */
|
||||
int eops_float; /* true if DD and floating */
|
||||
int32_t times; /* repeat count (TIMES prefix) */
|
||||
int forw_ref; /* is there a forward reference? */
|
||||
uint8_t rex; /* Special REX Prefix */
|
||||
int rex; /* Special REX Prefix */
|
||||
int drexdst; /* Destination register for DREX suffix */
|
||||
} insn;
|
||||
|
||||
enum geninfo { GI_SWITCH };
|
||||
|
Loading…
Reference in New Issue
Block a user