diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 96d6690df..480c5faa3 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -88,4 +88,4 @@ %type c %type e16 u8 u7 u6 u5 u4 u2 u1 -%type nb ds bda bdl lia lil +%type nb ds bda bdl lia lil spr_num diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 3f79ca86c..e1fb3fdf0 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -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_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_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_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); } @@ -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_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_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_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_LEV u7 { emit4($1 | ($2<<5)); } @@ -237,4 +237,14 @@ lia $$ = target & 0x03FFFFFD; } ; - + +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); + } + ; diff --git a/plat/qemuppc/boot.s b/plat/qemuppc/boot.s index 2dd9a4c5c..ac3227dc9 100644 --- a/plat/qemuppc/boot.s +++ b/plat/qemuppc/boot.s @@ -13,22 +13,14 @@ .sect .text begtext: - ! This code is placed at the beginning of the ELF executable and is the - ! first thing that runs. + ! This code is the first thing that runs. The booloader + ! 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+(4*argc) env (X quads) - ! sp+4+(4*argc) NULL - ! sp+4 argv (argc quads) + ! sp+8 environment pointer + ! sp+4 argv as a pointer ! sp argc - ! - ! The ACK actually expects: - ! - ! sp+8 argc - ! sp+4 ptr to argv - ! sp ptr to env li32 r3, __openfirmware_ptr stw r5, 0(r3) @@ -47,15 +39,23 @@ begtext: ! falls through .define __exit -.extern __exit .define EXIT -.extern 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 -.extern _openfirmware_call _openfirmware_call: lwz r3, 0(sp) li32 r4, __openfirmware_ptr @@ -66,15 +66,10 @@ _openfirmware_call: ! Define symbols at the beginning of our various segments, so that we can find ! them. (Except .text, which has already been done.) -.sect .data; begdata: .sect .rom; begrom: +.sect .data; begdata: .sect .bss; begbss: -! Some magic data. All EM systems need these. - -.define _errno -.comm _errno, 4 ! Posix errno storage - ! The argv and env arrays. .sect .rom @@ -82,6 +77,12 @@ argv: .data4 exename, 0 envp: .data4 0 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 .comm .trppc, 4 ! ptr to user trap handler .comm .ignmask, 4 ! user trap ignore mask