mirror of https://github.com/yasm/yasm.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
6.7 KiB
279 lines
6.7 KiB
/* $Id: bytecode.c,v 1.8 2001/05/30 07:41:03 peter Exp $ |
|
* Bytecode utility functions |
|
* |
|
* Copyright (C) 2001 Peter Johnson |
|
* |
|
* This file is part of YASM. |
|
* |
|
* YASM is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; either version 2 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* YASM is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
#include <stdio.h> |
|
#include "globals.h" |
|
#include "bytecode.h" |
|
#include "errwarn.h" |
|
|
|
static effaddr eff_static; |
|
static immval im_static; |
|
unsigned char bytes_static[16]; |
|
|
|
effaddr *ConvertIntToEA(effaddr *ptr, unsigned long int_val) |
|
{ |
|
if(!ptr) |
|
ptr = &eff_static; |
|
|
|
ptr->segment = 0; |
|
|
|
ptr->valid_modrm = 0; |
|
ptr->need_modrm = 1; |
|
ptr->valid_sib = 0; |
|
ptr->need_sib = 0; |
|
|
|
ptr->disp = int_val; |
|
|
|
if((int_val & 0xFF) == int_val) |
|
ptr->len = 1; |
|
else if((int_val & 0xFFFF) == int_val) |
|
ptr->len = 2; |
|
else |
|
ptr->len = 4; |
|
|
|
return ptr; |
|
} |
|
|
|
effaddr *ConvertRegToEA(effaddr *ptr, unsigned long reg) |
|
{ |
|
if(!ptr) |
|
ptr = &eff_static; |
|
|
|
ptr->len = 0; |
|
ptr->segment = 0; |
|
ptr->modrm = 0xC0 | (reg & 0x07); /* Mod=11, R/M=Reg, Reg=0 */ |
|
ptr->valid_modrm = 1; |
|
ptr->need_modrm = 1; |
|
ptr->valid_sib = 0; |
|
ptr->need_sib = 0; |
|
|
|
return ptr; |
|
} |
|
|
|
effaddr *ConvertImmToEA(effaddr *ptr, immval *im_ptr, unsigned char im_len) |
|
{ |
|
if(!ptr) |
|
ptr = &eff_static; |
|
|
|
ptr->disp = im_ptr->val; |
|
if(im_ptr->len > im_len) |
|
Warning(WARN_VALUE_EXCEEDS_BOUNDS, (char *)NULL, "word"); |
|
ptr->len = im_len; |
|
ptr->segment = 0; |
|
ptr->valid_modrm = 0; |
|
ptr->need_modrm = 0; |
|
ptr->valid_sib = 0; |
|
ptr->need_sib = 0; |
|
|
|
return ptr; |
|
} |
|
|
|
immval *ConvertIntToImm(immval *ptr, unsigned long int_val) |
|
{ |
|
if(!ptr) |
|
ptr = &im_static; |
|
|
|
ptr->val = int_val; |
|
|
|
if((int_val & 0xFF) == int_val) |
|
ptr->len = 1; |
|
else if((int_val & 0xFFFF) == int_val) |
|
ptr->len = 2; |
|
else |
|
ptr->len = 4; |
|
|
|
ptr->isrel = 0; |
|
ptr->isneg = 0; |
|
|
|
return ptr; |
|
} |
|
|
|
void SetEASegment(effaddr *ptr, unsigned char segment) |
|
{ |
|
if(!ptr) |
|
return; |
|
|
|
if(ptr->segment != 0) |
|
Warning(WARN_MULT_SEG_OVERRIDE, (char *)NULL); |
|
|
|
ptr->segment = segment; |
|
} |
|
|
|
void SetEALen(effaddr *ptr, unsigned char len) |
|
{ |
|
if(!ptr) |
|
return; |
|
|
|
/* Currently don't warn if length truncated, as this is called only from |
|
* an explicit override, where we expect the user knows what they're doing. |
|
*/ |
|
|
|
ptr->len = len; |
|
} |
|
|
|
void SetInsnOperSizeOverride(bytecode *bc, unsigned char opersize) |
|
{ |
|
if(!bc) |
|
return; |
|
|
|
bc->data.insn.opersize = opersize; |
|
} |
|
|
|
void SetInsnAddrSizeOverride(bytecode *bc, unsigned char addrsize) |
|
{ |
|
if(!bc) |
|
return; |
|
|
|
bc->data.insn.addrsize = addrsize; |
|
} |
|
|
|
void SetInsnLockRepPrefix(bytecode *bc, unsigned char prefix) |
|
{ |
|
if(!bc) |
|
return; |
|
|
|
if(bc->data.insn.lockrep_pre != 0) |
|
Warning(WARN_MULT_LOCKREP_PREFIX, (char *)NULL); |
|
|
|
bc->data.insn.lockrep_pre = prefix; |
|
} |
|
|
|
void BuildBC_Insn(bytecode *bc, |
|
unsigned char opersize, |
|
unsigned char opcode_len, |
|
unsigned char op0, |
|
unsigned char op1, |
|
unsigned char op2, |
|
effaddr *ea_ptr, |
|
unsigned char spare, |
|
immval *im_ptr, |
|
unsigned char im_len, |
|
unsigned char im_sign, |
|
unsigned char im_rel) |
|
{ |
|
bc->next = (bytecode *)NULL; |
|
bc->type = BC_INSN; |
|
|
|
if(ea_ptr) { |
|
bc->data.insn.ea = *ea_ptr; |
|
bc->data.insn.ea.modrm &= 0xC7; /* zero spare/reg bits */ |
|
bc->data.insn.ea.modrm |= (spare << 3) & 0x38; /* plug in provided bits */ |
|
} else { |
|
bc->data.insn.ea.len = 0; |
|
bc->data.insn.ea.segment = 0; |
|
bc->data.insn.ea.need_modrm = 0; |
|
bc->data.insn.ea.need_sib = 0; |
|
} |
|
|
|
if(im_ptr) { |
|
bc->data.insn.imm = *im_ptr; |
|
bc->data.insn.imm.f_rel = im_rel; |
|
bc->data.insn.imm.f_sign = im_sign; |
|
bc->data.insn.imm.f_len = im_len; |
|
} else { |
|
bc->data.insn.imm.len = 0; |
|
bc->data.insn.imm.f_rel = 0; |
|
bc->data.insn.imm.f_sign = 0; |
|
bc->data.insn.imm.f_len = 0; |
|
} |
|
|
|
bc->data.insn.opcode[0] = op0; |
|
bc->data.insn.opcode[1] = op1; |
|
bc->data.insn.opcode[2] = op2; |
|
bc->data.insn.opcode_len = opcode_len; |
|
|
|
bc->data.insn.addrsize = 0; |
|
bc->data.insn.opersize = opersize; |
|
|
|
bc->len = 0; |
|
|
|
bc->filename = (char *)NULL; |
|
bc->lineno = line_number; |
|
|
|
bc->offset = 0; |
|
bc->mode_bits = mode_bits; |
|
} |
|
|
|
/* TODO: implement. Shouldn't be difficult. */ |
|
unsigned char *ConvertBCInsnToBytes(unsigned char *ptr, bytecode *bc, int *len) |
|
{ |
|
if(bc->type != BC_INSN) |
|
return (unsigned char *)NULL; |
|
return (unsigned char *)NULL; |
|
} |
|
|
|
void DebugPrintBC(bytecode *bc) |
|
{ |
|
unsigned long i; |
|
|
|
switch(bc->type) { |
|
case BC_INSN: |
|
printf("_Instruction_\n"); |
|
printf("Effective Address:\n"); |
|
printf(" Disp=%lx Len=%u SegmentOv=%2x\n", bc->data.insn.ea.disp, |
|
(unsigned int)bc->data.insn.ea.len, |
|
(unsigned int)bc->data.insn.ea.segment); |
|
printf(" ModRM=%2x ValidRM=%u NeedRM=%u\n", |
|
(unsigned int)bc->data.insn.ea.modrm, |
|
(unsigned int)bc->data.insn.ea.valid_modrm, |
|
(unsigned int)bc->data.insn.ea.need_modrm); |
|
printf(" SIB=%2x ValidSIB=%u NeedSIB=%u\n", |
|
(unsigned int)bc->data.insn.ea.sib, |
|
(unsigned int)bc->data.insn.ea.valid_sib, |
|
(unsigned int)bc->data.insn.ea.need_sib); |
|
printf("Immediate/Relative Value:\n"); |
|
printf(" Val=%lx\n", bc->data.insn.imm.val); |
|
printf(" Len=%u, IsRel=%u, IsNeg=%u\n", |
|
(unsigned int)bc->data.insn.imm.len, |
|
(unsigned int)bc->data.insn.imm.isrel, |
|
(unsigned int)bc->data.insn.imm.isneg); |
|
printf(" FLen=%u, FRel=%u, FSign=%u\n", |
|
(unsigned int)bc->data.insn.imm.f_len, |
|
(unsigned int)bc->data.insn.imm.f_rel, |
|
(unsigned int)bc->data.insn.imm.f_sign); |
|
printf("Opcode: %2x %2x OpLen=%u\n", |
|
(unsigned int)bc->data.insn.opcode[0], |
|
(unsigned int)bc->data.insn.opcode[1], |
|
(unsigned int)bc->data.insn.opcode_len); |
|
printf("OperSize=%u LockRepPre=%2x\n", |
|
(unsigned int)bc->data.insn.opersize, |
|
(unsigned int)bc->data.insn.lockrep_pre); |
|
break; |
|
case BC_DATA: |
|
printf("_Data_\n"); |
|
for(i=0; i<bc->len; i++) { |
|
printf("%2x ", (unsigned int)bc->data.data.data[i]); |
|
if((i & ~0xFFFF) == i) |
|
printf("\n"); |
|
} |
|
break; |
|
case BC_RESERVE: |
|
printf("_Reserve_\n"); |
|
break; |
|
default: |
|
printf("_Unknown_\n"); |
|
} |
|
printf("Length=%lu\n", bc->len); |
|
printf("Filename=\"%s\" Line Number=%u\n", |
|
bc->filename ? bc->filename : "<UNKNOWN>", bc->lineno); |
|
printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits); |
|
} |
|
|
|
|