summaryrefslogtreecommitdiff
path: root/ecomp-c/asm-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-c/asm-i386.c')
-rw-r--r--ecomp-c/asm-i386.c113
1 files changed, 78 insertions, 35 deletions
diff --git a/ecomp-c/asm-i386.c b/ecomp-c/asm-i386.c
index c9de15a..584c631 100644
--- a/ecomp-c/asm-i386.c
+++ b/ecomp-c/asm-i386.c
@@ -32,6 +32,7 @@
* E9 XX XX XX XX jmp rel32
* E8 XX XX XX XX call rel32
* C3 ret
+ * C2 XX XX ret imm16
* F4 hlt
* CD XX int nnn
* 90 nop
@@ -52,6 +53,9 @@
* rel32
* relative address offset (8/32 bits)
*
+ * imm16
+ * little endian 16-bit constant
+ *
* format binary
* use32
* org 0x00000000
@@ -68,7 +72,8 @@ enum {
MAX_NUMBER_LEN = 10,
MAX_HEXNUMBER_LEN = 8,
MAX_STRING_LEN = 64,
- MAX_PASSES = 10
+ MAX_PASSES = 10,
+ MAX_NOF_OPERANDS = 64
};
static int DEBUG_GETCHAR = 0;
@@ -842,7 +847,8 @@ typedef struct OpcodeInfo {
Symbol *label;
int addr;
Opcode opcode;
- int nof_operands;
+ int min_operands;
+ int max_operands;
OperandInfo *operand;
struct OpcodeInfo *next;
int size;
@@ -866,51 +872,60 @@ static OpcodeInfo *parseOpcode( void )
case 'a':
if( strcmp( ident, "add" ) == 0 ) {
opcode_info->opcode = OPCODE_ADD;
- opcode_info->nof_operands = 2;
+ opcode_info->min_operands = 2;
+ opcode_info->max_operands = 2;
opcode_info->size = 2;
}
break;
case 'c':
if( strcmp( ident, "cmp" ) == 0 ) {
opcode_info->opcode = OPCODE_CMP;
- opcode_info->nof_operands = 2;
+ opcode_info->min_operands = 2;
+ opcode_info->max_operands = 2;
opcode_info->size = 2;
} else if( strcmp( ident, "call" ) == 0 ) {
opcode_info->opcode = OPCODE_CALL;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 5;
}
break;
case 'd':
if( strcmp( ident, "dd" ) == 0 ) {
opcode_info->opcode = OPCODE_PSEUDO_DD;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = MAX_NOF_OPERANDS;
opcode_info->size = 4;
} else if( strcmp( ident, "db" ) == 0 ) {
opcode_info->opcode = OPCODE_PSEUDO_DB;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = MAX_NOF_OPERANDS;
opcode_info->size = 1;
} else if( strcmp( ident, "dw" ) == 0 ) {
opcode_info->opcode = OPCODE_PSEUDO_DW;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = MAX_NOF_OPERANDS;
opcode_info->size = 2;
} else if( strcmp( ident, "div" ) == 0 ) {
opcode_info->opcode = OPCODE_DIV;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
case 'h':
if( strcmp( ident, "hlt" ) == 0 ) {
opcode_info->opcode = OPCODE_HLT;
- opcode_info->nof_operands = 0;
+ opcode_info->min_operands = 0;
+ opcode_info->max_operands = 0;
opcode_info->size = 1;
}
break;
case 'i':
if( strcmp( ident, "int" ) == 0 ) {
opcode_info->opcode = OPCODE_INT;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
@@ -919,43 +934,50 @@ static OpcodeInfo *parseOpcode( void )
case 'm':
if( strcmp( ident, "jmp" ) == 0 ) {
opcode_info->opcode = OPCODE_JMP;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
case 'e':
if( strcmp( ident, "je" ) == 0 ) {
opcode_info->opcode = OPCODE_JE;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
case 'n':
if( strcmp( ident, "jne" ) == 0 ) {
opcode_info->opcode = OPCODE_JNE;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
case 'b':
if( strcmp( ident, "jb" ) == 0 ) {
opcode_info->opcode = OPCODE_JB;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
} else if( strcmp( ident, "jbe" ) == 0 ) {
opcode_info->opcode = OPCODE_JBE;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
case 'a':
if( strcmp( ident, "ja" ) == 0 ) {
opcode_info->opcode = OPCODE_JA;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
} else if( strcmp( ident, "jae" ) == 0 ) {
opcode_info->opcode = OPCODE_JAE;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
@@ -964,43 +986,50 @@ static OpcodeInfo *parseOpcode( void )
case 'm':
if( strcmp( ident, "mov" ) == 0 ) {
opcode_info->opcode = OPCODE_MOV;
- opcode_info->nof_operands = 2;
+ opcode_info->min_operands = 2;
+ opcode_info->max_operands = 2;
opcode_info->size = 5;
} else if( strcmp( ident, "mul" ) == 0 ) {
opcode_info->opcode = OPCODE_MUL;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 2;
}
break;
case 'n':
if( strcmp( ident, "nop" ) == 0 ) {
opcode_info->opcode = OPCODE_NOP;
- opcode_info->nof_operands = 0;
+ opcode_info->min_operands = 0;
+ opcode_info->max_operands = 0;
opcode_info->size = 1;
}
break;
case 'p':
if( strcmp( ident, "push" ) == 0 ) {
opcode_info->opcode = OPCODE_PUSH;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 1;
} else if( strcmp( ident, "pop" ) == 0 ) {
opcode_info->opcode = OPCODE_POP;
- opcode_info->nof_operands = 1;
+ opcode_info->min_operands = 1;
+ opcode_info->max_operands = 1;
opcode_info->size = 1;
}
break;
case 'r':
if( strcmp( ident, "ret" ) == 0 ) {
opcode_info->opcode = OPCODE_RET;
- opcode_info->nof_operands = 0;
+ opcode_info->min_operands = 0;
+ opcode_info->max_operands = 1;
opcode_info->size = 1;
}
break;
case 's':
if( strcmp( ident, "sub" ) == 0 ) {
opcode_info->opcode = OPCODE_SUB;
- opcode_info->nof_operands = 2;
+ opcode_info->min_operands = 2;
+ opcode_info->max_operands = 2;
opcode_info->size = 2;
}
break;
@@ -1317,17 +1346,16 @@ static void parseOperands( OpcodeInfo *opcode_info )
}
}
- if( opcode_info->opcode != OPCODE_PSEUDO_DB &&
- opcode_info->opcode != OPCODE_PSEUDO_DW &&
- opcode_info->opcode != OPCODE_PSEUDO_DD &&
- nof_operands != opcode_info->nof_operands ) {
- Abort( "'%s' expects %d operand(s), %d given", opcodename[opcode_info->opcode], opcode_info->nof_operands, nof_operands );
+ if( nof_operands < opcode_info->min_operands ) {
+ Abort( "'%s' expects at least %d operand(s), only %d given", opcodename[opcode_info->opcode], opcode_info->min_operands, nof_operands );
+ }
+ if( nof_operands > opcode_info->max_operands ) {
+ Abort( "'%s' expects at most %d operand(s), but %d given", opcodename[opcode_info->opcode], opcode_info->max_operands, nof_operands );
}
switch( opcode_info->opcode ) {
case OPCODE_HLT:
case OPCODE_NOP:
- case OPCODE_RET:
break;
case OPCODE_PSEUDO_DD:
case OPCODE_PSEUDO_DW: {
@@ -1349,7 +1377,7 @@ static void parseOperands( OpcodeInfo *opcode_info )
i++;
operand_info = operand_info->next;
}
- opcode_info->nof_operands = i;
+ opcode_info->max_operands = i;
opcode_info->size = size;
} break;
case OPCODE_PSEUDO_DB: {
@@ -1367,7 +1395,7 @@ static void parseOperands( OpcodeInfo *opcode_info )
i++;
operand_info = operand_info->next;
}
- opcode_info->nof_operands = i;
+ opcode_info->max_operands = i;
opcode_info->size = size;
} break;
case OPCODE_MOV:
@@ -1434,9 +1462,19 @@ static void parseOperands( OpcodeInfo *opcode_info )
}
break;
case OPCODE_INT:
- if( opcode_info->operand->next->type != OPERAND_ABSOLUTE ) {
+ if( opcode_info->operand->type == OPERAND_ABSOLUTE ) {
/* int $80, jump to interrupt vector number */
}
+ case OPCODE_RET:
+ if( opcode_info->operand == NULL ) {
+ /* ok, no parameter return */
+ opcode_info->size = 1;
+ } else if( opcode_info->operand->type == OPERAND_ABSOLUTE ) {
+ /* return, pop N bytes from stack */
+ opcode_info->size = 3;
+ } else {
+ Abort( "'%s' expects either no operand or a number of bytes to remove from the stack", opcodename[opcode_info->opcode] );
+ }
break;
default:
Abort( "Unhandled opcode '%s' when checking operand validity", opcodename[opcode_info->opcode] );
@@ -2169,7 +2207,12 @@ static void emit_opcode( OpcodeInfo *opcode_info )
}
break;
case OPCODE_RET:
- Emit( "%c", 0xC3 );
+ if( opcode_info->operand == NULL ) {
+ Emit( "%c", 0xC3 );
+ } else if( opcode_info->operand->type == OPERAND_ABSOLUTE ) {
+ Emit( "%c", 0xC2 );
+ Emit_word_little_endian( opcode_info->operand->num );
+ }
break;
case OPCODE_PSEUDO_ASSIGN:
break;