VOGONS


Powerpc dynrec for wii

Topic actions

First post, by wisk

User metadata
Rank Newbie
Rank
Newbie

Hello,

I'm working on a port of dosbox on wii (I know, it was already done, but it's for a school project).
To make it go faster, I'm writing a dynrec for powerpc, but I have some trouble with it :
I can make it draw the prompt but I'm unable to write anything with the keyboard, neither mount drive.

I was trying to find out where the problem was, I think the reason is because some callback like 0xd have never been called.

I wonder if someone could help me, I need some information about how key event is triggered (I was unable to find how it works with CBind).

Thanks 😀

Reply 1 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

So it works with core=normal but not with core=dynamic, right?
Just disable a bunch of instructions in decoder.h (they'll be handled by
the normal core then) until it works, then see if there's something special
about the instruction that causes trouble.

Reply 2 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Thank you for the advice, it was very helpful.
I manage to make the keyboard work, but I still have a problem with mount.

Reply 3 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Finally, I figure out the main problem, it's about the endian.
Wii is in big endian, so I defined WORDS_BIGENDIAN 1

When MOUNT is called, DOSBox executes this piece of code

static Bit8u exe_block[]={
[b]0xbc,0x00,0x04, //MOV SP,0x400 decrease stack size[/b]
0xbb,0x40,0x00, //MOV BX,0x040 for memory resize
0xb4,0x4a, //MOV AH,0x4A Resize memory block
0xcd,0x21, //INT 0x21
//pos 12 is callback number
0xFE,0x38,0x00,0x00, //CALLBack number
0xb8,0x00,0x4c, //Mov ax,4c00
0xcd,0x21, //INT 0x21
};

But I get this

gen_mov_word_to_reg (dest_reg=HOST_GPR3, data=0x900038e9, dword=false)
at /home/wisk/Projects/dosboxwii/trunk/dosbox/src/cpu/core_dynrec/risc_ppc750.h:225
225 CACHED(LIS_RT_SI(FC_TMP_REG1, (Bit32u)data >> 16));
(gdb) x/x data
0x900038e9: 0x[b]0004[/b]bb40

Am I supposed to do the convertion myself or there is something missing at this line ?

// fetch a word, val points to the code location if possible,
// otherwise val contains the current value read from the position
static bool decode_fetchw_imm(Bitu & val) {
if (decode.page.index<4095) {
HostPt tlb_addr=get_tlb_read(decode.code);
// see if position is directly accessible
if (tlb_addr) {
[b]val=(Bitu)(tlb_addr+decode.code);[/b]
decode_increase_wmapmask(2);
decode.code+=2;
decode.page.index+=2;
return true;
}
}
// not directly accessible, just fetch the value
val=decode_fetchw();
return false;
}

Reply 4 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Hm there's currently no big-endian recompiler backend in dosbox, so this may
indeed give some headaches...

As a quick workaround just disable that functionality, like use

static bool decode_fetchw_imm(Bitu & val) {
val=decode_fetchw();
return false;
}

and similar for the dword function.

Reply 5 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Alright, now dosbox is able to call DOS_21Handler.
This function calls DOS_Execute which returns true so it's OK, but it still doesn't work, for instance : if I execute "INTRO" command, nothing happens.
It works only if dosbox doesn't use dyn_mov_byte_imm and dyn_mov_word_imm (in other word, if I comment 0xb[0-9a-f] cases in decoder.h).
I wonder how dosbox reachs the entrypoint of a program.

