Crusoe Exposed: Transmeta TM5xxx Architecture 1

Pages: 1 2 3 4 5

The Proof

# Handler for reading MSR registers from x86 operating system code.
# Illustrates the code for functionality well documented in published
# specifications from Transmeta.
#
read_msr:
#=> target 0x000a6798:
0x000a6798:
ALU0 5039aff4 = 010 100000011 100110 101111 11110100
ALU1 103befe0 = 000 100000011 101111 101111 11100000
# addi    %r38,%r47,-12       # %r38 = %sp – 12
# addi    %r47,%r47,-32       # %sp = %sp – 32
0x000a67a0:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 1038e604 = 000 100000011 100011 100110 00000100
ALU0 1bb8bf00 = 000 110111011 100010 111111 00000000
imm 0×80000000
# nop.lsu
# addi    %r35,%r38,4          # %r35 = %r38 + 4
# oril    %r34,%zero,0×80000000 # %r34 = 0×80000000
0x000a67b0:
LSU 044319bf = 000 001000100 001100 011001 10111111
ALU1 100f008b = 000 100000000 111100 000000 10001011
nop0 14b00000 = 000 101001011 000000 000000 00000000
imm 0x14b00000                                    
# st      [%r47],%r25          # Save %r25
# add    %r60,%r0,%r34       # %r60 = %r0 (%eax) + 0×80000000
#                              # (to bring MSR offset down to zero base)
0x000a67c0:
LSU 04431a8f = 000 001000100 001100 011010 10001111
ALU1 09397c04 = 000 010010011 100101 111100 00000100
ALU0 18367f00 = 000 110000011 011001 111111 00000000
imm 0x0018aae0
# st      [%r35],%r26          # Save %r26
# slli    %r37,%r60,4          # Shift MSR number for indexing into table
# addil   %r25,%zero,0x0018aae0
#                              # 0x18aae0 -> cpuid data for 0×80000000-6
# NOTE: shifts (slli, etc). appear to only be available on ALU1, at least
# according to the opcode map. This is a bizarre (but low power) design.
0x000a67d0:
LSU 04431b9b = 000 001000100 001100 011011 10011011
ALU1 4606fa03 = 010 001100000 011011 111010 00000011
ALU0 1f3f8000 = 000 111110011 111110 000000 00000000
imm 0×80000006
# st      [%r38],%r27          # [%sp-12] = %r27 (callee saved)
# 001100000 %r27,%r58,%r0      #
# cmpil.c %sink,%r0,0×80000006 # compare %eax == 0×80000006?
0x000a67e0:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 103ed9c0 = 000 100000011 111011 011001 11000000
ALU0 18392500 = 000 110000011 100100 100101 00000000
imm 0x0018aae0
# nop.lsu
# addi    %r59,%r25,-64       # 0x18aaa0 -> cpuid data returned for 0×0-0×3
# addil   %r36,%r37,0x0018aae0 # %r36 = 0x18aae0 + (%r60 << 4)
0x000a67f0:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 170f808b = 000 101110000 111110 000000 10001011
ALU0 9386bfff = 100 100111000 011010 111111 11111111
BRU ae014d0c = 101 0111 0 000000010100110100001100
# nop.lsu
# cmp.c   %sink,%r0,%r34       # compare %eax == 0×80000000
# or      %r26,%zero,%zero    # Move %r26 = 0
# br.gt   0x000a6860          # branch if %eax > 0×80000006
#                              # (to handle 0×80860000 functions)
0x000a6800:
ALU0 773f8003 = 011 101110011 111110 000000 00000011
BRU a6014d17 = 101 0011 0 000000010100110100010111
# cmp.c   %sink,%r0,3          # Compare %eax == 3
# br.ge   0x000a68b8          # branch if (%eax >= 0×80000000)
# (branch to load_cpuid_data_to_regs)
0x000a6808:
ALU0 538f00ff = 010 100111000 111100 000000 11111111
ALU1 09394004 = 000 010010011 100101 000000 00000100
# or      %r60,%r0,%zero       # %r60 = %eax
# slli    %r37,%r0,4          # %r37 = %eax << 4 (index cpuid table)
0x000a6810:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 100925ef = 000 100000000 100100 100101 11101111
ALU0 93867bff = 100 100111000 011001 111011 11111111
# nop.lsu
# add    %r36,%r37,%r59       # %r36 = %r37 + (%r0<<4) + 0x18aaa0
#=> target 0x000a6820:
0x000a6820:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 1038ef14 = 000 100000011 100011 101111 00010100
ALU0 1380bfff = 000 100111000 000010 111111 11111111
imm 0x14b00000
# nop.lsu
# addi    %r35,%r47,20         # %r35 = %r47 + 20
# or      %r2,%zero,%zero      # %edx = 0
0x000a6830:
ALU0 53807fff = 010 100111000 000001 111111 11111111
ALU1 1380ffff = 000 100111000 000011 111111 11111111
# move    %r1,%zero,%zero       # %ecx = 0
# move    %r3,%zero,%zero       # %ebx = 0
0x000a6838:
ALU0 53803fff = 010 100111000 000000 111111 11111111
ALU1 1038af18 = 000 100000011 100010 101111 00011000
# move    %r0,%zero,%zero       # Set %eax = 0
# addi    %r34,%r47,24          # %r34 = %sp + 24
#=> target 0x000a6840:
0x000a6840:
LSU 2506c48f = 001 001010000 011011 000100 10001111
ALU1 46803a6f = 010 001101000 000000 111010 01101111
# ld      %r27,[%r35]       # load %r27 = [%r35]
# br.prep %r0,%r58,%r27    # prepare branch (%r58 = %link)
0x000a6848:
LSU 2506848b = 001 001010000 011010 000100 10001011
nop1 14b00000 = 000 101001011 000000 000000 00000000
# ld      %r26,[%r34]       # restore saved register
# nop
0x000a6850:
LSU 050644bf = 000 001010000 011001 000100 1011111
ALU1 103bef20 = 000 100000011 101111 101111 0010000
nop0 94b00000 = 100 101001011 000000 000000 00000000
BRU 80800076 = 100 0000 0 10000000000000000111011 0
# ld      %r25,[%r47]       # restore saved register
# addi    %r47,%r47,32      # restore stack frame
# nop
# br.ret %r58             # return to caller (%r58 = %from)

