Merge pull request #27 from kernigh/pr-qemu-doze

Teach qemuppc to halt the cpu on _exit().
This commit is contained in:
David Given 2016-12-11 23:17:12 +01:00 committed by GitHub
commit bf2e0be69a
3 changed files with 38 additions and 27 deletions

View file

@ -88,4 +88,4 @@
%type <y_word> c %type <y_word> c
%type <y_word> e16 u8 u7 u6 u5 u4 u2 u1 %type <y_word> e16 u8 u7 u6 u5 u4 u2 u1
%type <y_word> nb ds bda bdl lia lil %type <y_word> nb ds bda bdl lia lil spr_num

View file

@ -34,7 +34,7 @@ operation
| OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); }
| OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); }
| OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); }
| OP_RT_SPR GPR ',' SPR { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); }
| OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); }
| OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } | OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); }
| OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); }
@ -53,7 +53,7 @@ operation
| OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); }
| OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
| OP_RS_RA_SH6_C c GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | (($7&0x20)>>4)); } | OP_RS_RA_SH6_C c GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | (($7&0x20)>>4)); }
| OP_RS_SPR SPR ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } | OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); }
| OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
| OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); }
| OP_LEV u7 { emit4($1 | ($2<<5)); } | OP_LEV u7 { emit4($1 | ($2<<5)); }
@ -238,3 +238,13 @@ lia
} }
; ;
spr_num
: SPR { $$ = $1; }
| absexp
{
if (($1 < 0) || ($1 > 0x3ff))
serror("spr number out of range");
/* mfspr, mtspr swap the low and high 5 bits */
$$ = ($1 >> 5) | (($1 & 0x1f) << 5);
}
;

View file

@ -13,22 +13,14 @@
.sect .text .sect .text
begtext: begtext:
! This code is placed at the beginning of the ELF executable and is the ! This code is the first thing that runs. The booloader
! first thing that runs. ! passes the Open Firmware pointer in r5.
! !
! On entry, the stack looks like this: ! We keep the bootloader's stack. The ACK expects:
! !
! sp+... NULL ! sp+8 environment pointer
! sp+8+(4*argc) env (X quads) ! sp+4 argv as a pointer
! sp+4+(4*argc) NULL
! sp+4 argv (argc quads)
! sp argc ! sp argc
!
! The ACK actually expects:
!
! sp+8 argc
! sp+4 ptr to argv
! sp ptr to env
li32 r3, __openfirmware_ptr li32 r3, __openfirmware_ptr
stw r5, 0(r3) stw r5, 0(r3)
@ -47,15 +39,23 @@ begtext:
! falls through ! falls through
.define __exit .define __exit
.extern __exit
.define EXIT .define EXIT
.extern EXIT
__exit: __exit:
EXIT: EXIT:
b EXIT ! Halt the CPU. This code halts the default G3 emulation of
! qemu-system-ppc. It's wrong for some other CPU models.
#define hid0 0x3f0
#define mfmsr(r) [[31<<26]|[[r]<<21]|0x0a6]
#define mtmsr(r) [[31<<26]|[[r]<<21]|0x124]
mfspr r3, hid0
oris r3, r3, 0x00e0 ! set DOZE, NAP, SLEEP
mtspr hid0, r3 ! in hid0
.data4 mfmsr(3)
oris r3, r3, 0x0004 ! set POW
.data4 mtmsr(3) ! in msr
b EXIT ! If we failed to halt, then spin.
.define _openfirmware_call .define _openfirmware_call
.extern _openfirmware_call
_openfirmware_call: _openfirmware_call:
lwz r3, 0(sp) lwz r3, 0(sp)
li32 r4, __openfirmware_ptr li32 r4, __openfirmware_ptr
@ -66,15 +66,10 @@ _openfirmware_call:
! Define symbols at the beginning of our various segments, so that we can find ! Define symbols at the beginning of our various segments, so that we can find
! them. (Except .text, which has already been done.) ! them. (Except .text, which has already been done.)
.sect .data; begdata:
.sect .rom; begrom: .sect .rom; begrom:
.sect .data; begdata:
.sect .bss; begbss: .sect .bss; begbss:
! Some magic data. All EM systems need these.
.define _errno
.comm _errno, 4 ! Posix errno storage
! The argv and env arrays. ! The argv and env arrays.
.sect .rom .sect .rom
@ -82,6 +77,12 @@ argv: .data4 exename, 0
envp: .data4 0 envp: .data4 0
exename: .asciz 'qemuppc.img' exename: .asciz 'qemuppc.img'
! Some magic data. All EM systems need these.
.sect .bss
.define _errno
.comm _errno, 4 ! Posix errno storage
.define .trppc, .ignmask .define .trppc, .ignmask
.comm .trppc, 4 ! ptr to user trap handler .comm .trppc, 4 ! ptr to user trap handler
.comm .ignmask, 4 ! user trap ignore mask .comm .ignmask, 4 ! user trap ignore mask