BTW Have you a trick to set a breakpoint at the entrypoint of a program (I'm using gdb) ?

Reply 6 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

BTW Have you a trick to set a breakpoint at the entrypoint of a program (I'm using gdb) ?

What exactly do you want to do, like do you have a debugger-enabled build
that you can run on the wii and you want to put a breakpoint on the target
of int21/4b (program start) for the recompiled code?

If you're using the dosbox debugger along with a recompiling core, be sure
to change

block=CreateCacheBlock(chandler,ip_point,32);

the 32->1 so breakpoints can be reached at instruction boundaries and not
block boundaries.

Reply 7 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

What exactly do you want to do, like do you have a debugger-enabled build
that you can run on the wii and you want to put a breakpoint on the target
of int21/4b (program start) for the recompiled code?

That's it.
I set breakpoints at DOS_21Handler and DOS_Execute and PROGRAMS_Handler .
DOS_21Handler is called twice, one time for execution and one time for termination.
DOS_Execute is called with good parameters.
But PROGRAMS_Handler is never called, that's why DOSBox can't mount any drive.
I guess it never set core_dynrec.callback= 6, and I wonder why.

Reply 8 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Can you trace this with the dosbox debugger? Like put a bpint at 21 for ah=4b,
then type mount and trace into the call. There should be an sti, the callback
and the iret.
Log the BlockReturn value that you get from runcode, that should have the
Callback type and core_dynrec.callback contains the actual number of the
callback.

Reply 9 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie
Can you trace this with the dosbox debugger? Like put a bpint at 21 for ah=4b, then type mount and trace into the call. There sh […]
Show full quote

Can you trace this with the dosbox debugger? Like put a bpint at 21 for ah=4b,
then type mount and trace into the call. There should be an sti, the callback
and the iret.
Log the BlockReturn value that you get from runcode, that should have the
Callback type and core_dynrec.callback contains the actual number of the
callback.

Because of termcaps, I can't compile DOSBox with debug feather, however I can use gdb.

By "sti" you mean CPU_STI function ?

I set the bp (gdb) b DOS_21Handler if reg_ah == 0x4b […]
Show full quote

I set the bp
(gdb) b DOS_21Handler if reg_ah == 0x4b

Continue
(gdb) c

breakpoint is reached because of mount presents in autoexec.bat
Breakpoint 2, DOS_21Handler () at /home/wisk/Projects/dosboxwii/trunk/dosbox/src/dos/dos.cpp:65
65 if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) {
Current language: auto; currently c++

ah is egal to 4b
(gdb) p/x reg_ah
$2 = 0x4b

(gdb) n
Until a exit the function
...
Now we call runcode
we find a call to CPU_RET

(gdb) p/x new_cs
$5 = 0x17e
(gdb) p/x new_ip
$6 = 0x100
That's look weird...

return 0

exe_block code

CPU_Interrupt (reg_ah = 0, termination)

Reply 10 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Because of termcaps, I can't compile DOSBox with debug feather, however I can use gdb.

Do you have a debugger-enabled build for linux/windows at hand? As it's
quite nice to actually know what *should* be executed 😀

By "sti" you mean CPU_STI function ?

Yes, the instructions executed for mount should be INT, then STI, callback, IRET.

Can you utilize the LOG_MSG functionality? As tracing the cs:ip in core_dynrec.cpp
would be very handy.

Reply 11 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Do you have a debugger-enabled build for linux/windows at hand? As it's
quite nice to actually know what *should* be executed

Sure, I'm using powerpc-gekko-gdb, it's a gdb version for wii.
Wii is connected to my PC throught usbgecko.

Yes, the instructions executed for mount should be INT, then STI, callback, IRET.

Could you tell me where in the source code dosbox writes x86-16 assembly which corresponds with what you said above ?

Can you utilize the LOG_MSG functionality? As tracing the cs:ip in core_dynrec.cpp
would be very handy.

Yep, I'll try it.

Reply 12 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

The INT is from the actual instruction, whereas the STI/callback/IRET
comes from the int21 handler.
See dos.cpp:

callback[1].Install(DOS_21Handler,CB_INT21,"DOS Int 21");

which sets up the int21 handler, and see callback.cpp:

	case CB_INT21:
phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI
if (use_cb) {
phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction
phys_writeb(physAddress+0x02,(Bit8u)0xCB); //A RETF Instruction
return (use_cb?7:3);

Btw. what sources are you using exactly?

Reply 13 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Alright, so if I comment all mov (0xb?) in decoder.h, dosbox calls CPU_Interrupt, CPU_STI, PROGRAMS_Handle(the callback), CPU_IRET.
It looks like dyn_mov_byte_imm and dyn_mov_word_imm are broken, do you have an idea about where the problem is ?

Reply 14 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Thank you for your help. 😀

Btw. what sources are you using exactly?

0.73

Reply 15 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

It looks like dyn_mov_byte_imm and dyn_mov_word_imm are broken

Both or just the word variant?

Reply 16 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Actually, the problem comes from dyn_mov_byte_imm only.

Reply 17 of 27, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Wisk, can you please post a few lines about how far you got until now?

Reply 18 of 27, by wisk

User metadata
Rank Newbie
Rank
Newbie

Here's the whole file.

Reply 19 of 27, by fishbone

User metadata
Rank Newbie
Rank
Newbie

Hi,
I tried to build DOSBox for Wii with this file, but if setting cpu to dynamic, dosbox crashes immediately after start. normal mode works.
At first i couldn't compile, because SPR_LE and SPR_CTR are undefined so i #defined it to HOST_GPR11 and 12.
i additionally set the endianess to big endian and made the change mentioned above in decoder_basic.h, but it does not work.

wd, did you already look into the file?
what did i wrong?
wisk, can you give me the whole source code?

fishbone