vaddr: LONG(0x12468) ... LDR(vaddr,R0) ; load address of variable into R0 LD(R0,0,R0) ; load Mem[address] into R0
LD(c,R1) SHLC(R1,1,R0) ; 2*c ADD(R0,R1,R0) ; + c LD(b,R1) ADD(R1,R0,R0) ST(R0,a)
LD(a,R0) LD(b,R1) CMPLE(R0,R1,R0) BT(R0,_L2) CMOVE(17,R0) ST(R0,c) _L2:
LD(sxt_short,R0) BEQ(R0,_L3) LD(b,R1) SHLC(R1,16,R0) ; shift so that bit 15 is now bit 31 SRAC(R0,16,R0) ; shift back, replicating sign bit ST(R0,b)
LD(cjt,R1) LD(R1,8,R0) ADDC(R0,3752,R0) ST(R0,8,R1)
LD(i,R0) SHLC(R0,2,R0) LD(R0,a-4,R1) ST(R1,a,R0)
ST(R31,sum) ST(R31,i) _L7: LD(sum,R0) LD(i,R1) ADD(R0,R1,R0) ST(R0,sum) ADDC(R1,1,R1) ST(R1,i) CMPLTC(R1,10,R0) BT(R0,_L7)
int sum = 0; { int i; for (i = 0; i < 10; i = i+1) sum += i; }
MOVE(R31,R2) ; R2 holds sum ST(R2,sum) MOVE(R31,R1) ; R1 holds i _L5: ADD(R2,R1,R2) ADDC(R1,1,R1) CMPLTC(R1,10,R0) BT(R0,_L5) ST(R2,sum)
int sum = 0; { int i; for (i = 0; i < 10; i = i+2) { sum += i; sum += i+1; } }Hand-compile this loop into Beta assembly language and compare the total number of memory accesses generated when it executes to the total number of memory accesses from part (1).
MOVE(R31,R2) ; R2 holds sum ST(R2,sum) MOVE(R31,R1) ; R1 holds i _L5: ADD(R2,R1,R2) ADDC(R1,1,R0) ADD(R2,R0,R2) ADDC(R1,2,R1) CMPLTC(R1,10,R0) BT(R0,_L5) ST(R2,sum)This code has a 6 instruction loop that makes 0 data accesses; 5 loop iterations => 30 memory accesses. There are 6 additional memory accesses to initializes sum and i, and to store sum at the end of the loop. Total = 36.
I = 0x5678 B = 0x1234 LD(I,R0) SHLC(R0,2,R0) LD(R0,B,R1) MULC(R1,17,R1) ST(R1,B,R0)
I = 0x5678 B = 0x1234 LD(R31,I,R0) 011000 00000 11111 0101 0110 0111 1000 = 0x601F5678 SHLC(R0,2,R0) 111100 00000 00000 0000 0000 0000 0010 = 0xF0000002 LD(R0,B,R1) 011000 00001 00000 0001 0010 0011 0100 = 0x60201234 MULC(R1,17,R1) 110010 00001 00001 0000 0000 0001 0001 = 0xA8210011 ST(R1,B,R0) 011001 00001 00000 0001 0010 0011 0100 = 0x64201234
BEQ R31 R31 offset = -1 011101 11111 11111 1111 1111 1111 1111
BEQ R31 R31 offset = 0 011101 11111 11111 0000 0000 0000 0000
BEQ R31 R17 offset = (0x100 - 0x1004)/4 = 0xFC3F 011101 11111 10001 1111 1100 0011 1111
SUBC R22 R17 12 110001 10110 10001 0000 0000 0000 1100 = 0xC6D1000C
if literal = 0x8000 then new PC = 0x87654 + 4 - (8000 * 4) = 0x67658 if literal = 0x7FFF then new PC = 0x87654 + 4 + (7FFF * 4) = 0xA7654
Usage: SOB(Ra,label,Rc) Operation: literal = ((OFFSET(label) - OFFSET(current inst))/4) - 1 PC = PC + 4 EA = PC + 4*SEXT(literal) Reg[Rc] = Reg[Ra] - 1 if (Reg[Ra]- 1) != 0 then PC = EAAs with branches in the Beta, the binary encoding of the SOB instruction places the low-order 16 bits of the "literal" value in the low-order 16 bits of the instruction. The designers of the Meta implementation have used the Meta's ALU to perform the subtraction.
loop: ADD(R1,R2,R3) SOB(R4,loop,R4)Assuming the ADD instruction is placed in location 0x108 of memory, what are the contents of the low-order 16 bits of the SOB instruction?
Model | Clock Rate | Avg. clocks/Inst. |
---|---|---|
x | 40 Mhz | 2.0 |
y | 100 Mhz | 10.0 |
z | 60 Mhz | 3.0 |
[1] .macro LDC(const,Rx) { LD(.+8,Rx) BR(.+8) LONG(const) } [2] .macro LDC(const,Rx) { PUSH(R17) BR(.+8,R17) LONG(const) LD(R17,0,Rx) POP(R17) } [3] .macro LDC(const,Rx) { ADDC(R31,const >> 16,Rx) SHLC(Rx,16,Rx) ADDC(Rx,const & 0xFFFF,Rx) }Kerry tries each definition on a few test cases and convinces herself each works fine. The Quality Assurance team isn't so sure and complains that Kerry's LDC implementations don't all work for every choice of register (Rx), every choice of constant (const), and every choice of code location.
int x[20], y; y = x[1] + 4;
Address Contents (in hexadecimal) 0x100 0xC05F0008 0x104 0xC03F0000 0x108 0xE060000F 0x10C 0xF0210004 0x110 0xA4230800 0x114 0xF4000004 0x118 0xC4420001 0x11C 0x77E20002 0x120 0x77FFFFF9 0x124 0xA4230800 0x128 0x605F0124 0x12C 0x90211000
Address Contents Opcode Rc Ra Rb Assembly 0x100 0xC05F0008 110000 00010 11111 ADDC(R31, 0x8, R2) 0x104 0xC03F0000 110000 00001 11111 ADDC(R31, 0x0, R1) 0x108 0xE060000F 111000 00011 00000 ANDC(R0, 0xF, R3) 0x10C 0xF0210004 111100 00001 00001 SHLC(R1, 0x4, R1) 0x110 0xA4230800 101001 00001 00011 00001 OR(R3, R1, R1) 0x114 0xF4000004 111101 00000 00000 SHRC(R0, 0x4, R0) 0x118 0xC4420001 110001 00010 00010 SUBC(R2, 0x1, R2) 0x11C 0x77E20002 011101 11111 00010 BEQ(R2,0x128) * 0x120 0x77FFFFF9 011101 11111 11111 BEQ(R31,0x108) ** 0x124 0xA4230800 101001 00001 00011 not an opcode 0x128 0x605F0124 011000 00010 11111 LD(0x0124,R2) 0x12C 0x90211000 100100 00001 00001 00010 CMPEQ(R1,R2,R1) * The literal in instruction 0x11c is 0x2, so the corresponding label in Beta assembly is PC + 4 + 4*literal = 0x11c + 4 + 4*2 = 0x128 ** In instruction 0x120, SEXT(literal) = -7, so the corresponding label in Beta assembly is PC + 4 + 4*literal = 0x120 + 4 + 4*(-7) = 0x124 - 0x01C = 0x108
R2 = 8; /* R2 is used as a counter */ R1 = 0; loop: R3 = R0 & 0xF; /* R3 stores the current low nibble of R0 */ R1 = R1 << 4; R1 = R3 | R1; R0 = R0 >> 4; R2 = R2 - 1; if R2 == 0 goto done; goto loop; data: 0xA4230800 done: LD(data,R2); if (R1 == R2) R1=1; else R1=0;We can see that the code shifts R1 left by a nibble (4 bits) and ors it with the low nibble (R3) of the user's entered password (R0). It then shifts the user's password right by a nibble and loops back to the beginning. It does this a total of 8 times. The net effect is to reverse the order of the nibbles in R0 and to store this into R1. The result is then compared to 0xA4230800. Therefore, in order for the entered password to be accepted, it must be the nibble-reversed version of 0xA4230800. Thus, the "passnumber" required to enter is 0x0080324A