# ------------------------------------------------------------------- # GPU/DSP (c) Copyright 1995 KKP & Nat! # ------------------------------------------------------------------- # These are some of the results/guesses that Klaus and I (Nat!) found # out about the Jaguar. Since we are not under NDA or anything from # Atari we feel free to give this to you for educational purposes # only. # # Please note, that this is not official documentation from Atari # or derived work thereof (both of us have never seen the Atari docs) # and Atari isn't connected with this in any way. # # Please use this informationphile as a starting point for your own # exploration and not as a reference. If you find anything innacurate, # missing, needing more explanation etc. by all means please write # to us: # nat@zumdick.rhein-main.de # or # kkp@gamma.dou.dk # # If you could do us a small favor, don't use this information for # those lame flamewars on r.g.v.a or the mailing list. # # HTML soon ? # ------------------------------------------------------------------- # $Id: risc_doc.txt,v 1.2 1995/12/08 18:48:09 nat Exp $ # ------------------------------------------------------------------- 1 RISCy Buisness The RISC's has 2 register banks of 32 registers each. There are the Current and the Alternative register bank. Register R31 is the stack pointer and normally R0 is initilized to 0 (Zero). G_FLAGS and D_FLAGS are the status register. The first 5 bits contains the Carry, Zero and Minus flags (I THINK). Bit 3 IMASK (Interupt disable?) Bit 5 Interupt level 1 enable Bit 10 Interupt level 1 pending? Bit 14 is the register bank selection. Switch between the registerbanks is done: movei #G_FLAGS,r1 ; Status flags or movei #D_FLAGS,r1 ; Status flags load (r1),r0 bset #14,r0 store r0,(r1) ; Switch the GPU/DSP to bank 1 Register R31 is used by the RISC's as stack pointers. They only seems to be used by interupts. See the section on interupts. 1.0 Move instructions move Rn,Rm move PC,Rn movei #xxxxxxxx,Rn load (Rn),Rn load (Rm+n),Rn * Rm = R14 | R15 ! load (Rm+Ri),Rn * Rm = R14 | R15 ! loadb (Rn),Rn * load byte loadw (Rn),Rn * Load word loadp (Rn),Rn * Load Phrase (GPU only) store Rn,(Rn) store Rn,(Rm+n) * Rm = R14 | R15 ! store Rn,(Rm+Ri) * Rm = R14 | R15 ! storeb Rn,(Rn) * Store Byte storew Rn,(Rn) * Store Word storep Rn,(Rn) * Store Phrase (GPU only) moveta Rn,Rn * move to alternative register bank movefa Rn,Rn * move from alternative register bank 1.1 Logical Instructions or Rn,Rn xor Rn,Rn and Rn,Rn 1.2 Bitoperation Instructions bset #,Rn bclr #,Rn btst #,Rn 1.3 Shift Instructions shlq #xx,Rn shrq #xx,Rn sharq #xx,Rn ror Rn,Rn rorq #xx,Rn 1.4 Arith. Instructions mult Rn,Rn imult Rn,Rn mmult Rn,Rn imultn Rn,Rn imacn Rn,Rn resmac Rn div Rn,Rn * exec seems to use max 4 i-cycles add Rn,Rn addc Rn,Rn * add with carry addq #xx,Rn addqt #xx,Rn * add quick, test result addqmod #xx,Rn * add quick, take modulo sub Rn,Rn subc Rn,Rn * add with carry subq #xx,Rn subqt #xx,Rn * sub quick, test result subqmod #xx,Rn * sub quick, take modulo cmp Rn,Rn cmpq #xx,Rn neg Rn not Rn abs Rn 1.5 Program Structure Instructions jump CC,(Rn) jump (Rn) jr CC,xxxxxx jr xxxxxxx nop 1.6 Condition Codes Condition codes CC can be any of CC (%00100) CS (%01000) EQ (%00010) MI (%11000) NE (%00001) PL (%10100) HI (%00101) T (%00000). They are used together with the jump instructions... 2.0 Restrictions 'JR+MOVEI', 'JUMP+MOVEI', 'JR+JR', 'JR+JUMP', 'JUMP+JR', 'JUMP+JUMP', 'JR+MOVE PC', 'JUMP+MOVE PC' IMULTN must be followed by a IMACN (Error displayed) IMACN must be followed by a IMACN or RESMAC (Error displayed) RESMAC must be preceed by a IMACN (Error displayed) a NOP is inserted between LOAD+MMULT and STORE+MMULT (Warning displayed). I don't know if LOADB+MMULT, LOADW+MMULT, LOADP+MMULT, ... are valid or not. Currently, it's not tested... 3.0 Instruction Encoding Most instructions are only 2 bytes long. This means that 4 instructions can be pulled from RAM in one memory access!! This also makes the code extremly tight, which is of optimum concern when writing cartridge based programs. One more than 2 byte instruction is the movei #x,Rn which have the 32 bit constant just after the 2 byte instruction, this saves a lot of time and space over other RISC's. The ARM forexample uses 4 32 bit instructions to fill a register (8 bit at a time). The SPARC 2 32 bit instructions. 3.2 Instruction Encoding All instructions uses the top 6 bits to encode the instruction. The 2 operand instructions split the remainder of the 16 bits into 2 5 bit fields, the source (quick or register) and the destination register. 3.2.1 The Implied Instructions iiiiii 0000000000 /\ /\ || |_============== room for extensions || \`======================= instruction The Implied instruction are nop! 3.2.2 The 1 Operand Instructions iiiiii 00000 ddddd <====== destination register /\ /\ || |_================ room for extensions || \`======================= instruction The one operand instructions are: neg R0 not R1 abs R2 resmac R3 3.2.3 The 2 Operand Instructions Most instructions are 2 operand and follow this pattern. The register to register instructions use the sssss and ddddd to specify source and destination registers, as add r1,r0. In the quick to register instructions the sssss field is used to hold a constant, as asl #3,r0 where the constans is between 1 and 32 and moveq #0,d2 where the constant is between 0 and 31. iiiiii sssss ddddd <====== destination register /\ /\ || |_================ source (quick or register) || \`======================= instruction Examples of 2 operand instructions are: move R1,R2 bset #31,R2 etc... 3.2.4 The movei Instruction The movei instruction are very special! This instruction is the only 6 byte instruction, that is what makes it special. The instruction word follow the general structure, iiiiii 00000 ddddd <====== destination register /\ /\ || |_================ room for extensions || \`======================= instruction ($98) but the 32 bit constant that is to be loaded into the destination register followes the instruction +-------------+ +------------+ +------------+ | Movei Rn | | Lower word | | Upper word | +-------------+ +------------+ +------------+ 3.2.5 The Load & Store Instructions Most instructions are 2 operand and follow this pattern. iiiiii ppppp ddddd <====== destination register /\ /\ || |_================ indirect register || \`======================= instruction 3.2.5.1 Addressing Modes For Load/Store Byte/Word/Phrase All load and store instructions support register indirect addressing, which is written (Rn). This means that you can load the memory location pointed to by a register into yet another register (or the same). 3.2.5.2 Addressing Modes For Load/Store Longword Together with the Load/Store longword instructions, there are other addressing modes. Called: * indexed register indirect addressing, which is written (Rn+Rm), * register indirect addressing w. offset, which is written (Rn+xx), In these addressing modes Rn _have_ to be R14 or R15! fx: load (r1+r2),r0 store r0,(r1+16) 3.2.5.3 Load/Store Phrase (GPU Only) The GPU has an direct 64 bit (Phrase) interface to the main memory. The loadp/storep instructions access this memorys full width. The lower part of the phrase pointed to by the (Rp) goes from/to the register specified, the other part of the phrase is in G_HIDATA ( 0xF02118 ) /* GPU Bus Interface high data */ fx: store r0,(rp) 3.2.6 The Program Control Instructions Most Program Control instructions follow this pattern: iiiiii ddddd ccccc <====== Condition Vector /\ /\ || |_================ source (quick or register) || \`======================= instruction The ddddd field can either speify an offset (jr instruction) or a register containing a absolute address (jump instruction), all jump instructions are conditional. 3.2.6.1 Condition Codes Condition codes ccccc can be any 5 bit vector, here are some ready defined usefull values: CC (%00100 CS (%01000) EQ (%00010) MI (%11000) NE (%00001) PL (%10100) HI (%00101) T (%00000) Examples of Program Control instructions: jump mi, (r5) jr ne, exit jr t, loop ; loop forever jr loop ; loop forever jump (r5) 3.2.7 Modulo Aritimetics (DSP only) The instructions addqmod and subqmod are modular with the size specified in the D_MOD (0xF1A118) /* DSP Modulo Instruction Mask */ The mask register contains a mask that is applied to the register after the add operation, as in the following two step movei #%111111,r1 loop: addq #4,r0 and r1,r0 ... jr loop With the modulo register this can be written: movei #D_MOD,r3 movei #~%111111,r1 store r1,(r3) loop: addq #4,r0 ... jr loop This is an obvious win! - you save a cycle each loop! Instructions are subqmod, addqmod 3.2.8 Multiply and Multiply-Accumulate Locations D_MACHI EQU BASE+$1A120 ; DSP Hi byte of MAC operations 3.2.9 Matrix Multiply Locations D_MTXC EQU BASE+$1A104 ; DSP Matrix Control D_MTXA EQU BASE+$1A108 ; DSP Matrix Address G_MTXC EQU BASE+$2104 ; GPU Matrix Control G_MTXA EQU BASE+$2108 ; GPU Matrix Address 3.2.10 Divide Locations D_REMAIN EQU BASE+$1A11C ; DSP Division Remainder D_DIVCTRL EQU BASE+$1A11C ; DSP Divider control G_REMAIN EQU BASE+$211C ; GPU Division Remainder G_DIVCTRL EQU BASE+$211C ; GPU Divider control 3.2.20 Strange things: 3.3 Instruction numbers Mnemonic Mode iiiiii sssss ddddd hex Notes -------------------------------------------------------------- ADD Rs,Rd 000000 sssss ddddd $00 ADDC Rs,Rd 000001 sssss ddddd $04 ADDQ #q,Rd 000010 qqqqq ddddd $08 q is [32, 1..31] ADDQT #q,Rd 000011 qqqqq ddddd $0C q is [32, 1..31] SUB Rs,Rd 000100 sssss ddddd $10 SUBC Rs,Rd 000101 sssss ddddd $14 SUBQ #q,Rd 000110 qqqqq ddddd $18 q is [32, 1..31] SUBQT #q,Rd 000111 qqqqq ddddd $1C q is [32, 1..31] NEG Rd 001000 00000 ddddd $20 AND Rs,Rd 001001 sssss ddddd $24 OR Rs,Rd 001010 sssss ddddd $28 XOR Rs,Rd 001011 sssss ddddd $2C NOT Rd 001100 00000 ddddd $30 BTST #q,Rd 001101 qqqqq ddddd $34 q is [0..31] BSET #q,Rd 001110 qqqqq ddddd $38 q is [0..31] BCLR #q,Rd 001111 qqqqq ddddd $3C q is [0..31] MULT Rs,Rd 010000 sssss ddddd $40 IMULT Rs,Rd 010001 sssss ddddd $44 IMULTN Rs,Rd 010010 sssss ddddd $48 RESMAC Rd 010011 00000 ddddd $4C IMACN Rs,Rd 010100 sssss ddddd $50 DIV Rs,Rd 010101 sssss ddddd $54 ABS Rd 010110 00000 ddddd $58 $5C SHLQ #q,Rd 011000 qqqqq ddddd $60 q is [32, 1..31] SHRQ #q,Rd 011001 qqqqq ddddd $64 q is [32, 1..31] $68 SHARQ #q,Rd 011011 qqqqq ddddd $6C q is [32, 1..31] ROR Rs,Rd 011100 sssss ddddd $70 RORQ #q,Rd 011101 qqqqq ddddd $74 q is [32, 1..31] CMP Rs,Rd 011110 sssss ddddd $78 CMPQ #q,Rd 011111 qqqqq ddddd $7C q is [0..31] DSP SUBQMOD #q,Rd 100000 qqqqq ddddd $80 q is [32, 1..31] $84 MOVE Rs,Rd 100010 sssss ddddd $88 MOVEQ #q,Rd 100011 qqqqq ddddd $8C q is [0..31] MOVETA Rs,Rd 100100 sssss ddddd $90 MOVEFA Rs,Rd 100101 sssss ddddd $94 MOVEI #c32,Rd 100110 00000 ddddd $98 followed by a 32 bit const LOADB (Rp),Rd 100111 ppppp ddddd $9C LOADW (Rp),Rd 101000 ppppp ddddd $A0 LOAD (Rp),Rd 101001 ppppp ddddd $A4 GPU LOADP (Rp),Rd 101010 ppppp ddddd $A8 Load Phrase LOAD (R14+n),Rd 101011 nnnnn ddddd $AC LOAD (R15+n),Rd 101100 nnnnn ddddd $B0 STOREB Rs,(Rp) 101101 ppppp sssss $B4 STOREW Rs,(Rp) 101110 ppppp sssss $B8 STORE Rs,(Rp) 101111 ppppp sssss $BC GPU STOREP Rs,(Rp) 110000 ppppp sssss $C0 Store Phrase STORE Rs,(R14+n) 110001 nnnnn sssss $C4 STORE Rs,(R15+n) 110010 nnnnn sssss $C8 MOVE PC,Rn 110011 00000 ddddd $CC JUMP CC,(Rd) 110100 ddddd ccccc $D0 JR CC,q 110101 qqqqq ccccc $D4 MMULT Rs,Rd 110110 sssss ddddd $D8 $DC $E0 NOP 111001 00000 00000 $E4 LOAD (R14+Ri),Rd 111010 iiiii ddddd $E8 LOAD (R15+Ri),Rd 111010 iiiii ddddd $EC STORE Rs,(R14+Ri) 110001 iiiii sssss $F0 STORE Rs,(R15+Ri) 110010 iiiii sssss $F4 $F8 DSP ADDQMOD #q,Rd 111111 qqqqq ddddd $FC q is [32, 1..31] 4.0 Interupts The GPU and the DSP uses an interupt scheme that looks a lot like the 56000's way of handling interupts. In the lowest part of each processors memory the interupt entry points are. There are 16 bytes for each interupt. This should be enough to jump into the real interupt handler. ( If this works like on the 56000 it should be possible to have Fast Interupts, where the CPU returns automatically when the 16 bytes have been executed and no jump instructions have been executed ). For the DSP it looks like this: 000000 Reset (or DSP control interupt) 000010 I2S Interupt Enable interupts I2S: movei #D_FLAGS,r1 ; load dsp flags to go to bank 1 load (r1),r0 bset #5,r0 ; enable I2S interrupt store r0,(r1) ; save dsp flags Handle i2s interupts i2s_isr: movei #D_FLAGS,r30 ; get flags ptr load (r30),r12 bclr #3,r12 ; clear IMASK load (r31),r28 ; get last instruction address bset #10,r12 ; clear I2S interrupt addq #2,r28 ; point at next to be executed addq #4,r31 ; update the stack pointer ... jump T,(r28) ; and return store r12,(r30) ; restore flags --- uugate 0.40 (SunOS 4.1.3) * Origin: Internet gateway [cindy] (2:200/427.1)