Page 2 of 2
Posted: Sat Feb 24, 2007 3:11 pm
by Alboin
Here's version 2.0 of inc\dec. (Attached)
Add this to main:
And this to base:
Code: Select all
void inc_dec_r8();
SPEED_UP unsigned short add16(unsigned short base,unsigned short adder);
SPEED_UP unsigned short sub16(unsigned short base,unsigned short subt);
SPEED_UP unsigned char sub8(unsigned char base,unsigned char subt);
SPEED_UP unsigned char add8(unsigned char base,unsigned char adder);
It does 8\16bit register inc's and dec's.
No, I'm not on any of those, actually. I'm more of a forums person myself. Uhh, what about the sourceforge forums for Open86? Also, there's private messages through osdev if it's not public.
Posted: Sat Feb 24, 2007 4:19 pm
by earlz
thanks for this..
the only problem I see is that that isn't just dec and inc though, it is a "group" it uses a modrm byte to determine what opcode it is..
there are 6 more opcodes in that one byte other than inc and dec so, evenutally I will support those and well...you should get the point..but anyway...
now then..
the inc_r16 and dec_r16 look good...
I think I'll have to write a tutorial of some sort for anyone to understand the modrm system...think I'll write something of some sort...
oh wait..you may have misread your opcode documents..that inc_r/8 should be inc_mod/rm8 mod rm bytes are bytes that consist of 3 fields of data: mod(2bits), rm(3bits), and extra(3bits)
unless mod is less than 4 then it refers to a memory address, I won't go over all of these different memory address computation combo's but basically what you are doing is assuming that mod is 4 which would be correct for what you written, but it doesn't check!
ok I will show you what that inc and dec would have looked like if I had done it..
(I describe things best in code..)
Code: Select all
void group_fe(){
mod_rm rm[1];
unsigned char *ptr;
unsigned char *ptr2;
unsigned char *to_be_used; //this is the contents of the interpreted modrm
unsigned int tmp;
ip++;
MemRead8(CS,ip,rm); //store rm because we need 'extra'(sometimes)
tmp=GetModRM_write8(&ptr); //note it isn't always write8 for each group!
//pointer now contains the memory address that should be used(unless tmp==opcode_specific)
if(tmp==0){ //is normal and ptr contains the memory address
ptr=(unsigned long)ptr+(unsigned long)core;
to_be_used=ptr;
}
if(tmp==OPCODE_SPECIFIC){
to_be_used=gregs8[rm[0].rm];
}
//actually you can ignore above this line!
//do opcode specific stuff...
switch(rm[0].extra){ //check opcode
case 0: //inc modrm8
//now you do your thing, except for instead of reg, you use *to_be_used;
tmp=flags->cf;
*to_be_used=add8(*to_be_used,1);
flags->cf=tmp;
//this one is inc!
break;
case 1: //dec modrm8
//now you do your thing with dec, except for instead of reg, you use *to_be_used;
//you fill out this one!
//this one is dec!
break;
default:
panic("Unsupported opcode! at rm\n");
break;
}
}
edit:
no, I didn't have anything private to say, just prefer IM for talking to one person..(different with multiple people)
Posted: Sat Feb 24, 2007 5:32 pm
by Alboin
A question on the above. Does:
Find what the argument is for the instruction? So if I had
It would return 0xb8000?
Are my assumptions correct?
Also, a design question: There is a group (#2
here) that consists of (C0..C1h) and (D0..D3h). Would I be able to just create one group for all of these, and then connect all of their opcodes to the one group in main?
Posted: Sat Feb 24, 2007 6:07 pm
by earlz
actually there is no [0xb8000] in the 8086 instruction set
so I'll use this:
Code: Select all
mov ax,0xB800
mov ds,ax
mov bx,0
mov [bx],byte 12
then GetModRM_write8(&ptr) will add (DS<<4)+bx and put that in *ptr..
another thing it will do is make sure that you can write to that address...(hence you don't have to worry about it..)
what GetModRM.. returns is basically a control/error code, if it is 0 then everything is normal and &ptr is the target memory; if it returns OPCODE_SPECIFIC then it's not sure what to do because it is opcode specific, but under most(but not all) it should use a general register instead so the rm field contains what register to use(8 bit)
as far as those groups..
I really have no idea, I don't really understand that question...
Posted: Sat Feb 24, 2007 10:29 pm
by Alboin
Okay, after getting segfaults for an hour, I think I got somewhat of a draft of the shr and shl instructions. They are in a group like function, as suggested. It is attached. (I do believe that I set all of the required flags..maybe?....Please alert me if I missed anything....)
Posted: Sat Feb 24, 2007 11:11 pm
by earlz
dear God! what a complicated group!
there is only a bit of something wrong with your modrm code..
because there are two different bitsizes of where modrm points, you need to do this:
if(bit_type= = 8 ){
tmp=GetModRM_write8(&ptr);
}else{
tmp=GetModRM_write16(&ptr);
}
also when checking for what bitsize, if the bit size is either one or the other, then it would probably be faster to do a if(op ==0xD0 ||...){ bit_size=8;}ELSE{ bit_size=16} this would make it a tiny bit faster...
(I don't know if you can do else with that wierd no {}'s syntax of if..)
and you set most of the hard flags..
here is some simple precoded things for you, and ZF should be a bit obvious
Code: Select all
inline unsigned char shr8(unsigned char op1,unsigned char op2) {
unsigned char tmp_count = op2 & 0x1f;
unsigned char tmp_dest = op1;
while(tmp_count > 0) {
op1 = op1 >> 1;
unsigned char lsb = tmp_dest & 0x01;
flags->cf = lsb;
tmp_count--;
}
if(op2 == 1) {
unsigned char msb = tmp_dest & 0x80;
flags->of = msb;
}
CalculatePF8(op1); //this will set PF for you
CalculateSF8(op1); //this will set SF for you
if(op1==0){flags->zf=1;}else{flags->zf=0;}
return op1;
}
inline unsigned short shr16(unsigned short op1,unsigned char op2) {
unsigned char tmp_count = op2 & 0x1f;
unsigned short tmp_dest = op1;
while(tmp_count > 0) {
op1 = op1 >> 1;
unsigned char lsb = op1 & 0x01;
flags->cf = lsb;
tmp_count--;
}
if(tmp_count == 1) {
unsigned short msb = tmp_dest & 0x8000;
flags->of = msb;
}
CalculatePF16(op1); //this will set PF for you
CalculateSF16(op1); //this will set SF for you
if(op1==0){flags->zf=1;}else{flags->zf=0;}
return op1;
}
where are you getting your documentation? if your having trouble finding which flags should be set, then you can maybe try this little website on for size..
http://www.ousob.com/ng/iapx86/index.php ..it is my favorite..
I think I should eventually document that helpers.c file...
just found a bit of a bug...you kept to_be_used as a char * even though it is used as a 16bit data type... the simplest way to fix that would just be put some casting on where it should be 16bit
btw did you test that?(beyond segmentation faults)
edit:
I lol at your website...very random...and I just happen to like random....
Posted: Sun Feb 25, 2007 3:08 pm
by Alboin
Okay, I think I got the bugs fixed....I think it works....I tested it..You might want to test it to double check.....It''s attached....Why am I writing like this?
What other instructions\group are next in line of importance, so I can implement them? I think I've gotten the system somewhat down.
Posted: Sun Feb 25, 2007 4:27 pm
by earlz
...it looks pretty good, the only thing I ask is that for things like the set_flags8 thing, use the attribute SPEED_UP on the function, this is replaced with inline if memory isn't a problem, or is left outlined if we have LOW_MEMORY defined(this is for future use mostly)
do you know how to test these?
what you can do is make a binary test file(from asm) and then copy it to the trunk and rename/replace it to tester.bin..then just type "open86 test_config.o86" and it will run that file
and
does open86 run on your pc!? I would be very suprised if it does, as I didn't think it was built portably enough to work in 64bit..
Code: Select all
else if(bit_type == 16)
*to_be_used = shl16((unsigned short)*to_be_used, iw);[/code
does that work? does shl16 returning unsigned short, override the default type of to_be_used(which is unsigned char) otherwise it will still only write one byte rather than a word...
edit:
as far as next things to do..
there are the things like movs, and other string operations(already have cmps implemented) btw, no need to worry about rep stuff..
umm..immediant maths like
sub modrm16, imm16
and add modrm16, imm16
as far as your shift stuff, I will probably move it to a different file..(it will be in bitwise.c)
edit2:
Could you please provide the InstallOp things for that group..I'm not for sure if it takes from C0 to D0 or what..?
Posted: Sun Feb 25, 2007 4:42 pm
by Alboin
hckr83 wrote:do you know how to test these?
what you can do is make a binary test file(from asm) and then copy it to the trunk and rename/replace it to tester.bin..then just type "open86 test_config.o86" and it will run that file
and does open86 run on your pc!? I would be very suprised if it does, as I didn't think it was built portably enough to work in 64bit..
Of course it does! How else would I be testing these instructions? (Although, I am using an SVN version from a day or two ago.)
hckr83 wrote:
Code: Select all
else if(bit_type == 16)
*to_be_used = shl16((unsigned short)*to_be_used, iw);
does that work? does shl16 returning unsigned short, override the default type of to_be_used(which is unsigned char) otherwise it will still only write one byte rather than a word...
Oh.....I see your point......What about using a void* for to_be_used?
hckr83 wrote:
edit:
as far as next things to do..
there are the things like movs, and other string operations
Okay, I'll start working on string operations. Sounds good to me.
Posted: Sun Feb 25, 2007 4:45 pm
by earlz
could you provide the InstallOp code things for that group?
I don't entirely understand how that group works, is it just a few values or is it completely from C0 to D3?
Posted: Sun Feb 25, 2007 4:46 pm
by Alboin
Here ya go:
Code: Select all
InstallOp(0xC0,group_c0_through_d3);
InstallOp(0xC1,group_c0_through_d3);
InstallOp(0xD0,group_c0_through_d3);
InstallOp(0xD1,group_c0_through_d3);
InstallOp(0xD2,group_c0_through_d3);
InstallOp(0xD3,group_c0_through_d3);
Edit: Wow, MOVS, STOS, SCAS, and LODS have easy opcodes....I'm pretty excited.....
Posted: Sun Feb 25, 2007 5:11 pm
by earlz
you can look at sub_add.c and then use cmps() as a template...
the only thing to make sure to do is rather than use DS, use CurrentSegment..this will allow me to later implement segment overrides
edit:
I will be away from here a bit(2 weeks) so if you could, post source code on my SF.net project page..(in the forum there) ...it is a bit easier and faster for me to access there...