#
# Load %eax/%ebx/%ecx/%edx with values for a given cpuid
# MSR read request. Illustrates operation of load unit.
#

load_cpuid_data_to_regs:
#=> target 0x000a68b8:
0x000a68b8:
nop0 54b00000 = 010 101001011 000000 000000 00000000
nop1 14b00000 = 000 101001011 000000 000000 00000000
0x000a68c0:
ALU0 5039e40c = 010 100000011 100111 100100 00001100
ALU1 103a2404 = 000 100000011 101000 100100 00000100
# addi    %r39,%r36,12         # %r39 = %r36 + 12   (0x18aaec -> “smet”)
# addi    %r40,%r36,4          # %r40 = %r36 + 4    (0x18aae4 -> “Tran”)
0x000a68c8:
LSU 25000493 = 001 001010000 000000 000100 10010011
ALU1 1039a408 =<000>100000011 100110 100100 00001000
# ld      %r0,[%r36]          # %eax = max cpuid request id
# addi    %r38,%r36,8          # %r38 = %r38 + 8 (= 0x18aae8)
0x000a68d0:
LSU 2500c4a3 = 001 001010000 000011 000100 10100011
ALU1 170f9aff = 000 101110000 111110 011010 11111111
# ld      %r3,4,[%r40]         # load %ebx (%r3) = “Tran”
# cmp.c   %sink,%r26,%zero    # (as called from above, %r26 always is zero)
0x000a68d8:
LSU 2500849f = 001 001010000 000010 000100 10011111
ALU1 1038ef14 = 000 100000011 100011 101111 00010100
# ld      %r2,[%r39]          # load %edx (%r2) = “smet”
# addi    %r35,%r47,20         # r35 = r47 + 20
0x000a68e0:
LSU 0500449b = 000 001010000 000001 000100 10011011
ALU1 1038af18 = 000 100000011 100010 101111 00011000
nop0 94b00000 = 100 101001011 000000 000000 00000000
BRU a8014d08 = 101 01000 00000001 01001101 00001000
# ld      %r1,[%r38]          # load %ecx (%r1) = “aCPU” (%r38 = 0x18aae8)
# addi    %r34,%r47,24         # %r34 = %r47 + 24
# nop
# br.eq   0x000a6840          # branch to common completion
0x000a68f0:
LSU 03b00600 = 000 000111011 000000 000110 00000000
nop1 74b00014 = 011 101001011 000000 000000 00010100
nop0 14b00000 = 000 101001011 000000 000000 00000000
imm 0x14b00000
# nop.lsu | nop | nop | nop
0x000a6900:
nop0 54b00000 = 010 101001011 000000 000000 00000000
nop1 74b00315 = 011 101001011 000000 000011 00010101
0x000a6908:
nop0 54b00000 = 010 101001011 000000 000000 00000000
nop1 74b00116 = 011 101001011 000000 000001 00010110
0x000a6910:
LSU 03b00600 = 000 000111011 000000 000110 00000000
nop1 74b00217 = 011 101001011 000000 000010 00010111
nop0 94b00000 = 100 101001011 000000 000000 00000000
BRU 80014d08 = 100 00000 00000001 01001101 00001000
# nop.lsu | nop | nop
# br      0x000a6840

