Skip to content

Instantly share code, notes, and snippets.

@cwli24
Last active April 29, 2022 21:15
Show Gist options
  • Save cwli24/e958f52b75c56cfd3414a2f32fe43c25 to your computer and use it in GitHub Desktop.
Save cwli24/e958f52b75c56cfd3414a2f32fe43c25 to your computer and use it in GitHub Desktop.
[ECE411] Testing/simple prog code for the 3 MPs in Assembly
;; Calculates factorial of arbitrary number using LC-3b assembly. (Only LDR/STR/ADD/AND/NOT/BR instructions supported.)
ORIGIN 4x0000
SEGMENT CodeSegment:
;; Assuming all registers, specifically R0, are zeroed at beginning
;; R0 - x0000 throughout program for convenience due to limited instrs
;; R1 - accumulator of final factorial RESULT ("s")
;; R2 - down counter of 's' additions in each round (inner loop, "j")
;; R3 - down counter of factorial rounds from x to 0 (outer loop, "i")
;; R4 - 's' at the beginning of reach round ("n")
;; R5 - contain decrement value (-1) for convenience
;;
;; note: multiplication is done through addition. e.g., 5! = 5*4*3*2*1 = (5+5+5+5)*3*2*1 = ...
;; and edge cases, such as 0!, are not considered
LDR R5, R0, decr
LDR R3, R0, facx
ADD R1, R1, R3 ; first step is just to accumulate x itself, e.g. 's' = 5 to start
MULPLY_NEXT:
ADD R3, R3, R5 ; decr 'i' and stop fac rounds when it reaches 0, e.g. 'i' = 4 in 1st rnd
BRnz STOP
ADD R4, R0, R1 ; save sum so far, e.g. 'n' = 5 in 1st rnd & 20 in 2nd rnd
ADD R2, R0, R3
ADD_N_AGAIN:
ADD R2, R2, R5 ; 'n' is added 'j'(='i'-1) times to 's', e.g. 'j' = 3 in 1st rnd (for +5+5+5)
BRnz MULPLY_NEXT
ADD R1, R1, R4
BRnzp ADD_N_AGAIN
STOP:
BRnzp STOP ; infinite loop for simulation convenience
facx: DATA2 4x0005
decr: DATA2 4xFFFF
;; Testing code for all of LC-3b instructions' functionality (except for RTI--not implemented)
ORIGIN 4x0040
SEGMENT TrapVector:
BRnzp CodeSegment
HITME: DATA2 TRAPTEST
SEGMENT CodeSegment:
;; Assuming all registers, specifically R0, are zeroed at beginning
;; R0 - counter for the number of correct instructions passing test
;; R7 - used only for RET-related tests
ADD R1, R1, 5 ; R1 = x0005
BRnz INF_LOOP
ADD R2, R2, 4
NOT R2, R2 ; R2 = xFFFB
BRzp INF_LOOP
ADD R2, R1, R2 ; R2 = x0000
BRnp INF_LOOP
ADD R0, R0, 4 ; ADDr, ADDi, NOT, BR pass
;; R0 = 4, CC set to p
AND R2, R1, R2 ; R2 same
BRnp INF_LOOP
AND R2, R1, -1 ; R2 = x0005
BRnz INF_LOOP
ADD R2, R2, -5 ; R2 = x0000
BRnp INF_LOOP
ADD R0, R0, 2 ; ANDr, ANDi pass (and SEXT(imm5) check)
;; R0 = 6
AND R1, R1, R2 ; R1 = x0005, CC set to z
LEA R1, JUMPTEST ; label below this instr should set cc to pos
BRnz INF_LOOP
JMP R1
RETTEST:
ADD R0, R0, 1 ; RET passes
;; R0 = 9
JSR OUTER_FN
ADD R0, R0, 1 ; JSR passes
;; R0 = 11
LSHF R1, R2, 15 ; R1 = 0x0000 << 15
BRnp INF_LOOP
ADD R1, R1, -1 ; R1 = xFFFF
ADD R2, R2, -1 ; R2 = xFFFF
RSHFL R2, R2, 8 ; R2 = x00FF, cc should be set to p
BRnz INF_LOOP
RSHFA R1, R1, 15 ; R1 = xFFFF, cc should be set to n
BRzp INF_LOOP
RSHFL R1, R1, 0 ; this should do nothing so that
ADD R1, R1, 1 ; R1 = x0000
BRnp INF_LOOP
ADD R0, R0, 1 ; SHF passes
;; R0 = 12
LEA R6, Data
ADD R1, R1, 13 ; R1 = x000D
STR R1, R6, TSTR
AND R2, R2, 0 ; R2 = x0000, set cc to z
LDR R2, R6, TSTR ; R2 = x000D
BRnz INF_LOOP
ADD R3, R2, -13 ; R3 = x000D + xFFF3 = x0000
BRnp INF_LOOP
ADD R0, R0, 2 ; STR, LDR pass
;; R0 = 14
STI R1, R6, TSTI
AND R2, R2, 0 ; R2 = x0000, set cc to z
LDI R3, R6, TSTI ; R3 = x000D
BRnz INF_LOOP
ADD R3, R3, -13 ; R3 = x0000
BRnp INF_LOOP
ADD R0, R0, 2 ; STI, LDI pass
;; R0 = 16
ADD R3, R3, 10 ; R3 = x000A
LSHF R3, R3, 4 ; = x00A0
ADD R3, R3, 10 ; = x00AA
STB R3, R6, TSTBL
NOT R2, R3 ; R2 = xFF55, set CC to n
STB R2, R6, TSTBH
LDB R1, R6, TSTBL ; R1 = x00AA
BRnz INF_LOOP
AND R1, R1, R2 ; R1 = x00AA & xFF55 = x0000
BRnp INF_LOOP
LDB R1, R6, TSTBH ; R1 = x0055, set CC to p
AND R3, R1, R3 ; R3 = x00AA & x0055 = x0000
BRnp INF_LOOP
ADD R0, R0, 2 ; STB, LDB pass
;; R0 = 18
TRAP HITME
ADD R0, R0, 1 ; TRAP passes
;; R0 = 19
INF_LOOP:
BRnzp INF_LOOP ; most likely failed... unless R0 = 0x13 ;)
JUMPTEST:
ADD R0, R0, 2 ; LEA, JMP pass
; R0 = 8
LEA R7, RETTEST
RET ; PC should jump to [R7]
OUTER_FN:
ADD R6, R7, 0 ; save ret addr
LEA R1, INNER_FN
JSRR R1
ADD R0, R0, 1 ; JSRR passes
; R0 = 10
AND R7, R7, 0 ; restore R7 from JSR
ADD R7, R6, 0 ; if correctly saved
RET
INNER_FN:
RET
TRAPTEST:
RET
SEGMENT Data:
TSTR: DATA2 ?
TSTI: DATA2 BAIT
BAIT: DATA2 ?
TSTBL: DATA1 ?
TSTBH: DATA1 ?
; Testing basic functionality of cache R/W hit/miss
ORIGIN 0
SEGMENT 0 CODE:
LDR R1, R0, l1p
LDR R2, R0, l2p
LDR R3, R0, l3p
LDR R4, R1, 0 ; miss, loads line1 (s0), R4 = x11
LDR R5, R2, 0 ; miss, loads line2 (s1), R5 = x22
STB R4, R1, 1 ; hit, dirty ln1, set ln2 as LRU
STB R5, R2, 1 ; hit, dirty ln2, set ln1 as LRU
LSHF R6, R5, 2 ; R6 = x88
STR R6, R3, A ; miss, write+evict ln1, ld line3 (s0), dirty ln3
LDR R7, R3, 0 ; hit, R7 = x44, ln2 (s1) is LRU
STB R7, R3, 1
LDR R4, R1, 0 ; miss, wr+ev ln2, ld ln1 (s1), R4 = x1111
LDB R5, R2, 1 ; miss, wr+ev ln3, ld ln2 (s0), R5 = x22 (HB)
LSHF R6, R5, 8 ; R6 = x2200
ADD R5, R5, R6 ; R5 = x2222
LDB R6, R3, A ; miss, ev ln1, ld ln3 (s1), R6 = x88
LSHF R7, R6, 8 ; R7 = x8800
ADD R6, R6, R7 ; R6 = x8888
LDR R7, R3, 0 ; hit, R7 = x4444, ln2 (s0) is LRU
ADD R7, R4, R7
ADD R7, R5, R7
ADD R7, R6, R7 ; R7 = xFFFF
; instructions will load into conflicting set offset 0, so result will be flipped:
; data0[0] (s0) should have ln3 = x4444
; data1[0] (s1) should have ln2 = x2222
inf:
BRnzp inf
l1p: DATA2 line1
l2p: DATA2 line2
l3p: DATA2 line3
SEGMENT 128 line1:
X: DATA2 4x0011
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SEGMENT 128 line2:
Y: DATA2 4x0022
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SEGMENT 128 line3:
Z: DATA2 4x0044
NOP
NOP
NOP
NOP
NOP
NOP
A: DATA2 ?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment