| see if it's *really* a Beta or only just pretending... | This code makes the following assumptions about the Beta design: | after reset, the Beta starts executing at location 0 | illegal instructions cause a trap to location 4 | interrupts cause a trap to location 8 | If this program completes successfully, it enters a two-instruction | loop at locations 0x3C4 and 0x3C8. It reaches 0x3C4 for the first | time on cycle 277. | If this program detects an error, it enters a two-instruction loop at | locations 0x00C and 0x010 with an error code in R0. The instruction | at 0x00C is ADDC(R0,0,R31) so it is usually possible to use the | waveform browser in the simulator to display the error code. | possible error addresses in R0: | 0x004 error1: BEQ(R31,...) didn't branch | 0x030 error3: BNE(R31,...) did branch | 0x038 cmp1: CMPEQC(R31,0,R0) failed | 0x040 cmp2: CMPLEC(R31,0,R0) failed | 0x048 cmp3: CMPLTC(R31,1,R0) failed | 0x050 cmp4: CMPEQC(R31,-1,R0) failed | 0x058 cmp5: CMPLEC(R31,-1,R0) failed | 0x060 cmp6: CMPLTC(R31,-1,R0) failed | 0x078 cmp7: didn't generate 0x8000000 or 0x7FFFFFFF correctly (see code) | 0x080 cmp8: 0x8000000 <= 0x7FFFFFF failed | 0x088 cmp9: 0x7FFFFFF <= 0x80000000 failed | 0x090 reg1: ADD(R31,R31,R0) didn't put 0 into R0 | 0x098 reg2: ADDC(R31,0,R0) didn't put 0 into R0 | 0x120 reg3: ADDC(R31,0,R0) didn't produce the correct value | 0x128 reg4: ADDC(R31,1,R1) didn't produce the correct value | 0x130 reg5: ADDC(R31,2,R2) didn't produce the correct value | 0x138 reg6: ADDC(R31,3,R3) didn't produce the correct value | 0x140 reg7: ADDC(R31,4,R4) didn't produce the correct value | 0x148 reg8: ADDC(R31,5,R5) didn't produce the correct value | 0x150 reg9: ADDC(R31,6,R6) didn't produce the correct value | 0x158 reg10: ADDC(R31,7,R7) didn't produce the correct value | 0x160 reg11: ADDC(R31,8,R8) didn't produce the correct value | 0x168 reg12: ADDC(R31,9,R9) didn't produce the correct value | 0x170 reg13: ADDC(R31,10,R10) didn't produce the correct value | 0x178 reg14: ADDC(R31,11,R11) didn't produce the correct value | 0x180 reg15: ADDC(R31,12,R12) didn't produce the correct value | 0x188 reg16: ADDC(R31,13,R13) didn't produce the correct value | 0x190 reg17: ADDC(R31,14,R14) didn't produce the correct value | 0x198 reg18: ADDC(R31,15,R15) didn't produce the correct value | 0x1A0 reg19: ADDC(R31,16,R16) didn't produce the correct value | 0x1A8 reg20: ADDC(R31,17,R17) didn't produce the correct value | 0x1B0 reg21: ADDC(R31,18,R18) didn't produce the correct value | 0x1B8 reg22: ADDC(R31,19,R19) didn't produce the correct value | 0x1C0 reg23: ADDC(R31,20,R20) didn't produce the correct value | 0x1C8 reg24: ADDC(R31,21,R21) didn't produce the correct value | 0x1D0 reg25: ADDC(R31,22,R22) didn't produce the correct value | 0x1D8 reg26: ADDC(R31,23,R23) didn't produce the correct value | 0x1E0 reg27: ADDC(R31,24,R24) didn't produce the correct value | 0x1E8 reg28: ADDC(R31,25,R25) didn't produce the correct value | 0x1F0 reg29: ADDC(R31,26,R26) didn't produce the correct value | 0x1F8 reg30: ADDC(R31,27,R27) didn't produce the correct value | 0x200 reg31: ADDC(R31,28,R28) didn't produce the correct value | 0x208 reg32: ADDC(R31,29,R29) didn't produce the correct value | 0x210 reg33: ADDC(R31,30,R30) didn't produce the correct value | 0x214 reg34: ADDC(R31,31,R31) changed the value of R31! | 0x224 jmp1: JMP executed following instruction | 0x238 jmp2: JMP didn't fill LP correctly | 0x24C add1: LDR failed or 0xAAAAAAAA + 0x55555555 != 1 | 0x25C add2: 0xAAAAAAAA + 0xAAAAAAAA != 0x55555554 | 0x268 add3: 0x55555555 + 0x55555555 != 0xAAAAAAAA | 0x274 add4: 1 - 1 != 0 (carry propagation test) | 0x288 bool1: 0x0F0F & 0x7F00 != 0x0F00 | 0x294 bool2: 0x0F0F & 0x7F00 != 0x7F0F | 0x2A0 bool3: 0x0F0F & 0x7F00 != 0x700F | 0x2B0 shift1: 1 << 32 != 1 | 0x2C0 shift2: (1 << 31) >>signed 17 != 0xFFFFC000 | 0x2CC shift3: (1 << 31) >>unsigned 17 != 0x00004000 | 0x2E8 illop1: XP not filled correctly on illegal op trap | 0x310 illop2: expected 9 illops: 00, 1A, 1C, 27, 2B, 2F, 37, 3B, 3F | 0x33C ldst1: load or store failure | 0x348 ldst2: load or store failure | 0x354 ldst3: load or store failure | 0x360 ldst4: load or store failure | 0x388 bypass1: alu-bypass failure | 0x3B0 bypass2: pc-bypass failure | 0x3BC int1: interrupt didn't happen on correct cycle | 0x3C4 int2: XP not filled correctly on interrupt .include beta.uasm . = 0 | here on reset BEQ(R31,Start,XP) | should branch error1 = . | here on illegal instructions or if BEQ above didn't work BR(IllInst) | here on interrupts JMP(XP) | return from interrupt (don't adjust XP!) | here when we've found an error Error: ADDC(R0,0,R31) | put error code on result bus BR(Error) | loop (or least try to!) | handler for illegal instructions IllInst: CMPEQC(XP,error1,R0) | did the first instruction fail? BF(R0,Ill_1) | nope, do regular processing MOVE(XP,R0) | yup, branch to error handler BR(Error) Ill_1: ADDC(R1,1,R1) | update count JMP(XP) | return to user... | okay, now for some real tests... Start: BNE(R31,Error,R0) | shouldn't branch error3 = . | test simple comparisons CMPEQC(R31,0,R0) BF(R0,Error,R0) cmp1 = . CMPLEC(R31,0,R0) BF(R0,Error,R0) cmp2 = . CMPLTC(R31,1,R0) BF(R0,Error,R0) cmp3 = . CMPEQC(R31,-1,R0) BT(R0,Error,R0) cmp4 = . CMPLEC(R31,-1,R0) BT(R0,Error,R0) cmp5 = . CMPLTC(R31,-1,R0) BT(R0,Error,R0) cmp6 = . | test comparisons with overflow ADDC(R31,1,R1) | load 0x8000000 into r0 SHLC(R1,31,R1) SUBC(R1,1,R2) | load 0x7FFFFFF into r1 OR(R1,R2,R3) | make sure we have what we think we have CMPEQC(R3,-1,R3) BF(R3,Error,R0) cmp7 = . CMPLE(R1,R2,R3) | subtraction should overflow BF(R3,Error,R0) | shouldn't branch cmp8 = . CMPLE(R2,R1,R3) | test it the other way too BT(R3,Error,R0) cmp9 = . | test the registers ADD(R31,R31,R0) | start by making sure ADD works BNE(R0,Error,R0) | shouldn't branch reg1 = . ADDC(R31,0,R0) | and then ADDC BNE(R0,Error,R0) | shouldn't branch reg2 = . ADDC(R31,0,R0) | now fill all regs with unique values ADDC(R31,1,R1) ADDC(R31,2,R2) ADDC(R31,3,R3) ADDC(R31,4,R4) ADDC(R31,5,R5) ADDC(R31,6,R6) ADDC(R31,7,R7) ADDC(R31,8,R8) ADDC(R31,9,R9) ADDC(R31,10,R10) ADDC(R31,11,R11) ADDC(R31,12,R12) ADDC(R31,13,R13) ADDC(R31,14,R14) ADDC(R31,15,R15) ADDC(R31,16,R16) ADDC(R31,17,R17) ADDC(R31,18,R18) ADDC(R31,19,R19) ADDC(R31,20,R20) ADDC(R31,21,R21) ADDC(R31,22,R22) ADDC(R31,23,R23) ADDC(R31,24,R24) ADDC(R31,25,R25) ADDC(R31,26,R26) ADDC(R31,27,R27) ADDC(R31,28,R28) ADDC(R31,29,R29) ADDC(R31,30,R30) ADDC(R31,31,R31) CMPEQC(R0,0,R0) | now check all the reg values BF(R0,Error,R0) reg3 = . CMPEQC(R1,1,R0) BF(R0,Error,R0) reg4 = . CMPEQC(R2,2,R0) BF(R0,Error,R0) reg5 = . CMPEQC(R3,3,R0) BF(R0,Error,R0) reg6 = . CMPEQC(R4,4,R0) BF(R0,Error,R0) reg7 = . CMPEQC(R5,5,R0) BF(R0,Error,R0) reg8 = . CMPEQC(R6,6,R0) BF(R0,Error,R0) reg9 = . CMPEQC(R7,7,R0) BF(R0,Error,R0) reg10 = . CMPEQC(R8,8,R0) BF(R0,Error,R0) reg11 = . CMPEQC(R9,9,R0) BF(R0,Error,R0) reg12 = . CMPEQC(R10,10,R0) BF(R0,Error,R0) reg13 = . CMPEQC(R11,11,R0) BF(R0,Error,R0) reg14 = . CMPEQC(R12,12,R0) BF(R0,Error,R0) reg15 = . CMPEQC(R13,13,R0) BF(R0,Error,R0) reg16 = . CMPEQC(R14,14,R0) BF(R0,Error,R0) reg17 = . CMPEQC(R15,15,R0) BF(R0,Error,R0) reg18 = . CMPEQC(R16,16,R0) BF(R0,Error,R0) reg19 = . CMPEQC(R17,17,R0) BF(R0,Error,R0) reg20 = . CMPEQC(R18,18,R0) BF(R0,Error,R0) reg21 = . CMPEQC(R19,19,R0) BF(R0,Error,R0) reg22 = . CMPEQC(R20,20,R0) BF(R0,Error,R0) reg23 = . CMPEQC(R21,21,R0) BF(R0,Error,R0) reg24 = . CMPEQC(R22,22,R0) BF(R0,Error,R0) reg25 = . CMPEQC(R23,23,R0) BF(R0,Error,R0) reg26 = . CMPEQC(R24,24,R0) BF(R0,Error,R0) reg27 = . CMPEQC(R25,25,R0) BF(R0,Error,R0) reg28 = . CMPEQC(R26,26,R0) BF(R0,Error,R0) reg29 = . CMPEQC(R27,27,R0) BF(R0,Error,R0) reg30 = . CMPEQC(R28,28,R0) BF(R0,Error,R0) reg31 = . CMPEQC(R29,29,R0) BF(R0,Error,R0) reg32 = . CMPEQC(R30,30,R0) BF(R0,Error,R0) reg33 = . BNE(R31,Error,R0) reg34 = . | check out JMPs CMOVE(jmp1,R17) SHLC(R1,31,R1) OR(R1,R17,R17) JMP(R17,LP) BEQ(R31,Error,R0) | shouldn't execute this! jmp1 = . SHLC(LP,1,LP) | get rid of kernel-mode bit SHRC(LP,1,LP) CMPEQC(LP,jmp1-4,R23) | see if LP was filled correctly BEQ(R23,Error,R0) jmp2 = . | check out LDR/ADD/SUB LDR(CA,R24) LDR(C5,R25) ADD(R24,R25,R26) | 0xAAAAAAAA + 0x55555555 = -1 CMPEQC(R26,-1,R27) BEQ(R27,Error,R0) add1 = . ADD(R24,R24,R26) | 0xAAAAAAAA + 0xAAAAAAAA = 0x55555554 SUB(R26,R25,R26) CMPEQC(R26,-1,R27) BEQ(R27,Error,R0) add2 = . ADD(R25,R25,R26) | 0x55555555 + 0x55555555 = 0xAAAAAAAA SUB(R26,R24,R26) BNE(R26,Error,R0) add3 = . CMOVE(1,R17) SUBC(R17,1,R18) | test carry propagation BNE(R18,Error,R0) add4 = . | test boolean operations CMOVE(0x0F0F,R11) CMOVE(0x7F00,R12) AND(R11,R12,R13) | 0x0F0F & 0x7F00 = 0x0F00 CMPEQC(R13,0x0F00,R14) BEQ(R14,Error,R0) bool1 = . OR(R11,R12,R13) | 0x0F0F | 0x7F00 = 0x7F0F CMPEQC(R13,0x7F0F,R14) BEQ(R14,Error,R0) bool2 = . XOR(R11,R12,R13) | 0x0F0F ^ 0x7F00 = 0x700F CMPEQC(R13,0x700F,R14) BEQ(R14,Error,R0) bool3 = . | test shifts CMOVE(1,R27) SHLC(R27,32,R28) | should do nothing CMPEQC(R28,1,R29) BEQ(R29,Error,R0) shift1 = . SHLC(R27,31,R28) | 1 << 31 = 0x80000000 SRAC(R28,17,R26) | 0x80000000 >>(signed) 17 = 0xFFFFC000 CMPEQC(R26,0xC000,R25) BEQ(R25,Error,R0) shift2 = . SHRC(R28,17,R26) | 0x80000000 >>(unsigned) 17 = 0x00004000 CMPEQC(R26,0x4000,R25) BEQ(R25,Error,R0) shift3 = . | test illegal operations CMOVE(0,XP) CMOVE(0,R1) LONG(0x08 << 26) | illegal operation SHLC(XP,1,XP) | get rid of kernel-mode bit SHRC(XP,1,XP) CMPEQC(XP,.-8,R0) BEQ(R0,Error,R0) illop1 = . LONG(0x1A << 26) | some more illegal operations LONG(0x1C << 26) LONG(0x27 << 26) LONG(0x2B << 26) LONG(0x2F << 26) LONG(0x37 << 26) LONG(0x3B << 26) LONG(0x3F << 26) CMPEQC(R1,9,R0) BEQ(R0,Error,R0) illop2 = . | test load and store CMOVE(LDST,R4) | load base reg LDR(CA,R9) XORC(R9,-1,R0) | R0 <- 0x55555555 ST(R0,0,R4) | try some stores ST(R0,LDST+4,R31) | check out bypassing (if any!) ST(R0,8,R4) ST(R0,LDST+12,R31) LD(R4,0,R6) LDR(C5,R5) CMPEQ(R6,R5,R0) | check 1-stage stall BEQ(R0,Error,R0) ldst1 = . LD(R31,LDST+4,R7) CMPEQ(R7,R5,R0) | check 2-stage stall BEQ(R0,Error,R0) ldst2 = . LD(R4,8,R8) CMPEQ(R8,R5,R0) BEQ(R0,Error,R0) ldst3 = . LD(R31,LDST+12,R9) CMPEQ(R9,R5,R0) BEQ(R0,Error,R0) ldst4 = . | finally, check out some bypass paths (just in case...) ADD(R31,R20,R0) | R20 = 20 ADD(R0,R0,R1) | bypass from ALU stage ADD(R0,R0,R2) | bypass from MEM stage ADD(R0,R0,R3) | bypass from WB stage ADD(R0,R0,R4) | read from register ADD(R1,R2,R5) ADD(R3,R5,R5) ADD(R4,R5,R5) CMPEQC(R5,160,R0) BEQ(R0,Error,R0) bypass1 = . BNE(R31,.+4,R0) | R0 = bypass bypass: ADD(R0,R0,R1) | bypass PC from ALU stage ADD(R0,R0,R2) | bypass PC from MEM stage ADD(R0,R0,R3) | bypass PC from WB stage ADD(R0,R0,R4) | read from register ADD(R1,R2,R5) ADD(R3,R5,R5) ADD(R4,R5,R5) CMPEQC(R5,8*bypass,R0) BEQ(R0,Error,R0) bypass1 = . | check interrupts CMOVE(.+8,R0) JMP(R0) | leave supervisor mode BEQ(R31,Error,R0) | this should be interrupted int1 = . CMPEQC(XP,.,R0) | see if XP has correct value BF(R0,Error,R0) int2 = . | all done! Done: ADDC(R31,0,R31) BR(Done) CA: LONG(0xAAAAAAAA) C5: LONG(0x55555555) LDST: LONG(0) LONG(0) LONG(0) LONG(0)