#
# Called to enable/disable processor serial number (PSN)
# when bit 21 of MSR 0×119 is written. Top level write_msr
# handler is not shown, but is similar to read_msr.
#
# On entry:
#
# %r37 -> cpu_feature_flags (at 0x0018aabc)
# %r38 -> current value of msr_psn_disable
#

#=> target 0x000a6f20:
0x000a6f20:
LSU 050a8497 = 000 001010000 101010 000100 10010111
ALU1 170f80ff = 000 101110000 111110 000000 11111111
ALU0 1a3b0000 = 000 110100011 101100 000000 00000000
imm 0xffdfffff
# ld      %r42,%r4,%r37/3      # %r42 = [%r37] (load cpuid feature flags)
# cmp.c   %sink,%r0,%zero      # is %eax zero? (%eax = 0) meaning: *enable* PSN
# andil   %r44,%r0,0xffdfffff # %r44 = %eax & ~(1<<21): bit21 = PSN disable bit
0x000a6f30:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 020342ff = 000 000100000 001101 000010 11111111
ALU0 1a3a6a00 = 000 110100011 101001 101010 00000000
imm 0xfffbffff
# nop.lsu
# cmp.and %r13,%r2,%zero       # %edx == %zero (high 32 bits in %edx must be zero)
# andil   %r41,%r42,0xfffbffff # 0xfffbffff = ~(1 << 18) = PSN feature flag
0x000a6f40:
LSU 03b00600 = 000 000111011 000000 000110 00000000
ALU1 1388e5ff = 000 100111000 100011 100101 11111111
ALU0 82036cff = 100 000100000 001101 101100 11111111
BRU a8014dc9 = 101 0100 0 000000010100110111001001
# nop.lsu
# or      %r35,%r37,%zero      # %r35 = %r37
# cmp.and %r13,%r44,%zero      # cmp.and %r44 == %zero
#                              # (i.e., no other bits are set in %eax)
# br.eq   0x000a6e48          # (if %eax = 0 [means "enable PSN"], branch)
0x000a6f50:
LSU 04432997 = 000 001000100 001100 101001 10010111
ALU1 13b9ff01 = 000 100111011 100111 111111 00000001
ALU0 103a25e4 = 000 100000011 101000 100101 11100100
imm 0x14b00000
# st      [%r37],%r41          # cpu_feature_flags &= PSN_FF_BIT
# ori    %r39,%zero,1         # %r39 = 1
# addi    %r40,%r37,-28       # %r40 = 0x0018aaa0 [0x3 'Genu' 'Mx86' 'ineT']
0x000a6f60:
LSU 0443009b = 000 001000100 001100 000000 10011011
ALU1 10396518 = 000 100000011 100101 100101 00011000
ALU0 1039a514 = 000 100000011 100110 100101 00010100
imm 0x14b00000
# st      [%r38],%r0          # st [%r38],%r0 (%eax => msr_psn_disable)
# addi    %r37,%r37,24         # %r37 = 0x18aad4 &(“my unique id”)
# addi    %r38,%r37,20         # %r38 = 0x18aad0 &(before “my unique id”)
0x000a6f70:
LSU 044327a3 = 000 001000100 001100 100111 10100011
nop1 14b00000 = 000 101001011 000000 000000 00000000
nop0 14b00000 = 000 101001011 000000 000000 00000000
imm 0x14b00000
# st      [%r40],%r39          # max_cpuid_base_func_number = %r39 (i.e., 1)
0x000a6f80:
LSU 24433f97 = 001 001000100 001100 111111 10010111
ALU1 1038a320 = 000 100000011 100010 100011 00100000
# st      [%r37],%zero         # ["my u"] = 0
# addi    %r34,%r35,32         # %r34 = 0x18aadc
0x000a6f88:
LSU 24433f9b = 001 001000100 001100 111111 10011011
ALU1 1039231c = 000 100000011 100100 100011 00011100
# st      [%r38],%zero         # [word before "my unique id"] = 0
# addi    %r36,%r35,28         # %r36 = 0x18aad8
0x000a6f90:
LSU 24433f8b = 001 001000100 001100 111111 10001011
nop1 14b00000 = 000 101001011 000000 000000 00000000
# st      [%r34],%zero         # ["e ID"] = 0
0x000a6f98:
LSU 24433f93 = 001 001000100 001100 111111 10010011
nop1 14b00000 = 000 101001011 000000 000000 00000000
# st      [%r36],%zero         # ["niqu"] = 0
0x000a6fa0:
nop0 54b00000 = 010 101001011 000000 000000 00000000
nop1 14b00000 = 000 101001011 000000 000000 00000000
0x000a6fa8:
nop0 74b00000 = 011 101001011 000000 000000 00000000
BRU 80014dc9 = 100 0000 0 000000010100110111001001
# br      0x000a6e48


Pages: « Prev  1 2 3 4 5  

Be the first to discuss this article!