Skip to content

Commit

Permalink
rename a variable and add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
davidly committed Oct 2, 2024
1 parent 4ffaf9a commit ea174e4
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
2 changes: 2 additions & 0 deletions i8086.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// ignores some immediate vs. reg cases where the difference is 1 cycle, gets div/mult approximately,
// and doesn't handle many other cases. Also, various 8086 tech documents don't have consistent counts.
// I tested cycle counts against physical 80186 and 8088 machines. This is somewhere in between.
// Not implemented: "For the 8086, add four clocks for each 16-bit word transfer with an odd address. For the 8088, add four clocks for each 16-bit word transfer."
// String operations don't allow for interrupts until completion, unlike real hardware.

#include <djl_os.hxx>

Expand Down
33 changes: 18 additions & 15 deletions i8086.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct i8086
prefix_segment_override = prefix_repeat_opcode = 0xff;
_pcode = 0;
_bc = _b0 = _b1 = _mod = _reg = _rm = 0;
_final_offset = 0;
_effective_offset = 0;
fCarry = fParityEven = fAuxCarry = fZero = fSign = fTrap = fInterrupt = fDirection = fOverflow = fIgnoreTrap = false;
cycles = 0;
fSyscallEnabled = false;
Expand Down Expand Up @@ -176,7 +176,7 @@ struct i8086
uint8_t _reg; // bits 5:3 of _b1. register (generally, but also math in some cases)
uint8_t _mod; // bits 7:6 of _b1
uint8_t * _pcode; // pointer to the first opcode currently executing
uint16_t _final_offset; // for word instructions that have an address offset. used to handle wrapping
uint16_t _effective_offset; // for word instructions that have an address offset. used to handle segment wrapping

uint8_t * reg8_pointers[ 8 ];
uint16_t * reg16_pointers[ 8 ];
Expand All @@ -190,7 +190,7 @@ struct i8086
_rm = ( _b1 & 7 );
_reg = ( ( _b1 >> 3 ) & 7 );
_mod = ( _b1 >> 6 );
_final_offset = 0;
_effective_offset = 0;
} //decode_instruction

bool isword() { return ( _b0 & 1 ); } // true if the instruction is dealing with a word, not a byte (there are several exceptions)
Expand Down Expand Up @@ -295,7 +295,10 @@ struct i8086
// The 8086 can address 0000:0000 .. ffff:ffff, which is 0 .. 0x10ffef.
// But it only has 20 address lines, so high memory area (HMA) >= 0x100000 references wrap to conventional memory.
// The only apps I've found that depend on wrapping are those produced by IBM Pascal Version 2.00.
// Microsoft LISP v5.10 (mulisp.exe) references HMA and works whether wrapping or not.
// Microsoft LISP v5.10 (mulisp.exe) references HMA and works whether the CPU wraps or not.
// Pass 3 (pas3.exe) of Microsoft FORTRAN77 V3.13 8/05/83 references HMA along with the apps it generates.
// The compiler generates good code without wrapping, but the apps it creates require wrapping to work.
// Artek Ada Compiler Ver. 1.25's linklib.exe and interpreter ai.exe both reference HMA but work without wrapping.
// This extra mask costs about 1% in performance but is more compatible.

return ( 0xfffff & flat );
Expand All @@ -307,7 +310,7 @@ struct i8086

uint16_t read_word( void * p )
{
if ( 0xffff == _final_offset )
if ( 0xffff == _effective_offset )
{
uint8_t *pb = (uint8_t *) p;
uint16_t lo = (uint16_t) * pb;
Expand All @@ -320,7 +323,7 @@ struct i8086

void write_word( void * p, uint16_t val )
{
if ( 0xffff == _final_offset )
if ( 0xffff == _effective_offset )
{
uint8_t *pb = (uint8_t *) p;
*pb = (uint8_t) ( val & 0xff );
Expand All @@ -345,12 +348,12 @@ struct i8086
tracer.Trace( "wrapped back to start of memory plus one in add_two_wrap\n" );
p = (uint16_t *) ( memory + 1 );
}
else if ( 0xfffe == _final_offset || 0xffff == _final_offset )
else if ( 0xfffe == _effective_offset || 0xffff == _effective_offset )
{
tracer.Trace( "_final_offset in add_two_wrap is %04x, p start is %p\n", _final_offset, p );
tracer.Trace( "_effective_offset in add_two_wrap is %04x, p start is %p\n", _effective_offset, p );
uint8_t * pb = (uint8_t *) p;
p = (uint16_t *) ( pb - 65536 );
_final_offset += 2;
_effective_offset += 2;
}

return p;
Expand Down Expand Up @@ -397,17 +400,17 @@ struct i8086
_bc += 1;
AddCycles( 4 );
int16_t offset = (int16_t) (int8_t) _pcode[ 2 ];
_final_offset = get_displacement() + offset;
return flat_address( get_displacement_seg(), _final_offset );
_effective_offset = get_displacement() + offset;
return flat_address( get_displacement_seg(), _effective_offset );
}

if ( 2 == _mod ) // 2-byte unsigned immediate offset from register(s)
{
_bc += 2;
AddCycles( 5 );
uint16_t offset = * (uint16_t *) ( _pcode + 2 );
_final_offset = get_displacement() + offset;
return flat_address( get_displacement_seg(), _final_offset );
_effective_offset = get_displacement() + offset;
return flat_address( get_displacement_seg(), _effective_offset );
}

if ( 6 == _rm ) // 0 == mod. least frequent. immediate pointer to offset
Expand All @@ -417,8 +420,8 @@ struct i8086
return flat_address( get_seg_value(), * (uint16_t *) ( _pcode + 2 ) );
}

_final_offset = get_displacement();
return flat_address( get_displacement_seg(), _final_offset ); // no offset; just a value from register(s)
_effective_offset = get_displacement();
return flat_address( get_displacement_seg(), _effective_offset ); // no offset; just a value from register(s)
} //get_rm_ptr_common

uint16_t * get_rm_ptr16()
Expand Down

0 comments on commit ea174e4

Please sign in to comment.