├── .gitignore
├── .idea
├── artifacts
│ ├── mipsasm_linux_x86_64.xml
│ ├── mipsasm_linux_x86_64_gtk3.xml
│ ├── mipsasm_macosx_x86_64.xml
│ ├── mipsasm_win32_x86.xml
│ └── mipsasm_win32_x86_64.xml
├── compiler.xml
├── copyright
│ ├── ZH_Copyright.xml
│ └── profiles_settings.xml
├── description.html
├── dictionaries
│ └── zh.xml
├── encodings.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── libraries
│ ├── commons_cli_commons_cli_1_2.xml
│ ├── org_apache_commons_commons_lang3_3_4.xml
│ └── swt_4_4_2_gtk_linux_x86_64_debug.xml
├── misc.xml
├── modules.xml
├── project-template.xml
├── scopes
│ └── scope_settings.xml
├── uiDesigner.xml
└── vcs.xml
├── LICENSE.md
├── README.md
├── README_ZH_CN.md
├── art
├── app_icon.ico
└── app_icon.zip
├── dist
├── .gitignore
├── launch4j-mipsasm-win32-x86.xml
├── launch4j-mipsasm-win32-x86_64.xml
└── mipsasm-macosx-x86_64.sh
├── lib
├── swt-4.4.2-cocoa-macosx-x86_64.jar
├── swt-4.4.2-gtk-linux-x86_64-debug.jar
├── swt-4.4.2-gtk-linux-x86_64-src.zip
├── swt-4.4.2-gtk-linux-x86_64.jar
├── swt-4.4.2-win32-x86.jar
└── swt-4.4.2-win32-x86_64.jar
├── mipsasm.iml
├── screenshot
├── app-gtk3.png
└── app-windows.png
├── src
├── META-INF
│ └── MANIFEST.MF
├── me
│ └── zhanghai
│ │ └── mipsasm
│ │ ├── Build.java
│ │ ├── Cli.java
│ │ ├── Constants.java
│ │ ├── InternalException.java
│ │ ├── Main.java
│ │ ├── assembler
│ │ ├── Assemblable.java
│ │ ├── Assembler.java
│ │ ├── AssemblerException.java
│ │ ├── AssemblerPreferences.java
│ │ ├── AssemblyContext.java
│ │ ├── AssemblyProvider.java
│ │ ├── BackwardAddressException.java
│ │ ├── CoprocessorFunction.java
│ │ ├── DataDirective.java
│ │ ├── Directive.java
│ │ ├── DirectiveInformation.java
│ │ ├── Immediate.java
│ │ ├── Instruction.java
│ │ ├── InstructionAssembler.java
│ │ ├── InstructionAssemblers.java
│ │ ├── InstructionIndex.java
│ │ ├── InstructionInformation.java
│ │ ├── Label.java
│ │ ├── Offset.java
│ │ ├── OffsetBase.java
│ │ ├── OffsetLabel.java
│ │ ├── OffsetTooLargeException.java
│ │ ├── Operand.java
│ │ ├── OperandInstance.java
│ │ ├── OperandListPrototypes.java
│ │ ├── OperandNotFoundException.java
│ │ ├── OperandPrototype.java
│ │ ├── OperandPrototypes.java
│ │ ├── OperandType.java
│ │ ├── Operation.java
│ │ ├── Register.java
│ │ ├── ShiftAmount.java
│ │ ├── SpaceDirective.java
│ │ ├── StorageDirective.java
│ │ ├── Target.java
│ │ ├── TargetLabel.java
│ │ ├── TextDirective.java
│ │ ├── UndefinedLabelException.java
│ │ └── WordImmediate.java
│ │ ├── disassembler
│ │ ├── CoeReader.java
│ │ ├── CoeReaderException.java
│ │ ├── Disassembler.java
│ │ ├── DisassemblerException.java
│ │ ├── DisassemblyContext.java
│ │ ├── InstructionDisassembler.java
│ │ ├── InstructionDisassemblers.java
│ │ ├── InstructionWordDisassembler.java
│ │ ├── NoSuchOperationException.java
│ │ ├── StorageDirectiveDisassembler.java
│ │ └── WordDisassembler.java
│ │ ├── gui
│ │ ├── AboutDialog.java
│ │ ├── FontDataBuilder.java
│ │ ├── Ide.java
│ │ ├── MenuItemBuilder.java
│ │ ├── StyledTextMenuHelper.java
│ │ ├── StyledTextStyleHelper.java
│ │ ├── StyledTextUndoRedoHelper.java
│ │ ├── SwtUtils.java
│ │ └── Utf8Control.java
│ │ ├── parser
│ │ ├── AsciiDirectiveParser.java
│ │ ├── AsciizDirectiveParser.java
│ │ ├── ByteDirectiveParser.java
│ │ ├── CoprocessorFunctionParser.java
│ │ ├── DataDirectiveParser.java
│ │ ├── DirectiveParser.java
│ │ ├── EchoDirectiveParser.java
│ │ ├── EvalDirectiveParser.java
│ │ ├── HalfWordDirectiveParser.java
│ │ ├── IllegalDirectiveException.java
│ │ ├── IllegalInstructionException.java
│ │ ├── IllegalLabelException.java
│ │ ├── IllegalOperandException.java
│ │ ├── IllegalStatementException.java
│ │ ├── ImmediateParser.java
│ │ ├── InstructionParser.java
│ │ ├── JavaScriptParser.java
│ │ ├── LabelAlreadyDefinedException.java
│ │ ├── LabelOperandParser.java
│ │ ├── LabelParser.java
│ │ ├── LineParser.java
│ │ ├── MigratorException.java
│ │ ├── MultiplePendingLabelException.java
│ │ ├── NoSuchDirectiveException.java
│ │ ├── NoSuchOperationException.java
│ │ ├── OffsetBaseParser.java
│ │ ├── OffsetParser.java
│ │ ├── OperandCountMismatchException.java
│ │ ├── OperandListParser.java
│ │ ├── Parser.java
│ │ ├── ParserException.java
│ │ ├── ParserSplitUtils.java
│ │ ├── PendingLabelException.java
│ │ ├── RegisterParser.java
│ │ ├── ShiftAmountParser.java
│ │ ├── SpaceDirectiveParser.java
│ │ ├── SqsMigrator.java
│ │ ├── StatementParser.java
│ │ ├── StorageDirectiveParser.java
│ │ ├── TargetLabelParser.java
│ │ ├── TargetParser.java
│ │ ├── TextDirectiveParser.java
│ │ ├── Tokens.java
│ │ ├── WordDirectiveParser.java
│ │ └── WordImmediateParser.java
│ │ ├── util
│ │ ├── BitArray.java
│ │ ├── HexUnescaper.java
│ │ ├── IoUtils.java
│ │ ├── RegexUtils.java
│ │ ├── StringUtils.java
│ │ └── UnsignedCompat.java
│ │ └── writer
│ │ ├── BinaryWriter.java
│ │ ├── CoeWriter.java
│ │ ├── DebugWriter.java
│ │ ├── HexDebugWriter.java
│ │ ├── Writer.java
│ │ └── WriterException.java
└── res
│ ├── drawable
│ ├── mipside_128.png
│ ├── mipside_16.png
│ ├── mipside_256.png
│ ├── mipside_32.png
│ ├── mipside_48.png
│ ├── mipside_512.png
│ └── mipside_64.png
│ ├── font
│ ├── SourceCodePro-Bold.ttf
│ └── SourceCodePro-Regular.ttf
│ └── string
│ ├── mipside.properties
│ └── mipside_zh_CN.properties
└── test
├── .gitignore
├── computer_MCPU.s
├── hello_world.s
├── js.s
├── legacy
└── computer_MCPU.asm
├── migrate.s
└── test.s
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/workspace.xml
2 | out/
3 |
--------------------------------------------------------------------------------
/.idea/artifacts/mipsasm_linux_x86_64.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/artifacts/mipsasm_linux_x86_64
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/artifacts/mipsasm_linux_x86_64_gtk3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/artifacts/mipsasm_linux_x86_64_gtk3
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/artifacts/mipsasm_macosx_x86_64.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/artifacts/mipsasm_macosx_x86_64
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/artifacts/mipsasm_win32_x86.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/artifacts/mipsasm_win32_x86
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/artifacts/mipsasm_win32_x86_64.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/artifacts/mipsasm_win32_x86_64
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/copyright/ZH_Copyright.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/description.html:
--------------------------------------------------------------------------------
1 | Simple Java application that includes a class with main()
method
--------------------------------------------------------------------------------
/.idea/dictionaries/zh.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | assemblable
5 | disassemblers
6 | disassembly
7 | migrator
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/libraries/commons_cli_commons_cli_1_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/libraries/org_apache_commons_commons_lang3_3_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/libraries/swt_4_4_2_gtk_linux_x86_64_debug.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/project-template.xml:
--------------------------------------------------------------------------------
1 |
2 | IJ_BASE_PACKAGE
3 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MIPS Assembler and IDE
2 |
3 | [本文中文版](README_ZH_CN.md)
4 |
5 | This is my project for Computer Organization, Shi Qingsong, Zhejiang University.
6 |
7 | The MIPS assembler is based on the MIPS 32 specification, with some custom extensions.
8 |
9 | The MIPS IDE is built upon SWT, packaged with launch4j for Windows executable.
10 |
11 | ## Screenshot
12 |
13 | 
14 |
15 | 
16 |
17 | ## Specification
18 |
19 | This MIPS assembler mainly complies with the specifications from "MIPS Assembly Language Programmer’s Guide" and "MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set".
20 |
21 | ## Instruction set
22 |
23 | 95 Instrucitons:
24 |
25 | - ADD
26 | - ADDI
27 | - ADDIU
28 | - ADDU
29 | - AND
30 | - ANDI
31 | - B
32 | - BEQ
33 | - BEQL
34 | - BGEZ
35 | - BGEZAL
36 | - BGEZALL
37 | - BGEZL
38 | - BGTZ
39 | - BGTZL
40 | - BLEZ
41 | - BLEZL
42 | - BLTZ
43 | - BLTZAL
44 | - BLTZALL
45 | - BLTZL
46 | - BNE
47 | - BNEL
48 | - BREAK
49 | - COP2
50 | - DERET
51 | - DIV
52 | - DIVU
53 | - ERET
54 | - J
55 | - JAL
56 | - JALR
57 | - JR
58 | - LA
59 | - LB
60 | - LBU
61 | - LDC1
62 | - LDC2
63 | - LH
64 | - LHU
65 | - LI
66 | - LL
67 | - LUI
68 | - LW
69 | - LWC1
70 | - LWC2
71 | - LWL
72 | - LWR
73 | - MFC0
74 | - MFHI
75 | - MFLO
76 | - MOVE
77 | - MOVN
78 | - MOVZ
79 | - MTC0
80 | - MTHI
81 | - MTLO
82 | - MULT
83 | - MULTU
84 | - NOR
85 | - NOP
86 | - OR
87 | - ORI
88 | - PREF
89 | - SB
90 | - SC
91 | - SDC1
92 | - SDC2
93 | - SH
94 | - SLL
95 | - SLLV
96 | - SLT
97 | - SLTI
98 | - SLTIU
99 | - SLTU
100 | - SRA
101 | - SRAV
102 | - SRL
103 | - SRLV
104 | - SUB
105 | - SUBU
106 | - SW
107 | - SWC1
108 | - SWC2
109 | - SWC3
110 | - SWL
111 | - SWR
112 | - TLBP
113 | - TLBR
114 | - TLBWI
115 | - TLBWR
116 | - SYSCALL
117 | - WAIT
118 | - XOR
119 | - XOR
120 |
121 | 10 directives:
122 |
123 | - .TEXT
124 | - .DATA
125 | - .ASCII
126 | - .ASCIIZ
127 | - .BYTE
128 | - .HALF
129 | - .WORD
130 | - .SPACE
131 | - .EVAL
132 | - .ECHO
133 |
134 | JavaScript expression is supported for operands, while `.eval` can evaluate a JavaScript expression anywhere and `.echo` can echo the JavaScript returned string as the source code to assemble in place.
135 |
136 | ## Assemble
137 |
138 | Numerous error checks are done during the process of assembly, including illegal operand, immediate overflow, missing or duplicate label, text and data section overlap, etc.
139 |
140 | Available output formats include binary, COE and a debug mode.
141 |
142 | ## Disassemble
143 |
144 | Disassembling can be done by opening a binary or COE file. All the instructions listed above and labels are supported, and multiple bytes of zero can be compressed into a `.space` directive.
145 |
146 | ## Graphical user interface
147 |
148 | - Native GUI on Linux, Windows and Mac OSX.
149 |
150 | - Drag-and-drop to open a file.
151 |
152 | - Printing support.
153 |
154 | - Line number and syntax highlighting.
155 |
156 | ## Command line interface
157 |
158 | ```
159 | usage: mipsasm [OPTION]...
160 | -g,--graphical Launch graphical user interface
161 | -h,--help Display this help and exit
162 | -i,--input Read input from FILE
163 | -o,--output Write output to FILE
164 | -t,--terminal Launch in terminal mode
165 | -w,--writer Use writer of TYPE. TYPE can be 'binary', 'coe',
166 | 'debug' (the default), or 'hexdebug'
167 | ```
168 |
169 | ## Sample code
170 |
171 | ```mipsasm
172 | # "Hello World" in MIPS assembly
173 | # From: http://labs.cs.upt.ro/labs/so2/html/resources/nachos-doc/mipsf.html
174 |
175 | # All program code is placed after the
176 | # .text assembler directive
177 | .text 0x0
178 |
179 | # The label 'main' represents the starting point
180 | main:
181 | # Run the print_string syscall which has code 4
182 | li $v0, 4 # Code for syscall: print_string
183 | la $a0, msg # Pointer to string (load the address of msg)
184 | syscall
185 | li $v0, 10 # Code for syscall: exit
186 | syscall
187 |
188 | # All memory structures are placed after the
189 | # .data assembler directive
190 | .data 0x20
191 |
192 | # The .asciiz assembler directive creates
193 | # an ASCII string in memory terminated by
194 | # the null character. Note that strings are
195 | # surrounded by double-quotes
196 |
197 | msg: .asciiz "Hello World!\n"
198 | ```
199 |
--------------------------------------------------------------------------------
/README_ZH_CN.md:
--------------------------------------------------------------------------------
1 | # MIPS 汇编器及集成开发环境
2 |
3 | 这是我为浙江大学计算机组成课程编写的项目。
4 |
5 | MIPS 汇编器主要遵循 MIPS 32 规格说明,并采用了一些自定义的扩展.
6 |
7 | MIPS 集成开发环境基于 SWT 构建,并使用 launch4j 打包为 Windows 可执行程序。
8 |
9 | ## 预览
10 |
11 | 
12 |
13 | 
14 |
15 | ## 规范
16 |
17 | 本汇编器参考并主要遵循 MIPS Assembly Language Programmer’s Guide 及 MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set 所包含的规范。
18 |
19 | ## 指令集
20 |
21 | 支持以下 95 条指令:
22 |
23 | - ADD
24 | - ADDI
25 | - ADDIU
26 | - ADDU
27 | - AND
28 | - ANDI
29 | - B
30 | - BEQ
31 | - BEQL
32 | - BGEZ
33 | - BGEZAL
34 | - BGEZALL
35 | - BGEZL
36 | - BGTZ
37 | - BGTZL
38 | - BLEZ
39 | - BLEZL
40 | - BLTZ
41 | - BLTZAL
42 | - BLTZALL
43 | - BLTZL
44 | - BNE
45 | - BNEL
46 | - BREAK
47 | - COP2
48 | - DERET
49 | - DIV
50 | - DIVU
51 | - ERET
52 | - J
53 | - JAL
54 | - JALR
55 | - JR
56 | - LA
57 | - LB
58 | - LBU
59 | - LDC1
60 | - LDC2
61 | - LH
62 | - LHU
63 | - LI
64 | - LL
65 | - LUI
66 | - LW
67 | - LWC1
68 | - LWC2
69 | - LWL
70 | - LWR
71 | - MFC0
72 | - MFHI
73 | - MFLO
74 | - MOVE
75 | - MOVN
76 | - MOVZ
77 | - MTC0
78 | - MTHI
79 | - MTLO
80 | - MULT
81 | - MULTU
82 | - NOR
83 | - NOP
84 | - OR
85 | - ORI
86 | - PREF
87 | - SB
88 | - SC
89 | - SDC1
90 | - SDC2
91 | - SH
92 | - SLL
93 | - SLLV
94 | - SLT
95 | - SLTI
96 | - SLTIU
97 | - SLTU
98 | - SRA
99 | - SRAV
100 | - SRL
101 | - SRLV
102 | - SUB
103 | - SUBU
104 | - SW
105 | - SWC1
106 | - SWC2
107 | - SWC3
108 | - SWL
109 | - SWR
110 | - TLBP
111 | - TLBR
112 | - TLBWI
113 | - TLBWR
114 | - SYSCALL
115 | - WAIT
116 | - XOR
117 | - XOR
118 |
119 | 支持以下 10 条伪指令:
120 |
121 | - .TEXT
122 | - .DATA
123 | - .ASCII
124 | - .ASCIIZ
125 | - .BYTE
126 | - .HALF
127 | - .WORD
128 | - .SPACE
129 | - .EVAL
130 | - .ECHO
131 |
132 | 所有操作数均支持 JavaScript 表达式,同时`.EVAL`指令可以直接求值一个 JavaScript 表达式,`.ECHO`可以将 JavaScript 表达式的返回值作为一行 MIPS 代码就地进行汇编。
133 |
134 | ## 汇编功能
135 |
136 | 支持完备的错误检查,在参数不合法、立即数超出范围、标签缺失或重复、代码或数据段重叠等情况下输出错误信息。
137 |
138 | 支持的输出格式包括二进制、COE 和调试输出文件。
139 |
140 | 支持将旧格式导入至现有格式。
141 |
142 | ## 反汇编功能
143 |
144 | 支持以上所有指令所生成的二进制和 COE 文件。
145 |
146 | 支持标签的反汇编。
147 |
148 | 支持将二进制中大量 0 压缩为一条`.SPACE`伪指令。
149 |
150 | ## 命令行功能
151 |
152 | 支持以下命令格式:
153 |
154 | ```
155 | usage: mipsasm [OPTION]...
156 | -g,--graphical Launch graphical user interface
157 | -h,--help Display this help and exit
158 | -i,--input Read input from FILE
159 | -o,--output Write output to FILE
160 | -t,--terminal Launch in terminal mode
161 | -w,--writer Use writer of TYPE. TYPE can be 'binary', 'coe',
162 | 'debug' (the default), or 'hexdebug'
163 | ```
164 |
165 | ## 图形界面功能
166 |
167 | 支持在 Windows、Linux、Mac OSX 上使用原生控件显示图形界面。
168 |
169 | 支持文件、编辑、汇编菜单和相应快捷键。
170 |
171 | 支持拖拽打开文件。
172 |
173 | 支持打印。
174 |
175 | 支持语法高亮、行号显示。
176 |
177 | ## 示例代码
178 |
179 | MIPS 汇编代码:
180 |
181 | ```mipsasm
182 | # "Hello World" in MIPS assembly
183 | # From: http://labs.cs.upt.ro/labs/so2/html/resources/nachos-doc/mipsf.html
184 |
185 | # All program code is placed after the
186 | # .text assembler directive
187 | .text 0x0
188 |
189 | # The label 'main' represents the starting point
190 | main:
191 | # Run the print_string syscall which has code 4
192 | li $v0, 4 # Code for syscall: print_string
193 | la $a0, msg # Pointer to string (load the address of msg)
194 | syscall
195 | li $v0, 10 # Code for syscall: exit
196 | syscall
197 |
198 | # All memory structures are placed after the
199 | # .data assembler directive
200 | .data 0x20
201 |
202 | # The .asciiz assembler directive creates
203 | # an ASCII string in memory terminated by
204 | # the null character. Note that strings are
205 | # surrounded by double-quotes
206 |
207 | msg: .asciiz "Hello World!\n"
208 | ```
209 |
210 | COE 输出:
211 |
212 | ```coe
213 | memory_initialization_radix=16;
214 | memory_initialization_vector=
215 | 3C020004, 34420000, 3C040020, 34840000, 0000000C, 3C02000A, 34420000, 0000000C,
216 | 48656C6C, 6F20576F, 726C6421, 0A000000;
217 | ```
218 |
--------------------------------------------------------------------------------
/art/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/art/app_icon.ico
--------------------------------------------------------------------------------
/art/app_icon.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/art/app_icon.zip
--------------------------------------------------------------------------------
/dist/.gitignore:
--------------------------------------------------------------------------------
1 | out/
2 |
--------------------------------------------------------------------------------
/dist/launch4j-mipsasm-win32-x86.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 | gui
5 | ../out/artifacts/mipsasm_win32_x86/mipsasm-win32-x86.jar
6 | out/mipsasm-win32-x86.exe
7 |
8 |
9 | .
10 | normal
11 | https://java.com/download/
12 |
13 | false
14 | false
15 |
16 | ../art/app_icon.ico
17 |
18 |
19 | false
20 | false
21 | 1.7.0
22 |
23 | preferJre
24 | 32/64
25 |
26 |
--------------------------------------------------------------------------------
/dist/launch4j-mipsasm-win32-x86_64.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 | gui
5 | ../out/artifacts/mipsasm_win32_x86_64/mipsasm-win32-x86_64.jar
6 | out/mipsasm-win32-x86_64.exe
7 |
8 |
9 | .
10 | normal
11 | https://java.com/download/
12 |
13 | false
14 | false
15 |
16 | ../art/app_icon.ico
17 |
18 |
19 | false
20 | false
21 | 1.7.0
22 |
23 | preferJre
24 | 64
25 |
26 |
27 |
--------------------------------------------------------------------------------
/dist/mipsasm-macosx-x86_64.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | exec java \
3 | -d64 \
4 | -XstartOnFirstThread \
5 | -jar mipsasm-macosx-x86_64.jar
6 |
--------------------------------------------------------------------------------
/lib/swt-4.4.2-cocoa-macosx-x86_64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/lib/swt-4.4.2-cocoa-macosx-x86_64.jar
--------------------------------------------------------------------------------
/lib/swt-4.4.2-gtk-linux-x86_64-debug.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/lib/swt-4.4.2-gtk-linux-x86_64-debug.jar
--------------------------------------------------------------------------------
/lib/swt-4.4.2-gtk-linux-x86_64-src.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/lib/swt-4.4.2-gtk-linux-x86_64-src.zip
--------------------------------------------------------------------------------
/lib/swt-4.4.2-gtk-linux-x86_64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/lib/swt-4.4.2-gtk-linux-x86_64.jar
--------------------------------------------------------------------------------
/lib/swt-4.4.2-win32-x86.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/lib/swt-4.4.2-win32-x86.jar
--------------------------------------------------------------------------------
/lib/swt-4.4.2-win32-x86_64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/lib/swt-4.4.2-win32-x86_64.jar
--------------------------------------------------------------------------------
/mipsasm.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/screenshot/app-gtk3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/screenshot/app-gtk3.png
--------------------------------------------------------------------------------
/screenshot/app-windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/screenshot/app-windows.png
--------------------------------------------------------------------------------
/src/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Main-Class: me.zhanghai.mipsasm.Main
3 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/Build.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm;
7 |
8 | public class Build {
9 |
10 | public static final String VERSION_NAME = "1.0.2";
11 |
12 | private Build() {}
13 | }
14 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm;
7 |
8 | public class Constants {
9 |
10 | public static final int BYTE_LENGTH = 8;
11 | public static final int HALF_WORD_LENGTH = 16;
12 | public static final int WORD_LENGTH = 32;
13 | public static final int ADDRESS_LENGTH = WORD_LENGTH;
14 | public static final int INSTRUCTION_LENGTH = WORD_LENGTH;
15 | public static final int BYTES_PER_HALF_WORD = HALF_WORD_LENGTH / BYTE_LENGTH;
16 | public static final int BYTES_PER_WORD = WORD_LENGTH / BYTE_LENGTH;
17 | public static final int BYTES_PER_INSTRUCTION = INSTRUCTION_LENGTH / BYTE_LENGTH;
18 | }
19 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/InternalException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm;
7 |
8 | public class InternalException extends RuntimeException {
9 |
10 | public InternalException() {}
11 |
12 | public InternalException(String message) {
13 | super(message);
14 | }
15 |
16 | public InternalException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public InternalException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm;
7 |
8 | import me.zhanghai.mipsasm.gui.Ide;
9 | import org.apache.commons.cli.CommandLine;
10 | import org.apache.commons.cli.ParseException;
11 |
12 | public class Main {
13 |
14 | public static void main(String[] args) {
15 |
16 | CommandLine commandLine;
17 | try {
18 | commandLine = Cli.parseCommandLine(args);
19 | } catch (ParseException e) {
20 | e.printStackTrace();
21 | return;
22 | }
23 | if (!Cli.checkCommandLine(commandLine)) {
24 | return;
25 | }
26 |
27 | // If OPTION_TERMINAL is present, then there will be an option.
28 | if (Cli.hasGraphicalOption(commandLine) || !Cli.hasOption(commandLine)) {
29 | new Ide().run();
30 | } else {
31 | Cli.run(commandLine);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Assemblable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public interface Assemblable {
9 |
10 | void allocate(AssemblyContext context);
11 |
12 | void write(AssemblyContext context) throws AssemblerException;
13 | }
14 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Assembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class Assembler {
9 |
10 | private Assembler() {}
11 |
12 | public static void assemble(AssemblyContext context) throws AssemblerException {
13 | for (Assemblable assemblable : context.getAssemblableList()) {
14 | try {
15 | assemblable.write(context);
16 | } catch (AssemblerException e) {
17 | throw new AssemblerException("Assemblable: " + assemblable, e);
18 | }
19 | }
20 | context.packAssemblyToWords();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/AssemblerException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class AssemblerException extends Exception {
9 |
10 | public AssemblerException() {}
11 |
12 | public AssemblerException(String message) {
13 | super(message);
14 | }
15 |
16 | public AssemblerException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public AssemblerException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/AssemblerPreferences.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import java.util.prefs.Preferences;
9 |
10 | public class AssemblerPreferences {
11 |
12 | private enum Preference {
13 |
14 | DELAY_SLOT_ENABLED(true);
15 |
16 | private Object defaultValue;
17 |
18 | Preference(Object defaultValue) {
19 | this.defaultValue = defaultValue;
20 | }
21 |
22 | public T getDefaultValue() {
23 | //noinspection unchecked
24 | return (T) defaultValue;
25 | }
26 | }
27 |
28 | private static final Preferences PREFERENCES = Preferences.userNodeForPackage(AssemblerPreferences.class);
29 |
30 | private AssemblerPreferences() {}
31 |
32 | public static boolean getDelaySlotEnabled() {
33 | return PREFERENCES.getBoolean(Preference.DELAY_SLOT_ENABLED.name(),
34 | Preference.DELAY_SLOT_ENABLED.getDefaultValue());
35 | }
36 |
37 | public static void setDelaySlotEnabled(boolean delaySlotEnabled) {
38 | PREFERENCES.putBoolean(Preference.DELAY_SLOT_ENABLED.name(), delaySlotEnabled);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/AssemblyProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public interface AssemblyProvider {
11 |
12 | BitArray assemble(AssemblyContext context) throws AssemblerException;
13 | }
14 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/BackwardAddressException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class BackwardAddressException extends IllegalArgumentException {
9 |
10 | public BackwardAddressException() {}
11 |
12 | public BackwardAddressException(String message) {
13 | super(message);
14 | }
15 |
16 | public BackwardAddressException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public BackwardAddressException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/CoprocessorFunction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public class CoprocessorFunction implements Operand, AssemblyProvider {
11 |
12 | private static final int LENGTH = 25;
13 |
14 | private BitArray value;
15 |
16 | private CoprocessorFunction(BitArray value) {
17 | this.value = value;
18 | }
19 |
20 | public static CoprocessorFunction of(BitArray value) {
21 | if (value.length() != LENGTH) {
22 | throw new IllegalArgumentException("Coprocessor function length != " + LENGTH + ": " + value.length());
23 | }
24 | return new CoprocessorFunction(BitArray.copyOf(value));
25 | }
26 |
27 | public static CoprocessorFunction of(int value) {
28 | return new CoprocessorFunction(BitArray.of(value, LENGTH));
29 | }
30 |
31 | public BitArray getValue() {
32 | return value;
33 | }
34 |
35 | public BitArray assemble(AssemblyContext context) {
36 | return value;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return value.toString();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/DataDirective.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class DataDirective extends Directive {
9 |
10 | private WordImmediate address;
11 |
12 | private DataDirective(WordImmediate address) {
13 | this.address = address;
14 | }
15 |
16 | public static DataDirective of(WordImmediate address) {
17 | return new DataDirective(address);
18 | }
19 |
20 | public WordImmediate getAddress() {
21 | return address;
22 | }
23 |
24 | @Override
25 | public void allocate(AssemblyContext context) {
26 | context.allocateToAddress(address);
27 | }
28 |
29 | @Override
30 | public void write(AssemblyContext context) throws AssemblerException {
31 | context.writeToAddress(address);
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return "." + DirectiveInformation.DATA.name().toLowerCase() + " " + address;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Directive.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public abstract class Directive implements Assemblable {}
9 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/DirectiveInformation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.parser.*;
9 |
10 | public enum DirectiveInformation {
11 |
12 | TEXT,
13 | DATA,
14 | ASCII,
15 | ASCIIZ,
16 | BYTE,
17 | HALF,
18 | WORD,
19 | SPACE,
20 | EVAL,
21 | ECHO;
22 |
23 | public void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
24 | switch (this) {
25 | case TEXT:
26 | TextDirectiveParser.parse(operandStringList, context);
27 | break;
28 | case DATA:
29 | DataDirectiveParser.parse(operandStringList, context);
30 | break;
31 | case ASCII:
32 | AsciiDirectiveParser.parse(operandStringList, context);
33 | break;
34 | case ASCIIZ:
35 | AsciizDirectiveParser.parse(operandStringList, context);
36 | break;
37 | case BYTE:
38 | ByteDirectiveParser.parse(operandStringList, context);
39 | break;
40 | case HALF:
41 | HalfWordDirectiveParser.parse(operandStringList, context);
42 | break;
43 | case WORD:
44 | WordDirectiveParser.parse(operandStringList, context);
45 | break;
46 | case SPACE:
47 | SpaceDirectiveParser.parse(operandStringList, context);
48 | break;
49 | case EVAL:
50 | EvalDirectiveParser.parse(operandStringList, context);
51 | break;
52 | case ECHO:
53 | EchoDirectiveParser.parse(operandStringList, context);
54 | break;
55 | default:
56 | throw new IllegalStateException("Parser not found: " + this);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Immediate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.util.BitArray;
10 |
11 | public class Immediate implements Operand, AssemblyProvider {
12 |
13 | static final int LENGTH = Constants.HALF_WORD_LENGTH;
14 |
15 | private BitArray value;
16 |
17 | private Immediate(BitArray value) {
18 | this.value = value;
19 | }
20 |
21 | public static Immediate of(int value) {
22 | return new Immediate(BitArray.ofInteger(value, LENGTH));
23 | }
24 |
25 | public BitArray getValue() {
26 | return value;
27 | }
28 |
29 | @Override
30 | public BitArray assemble(AssemblyContext context) {
31 | return value;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return value.toDecimalString();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Instruction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.IoUtils;
9 |
10 | import java.util.Arrays;
11 |
12 | public class Instruction implements Assemblable {
13 |
14 | private Operation operation;
15 | private OperandInstance[] operandListInstance;
16 |
17 | private Instruction(Operation operation, OperandInstance[] operandListInstance) {
18 | this.operation = operation;
19 | this.operandListInstance = operandListInstance;
20 | }
21 |
22 | public static Instruction of(Operation operation, OperandInstance[] operandListInstance) {
23 | return new Instruction(operation, operandListInstance);
24 | }
25 |
26 | public Operation getOperation() {
27 | return operation;
28 | }
29 |
30 | public OperandInstance[] getOperandListInstance() {
31 | return operandListInstance;
32 | }
33 |
34 | public OperandInstance getOperandInstance(String operandName) {
35 | for (OperandInstance operandInstance : operandListInstance) {
36 | if (operandInstance.getName().equals(operandName)) {
37 | return operandInstance;
38 | }
39 | }
40 | throw new OperandNotFoundException("Operand name: " + operandName + ", operandListInstance: "
41 | + Arrays.toString(operandListInstance) + ", instruction: "+ this);
42 | }
43 |
44 | public Operand getOperand(String operandName) {
45 | return getOperandInstance(operandName).getOperand();
46 | }
47 |
48 | public Operand getOperand(OperandPrototype operandPrototype) {
49 | return getOperand(operandPrototype.getName());
50 | }
51 |
52 | private InstructionAssembler getAssembler() {
53 | return InstructionInformation.ofOperation(operation).getAssembler();
54 | }
55 |
56 | public void allocate(AssemblyContext context) {
57 | getAssembler().allocate(this, context);
58 | }
59 |
60 | public void write(AssemblyContext context) throws AssemblerException {
61 | getAssembler().write(this, context);
62 | }
63 |
64 | @Override
65 | public String toString() {
66 | if (operandListInstance.length == 0) {
67 | return operation.name().toLowerCase();
68 | } else {
69 | return operation.name().toLowerCase() + " " + IoUtils.arrayToString(operandListInstance,
70 | new IoUtils.Stringifier() {
71 | @Override
72 | public String stringify(OperandInstance operandInstance) {
73 | return operandInstance.getOperand().toString();
74 | }
75 | }, ", ");
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/InstructionAssembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public interface InstructionAssembler {
9 |
10 | void allocate(Instruction instruction, AssemblyContext context);
11 |
12 | void write(Instruction instruction, AssemblyContext context) throws AssemblerException;
13 | }
14 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/InstructionIndex.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public class InstructionIndex implements Operand, AssemblyProvider {
11 |
12 | private static final int LENGTH = 26;
13 |
14 | private BitArray value;
15 |
16 | private InstructionIndex(BitArray value) {
17 | this.value = value;
18 | }
19 |
20 | public static InstructionIndex of(int value) {
21 | return new InstructionIndex(BitArray.ofInteger(value, LENGTH));
22 | }
23 |
24 | public BitArray getValue() {
25 | return value;
26 | }
27 |
28 | public BitArray assemble(AssemblyContext context) {
29 | return value;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Label.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.parser.Tokens;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 |
13 | public class Label implements Operand {
14 |
15 | private static ThreadLocal MATCHER = RegexUtils.makeThreadLocalMatcher(Tokens.IDENTIFIER_REGEX);
16 |
17 | private String name;
18 |
19 | protected Label(String name) {
20 | this.name = name;
21 | }
22 |
23 | protected static void checkName(String name) {
24 | Matcher matcher = MATCHER.get().reset(name);
25 | if (!matcher.matches()) {
26 | throw new IllegalArgumentException("Label name must match " + matcher.pattern());
27 | }
28 | }
29 |
30 | public static Label of(String name) {
31 | checkName(name);
32 | return new Label(name);
33 | }
34 |
35 | public String getName() {
36 | return name;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return name;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Offset.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public class Offset implements Operand, AssemblyProvider {
11 |
12 | private boolean isLabel;
13 |
14 | private OffsetLabel label;
15 |
16 | private Immediate immediate;
17 |
18 | public Offset(boolean isLabel, OffsetLabel label, Immediate immediate) {
19 | this.isLabel = isLabel;
20 | this.label = label;
21 | this.immediate = immediate;
22 | }
23 |
24 | public static Offset of(OffsetLabel label) {
25 | return new Offset(true, label, null);
26 | }
27 |
28 | public static Offset of(Immediate immediate) {
29 | return new Offset(false, null, immediate);
30 | }
31 |
32 | public boolean isLabel() {
33 | return isLabel;
34 | }
35 |
36 | public OffsetLabel getLabel() {
37 | if (!isLabel) {
38 | throw new IllegalStateException("Not a label: " + immediate);
39 | }
40 | return label;
41 | }
42 |
43 | public Immediate getImmediate() {
44 | if (isLabel) {
45 | throw new IllegalStateException("Not an immediate: " + label);
46 | }
47 | return immediate;
48 | }
49 |
50 | @Override
51 | public BitArray assemble(AssemblyContext context) throws AssemblerException {
52 | if (isLabel) {
53 | return label.assemble(context);
54 | } else {
55 | return immediate.assemble(context);
56 | }
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return isLabel ? label.toString() : immediate.toString();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OffsetBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class OffsetBase implements Operand {
9 |
10 | private Register base;
11 | private Immediate offset;
12 |
13 | private OffsetBase(Register base, Immediate offset) {
14 | this.base = base;
15 | this.offset = offset;
16 | }
17 |
18 | public static OffsetBase of(Register base, Immediate offset) {
19 | return new OffsetBase(base, offset);
20 | }
21 |
22 | public Register getBase() {
23 | return base;
24 | }
25 |
26 | public Immediate getOffset() {
27 | return offset;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return (offset.getValue().isZero() ? "" : offset.toString()) + "(" + base.toString() + ")";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OffsetLabel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.InternalException;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 |
12 | public class OffsetLabel extends Label implements AssemblyProvider {
13 |
14 | private static final int LENGTH = Immediate.LENGTH;
15 |
16 | private OffsetLabel(String name) {
17 | super(name);
18 | }
19 |
20 | public static OffsetLabel of(String name) {
21 | checkName(name);
22 | return new OffsetLabel(name);
23 | }
24 |
25 | // From MIPS 32 manual:
26 | // An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) is added to the address of the instruction
27 | // following the branch (not the branch itself), in the branch delay slot, to form a PC-relative effective target
28 | // address.
29 | @Override
30 | public BitArray assemble(AssemblyContext context) throws AssemblerException {
31 | int offset = context.getLabelAddress(this) - (context.getAddress() + Constants.BYTES_PER_INSTRUCTION);
32 | if (offset % Constants.BYTES_PER_INSTRUCTION != 0) {
33 | throw new InternalException("Instruction alignment failed, label: " + getName() + ", offset: " + offset);
34 | }
35 | offset /= Constants.BYTES_PER_INSTRUCTION;
36 | try {
37 | return BitArray.ofInteger(offset, LENGTH);
38 | } catch (IllegalArgumentException e) {
39 | throw new OffsetTooLargeException("Label name: " + getName() + ", offset: " + offset, e);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OffsetTooLargeException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class OffsetTooLargeException extends AssemblerException {
9 |
10 | public OffsetTooLargeException() {}
11 |
12 | public OffsetTooLargeException(String message) {
13 | super(message);
14 | }
15 |
16 | public OffsetTooLargeException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public OffsetTooLargeException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Operand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public interface Operand {}
9 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OperandInstance.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class OperandInstance extends OperandPrototype {
9 |
10 | private Operand operand;
11 |
12 | private OperandInstance(String name, OperandType type, Operand operand) {
13 | super(name, type);
14 |
15 | this.operand = operand;
16 | }
17 |
18 | public static OperandInstance fromPrototype(OperandPrototype operandPrototype, Operand operand) {
19 | return new OperandInstance(operandPrototype.getName(), operandPrototype.getType(), operand);
20 | }
21 |
22 | public Operand getOperand() {
23 | return operand;
24 | }
25 |
26 | @Override
27 | public boolean equals(Object object) {
28 | if (this == object) {
29 | return true;
30 | } else if (object == null || getClass() != object.getClass()) {
31 | return false;
32 | } else if (!super.equals(object)) {
33 | return false;
34 | }
35 |
36 | OperandInstance that = (OperandInstance) object;
37 | return operand.equals(that.operand);
38 | }
39 |
40 | @Override
41 | public int hashCode() {
42 | int result = super.hashCode();
43 | result = 31 * result + operand.hashCode();
44 | return result;
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | return "OperandInstance {" +
50 | "operand=" + operand +
51 | "} " + super.toString();
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OperandListPrototypes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class OperandListPrototypes {
9 |
10 | public static final OperandPrototype[] EMPTY = new OperandPrototype[] {};
11 |
12 | public static final OperandPrototype[] DESTINATION_SOURCE_SOURCE2 = new OperandPrototype[] {
13 | OperandPrototypes.DESTINATION,
14 | OperandPrototypes.SOURCE,
15 | OperandPrototypes.SOURCE2
16 | };
17 |
18 | public static final OperandPrototype[] SOURCE2_SOURCE_IMMEDIATE = new OperandPrototype[] {
19 | OperandPrototypes.SOURCE2,
20 | OperandPrototypes.SOURCE,
21 | OperandPrototypes.IMMEDIATE
22 | };
23 |
24 | public static final OperandPrototype[] OFFSET = new OperandPrototype[] {
25 | OperandPrototypes.OFFSET
26 | };
27 |
28 | public static final OperandPrototype[] SOURCE_SOURCE2_OFFSET = new OperandPrototype[] {
29 | OperandPrototypes.SOURCE,
30 | OperandPrototypes.SOURCE2,
31 | OperandPrototypes.OFFSET
32 | };
33 |
34 | public static final OperandPrototype[] SOURCE_OFFSET = new OperandPrototype[] {
35 | OperandPrototypes.SOURCE,
36 | OperandPrototypes.OFFSET
37 | };
38 |
39 | public static final OperandPrototype[] COPROCESSOR_FUNCTION = new OperandPrototype[] {
40 | OperandPrototypes.COPROCESSOR_FUNCTION
41 | };
42 |
43 | public static final OperandPrototype[] SOURCE_SOURCE2 = new OperandPrototype[] {
44 | OperandPrototypes.SOURCE,
45 | OperandPrototypes.SOURCE2
46 | };
47 |
48 | public static final OperandPrototype[] DESTINATION_SOURCE2_SHIFT_AMOUNT = new OperandPrototype[] {
49 | OperandPrototypes.DESTINATION,
50 | OperandPrototypes.SOURCE2,
51 | OperandPrototypes.SHIFT_AMOUNT
52 | };
53 |
54 | public static final OperandPrototype[] DESTINATION_SOURCE2_SOURCE = new OperandPrototype[] {
55 | OperandPrototypes.DESTINATION,
56 | OperandPrototypes.SOURCE2,
57 | OperandPrototypes.SOURCE
58 | };
59 |
60 | public static final OperandPrototype[] TARGET = new OperandPrototype[] {
61 | OperandPrototypes.TARGET
62 | };
63 |
64 | public static final OperandPrototype[] DESTINATION_SOURCE = new OperandPrototype[] {
65 | OperandPrototypes.DESTINATION,
66 | OperandPrototypes.SOURCE
67 | };
68 |
69 | public static final OperandPrototype[] SOURCE = new OperandPrototype[] {
70 | OperandPrototypes.SOURCE
71 | };
72 |
73 | public static final OperandPrototype[] SOURCE2_OFFSET_BASE = new OperandPrototype[] {
74 | OperandPrototypes.SOURCE2,
75 | OperandPrototypes.OFFSET_BASE
76 | };
77 |
78 | public static final OperandPrototype[] SOURCE2_IMMEDIATE = new OperandPrototype[] {
79 | OperandPrototypes.SOURCE2,
80 | OperandPrototypes.IMMEDIATE
81 | };
82 |
83 | public static final OperandPrototype[] SOURCE2_DESTINATION = new OperandPrototype[] {
84 | OperandPrototypes.SOURCE2,
85 | OperandPrototypes.DESTINATION
86 | };
87 |
88 | public static final OperandPrototype[] DESTINATION = new OperandPrototype[] {
89 | OperandPrototypes.DESTINATION
90 | };
91 |
92 | public static final OperandPrototype[] HINT_OFFSET_BASE = new OperandPrototype[] {
93 | OperandPrototypes.HINT,
94 | OperandPrototypes.OFFSET_BASE
95 | };
96 |
97 | public static final OperandPrototype[] SOURCE2_WORD_IMMEDIATE = new OperandPrototype[] {
98 | OperandPrototypes.SOURCE2,
99 | OperandPrototypes.WORD_IMMEDIATE
100 | };
101 |
102 | public static final OperandPrototype[] SOURCE2_LABEL = new OperandPrototype[] {
103 | OperandPrototypes.SOURCE2,
104 | OperandPrototypes.LABEL
105 | };
106 | }
107 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OperandNotFoundException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.InternalException;
9 |
10 | public class OperandNotFoundException extends InternalException {
11 |
12 | public OperandNotFoundException() {}
13 |
14 | public OperandNotFoundException(String message) {
15 | super(message);
16 | }
17 |
18 | public OperandNotFoundException(String message, Throwable cause) {
19 | super(message, cause);
20 | }
21 |
22 | public OperandNotFoundException(Throwable cause) {
23 | super(cause);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OperandPrototype.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class OperandPrototype {
9 |
10 | private String name;
11 | private OperandType type;
12 |
13 | protected OperandPrototype(String name, OperandType type) {
14 | this.name = name;
15 | this.type = type;
16 | }
17 |
18 | public static OperandPrototype of(String name, OperandType type) {
19 | return new OperandPrototype(name, type);
20 | }
21 |
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public OperandType getType() {
27 | return type;
28 | }
29 |
30 | @Override
31 | public boolean equals(Object object) {
32 |
33 | if (this == object) {
34 | return true;
35 | } else if (object == null || getClass() != object.getClass()) {
36 | return false;
37 | }
38 |
39 | OperandPrototype that = (OperandPrototype) object;
40 | if (!name.equals(that.name)) {
41 | return false;
42 | } else if (type != that.type) {
43 | return false;
44 | }
45 |
46 | return true;
47 | }
48 |
49 | @Override
50 | public int hashCode() {
51 | int result = name.hashCode();
52 | result = 31 * result + type.hashCode();
53 | return result;
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | return "OperandPrototype {" +
59 | "name='" + name + "'" +
60 | ", type=" + type +
61 | '}';
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OperandPrototypes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class OperandPrototypes {
9 |
10 | private OperandPrototypes() {}
11 |
12 | public static final OperandPrototype DESTINATION = OperandPrototype.of("destination", OperandType.REGISTER);
13 |
14 | public static final OperandPrototype SOURCE2 = OperandPrototype.of("source2", OperandType.REGISTER);
15 |
16 | public static final OperandPrototype SOURCE = OperandPrototype.of("source", OperandType.REGISTER);
17 |
18 | public static final OperandPrototype IMMEDIATE = OperandPrototype.of("immediate", OperandType.IMMEDIATE);
19 |
20 | public static final OperandPrototype OFFSET = OperandPrototype.of("offset", OperandType.OFFSET);
21 |
22 | public static final OperandPrototype COPROCESSOR_FUNCTION = OperandPrototype.of("coprocessorFunction", OperandType.COPROCESSOR_FUNCTION);
23 |
24 | public static final OperandPrototype SHIFT_AMOUNT = OperandPrototype.of("shiftAmount", OperandType.SHIFT_AMOUNT);
25 |
26 | public static final OperandPrototype TARGET = OperandPrototype.of("target", OperandType.TARGET);
27 |
28 | public static final OperandPrototype OFFSET_BASE = OperandPrototype.of("offset(base)", OperandType.OFFSET_BASE);
29 |
30 | public static final OperandPrototype HINT = OperandPrototype.of("hint", OperandType.REGISTER);
31 |
32 | public static final OperandPrototype WORD_IMMEDIATE = OperandPrototype.of("wordImmediate", OperandType.WORD_IMMEDIATE);
33 |
34 | public static final OperandPrototype LABEL = OperandPrototype.of("label", OperandType.LABEL);
35 | }
36 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/OperandType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public enum OperandType {
9 | REGISTER,
10 | IMMEDIATE,
11 | OFFSET,
12 | COPROCESSOR_FUNCTION,
13 | SHIFT_AMOUNT,
14 | TARGET,
15 | OFFSET_BASE,
16 | WORD_IMMEDIATE,
17 | LABEL
18 | }
19 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Operation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.InternalException;
9 | import me.zhanghai.mipsasm.util.BitArray;
10 |
11 | // FIXME: In fact, Operation should not be abstracted like this. Due to some corner cases, we need dynamic abstractions,
12 | // like OperandPrototype and OperandInstance, and in this case template and instance.
13 | public enum Operation {
14 |
15 | ADD(Codes.SPECIAL, 0b100000),
16 | ADDI(0b001000),
17 | ADDIU(0b001001),
18 | ADDU(Codes.SPECIAL, 0b100001),
19 | AND(Codes.SPECIAL, 0b100100),
20 | ANDI(0b001100),
21 | B,
22 | // BAL, BC1F, BC1FL, ... , BC2TL
23 | BEQ(0b000100),
24 | BEQL(0b010100),
25 | BGEZ(Codes.REGIMM, 0b00001, true),
26 | BGEZAL(Codes.REGIMM, 0b10001, true),
27 | BGEZALL(Codes.REGIMM, 0b10011, true),
28 | BGEZL(Codes.REGIMM, 0b00011, true),
29 | BGTZ(0b000111, 0b00000, true),
30 | BGTZL(0b010111, 0b00000, true),
31 | BLEZ(0b000110, 0b00000, true),
32 | BLEZL(0b010110, 0b00000, true),
33 | BLTZ(Codes.REGIMM, 0b00000, true),
34 | BLTZAL(Codes.REGIMM, 0b10000, true),
35 | BLTZALL(Codes.REGIMM, 0b10010, true),
36 | BLTZL(Codes.REGIMM, 0b00010, true),
37 | BNE(0b000101),
38 | BNEL(0b010101),
39 | BREAK(Codes.SPECIAL, 0b001101),
40 | // C, ... , CLZ
41 | COP2(Codes.COP2),
42 | // CTC, ... , DERET
43 | DERET(Codes.COP0, 0b011111),
44 | DIV(Codes.SPECIAL, 0b011010),
45 | DIVU(Codes.SPECIAL, 0b011011),
46 | ERET(Codes.COP0, 0b011000),
47 | J(0b000010),
48 | JAL(0b000011),
49 | JALR(Codes.SPECIAL, 0b001001),
50 | JR(Codes.SPECIAL, 0b001000),
51 | LA,
52 | LB(0b100000),
53 | LBU(0b100100),
54 | LDC1(0b110101),
55 | LDC2(0b110110),
56 | LH(0b100001),
57 | LHU(0b100101),
58 | LI,
59 | LL(0b110000),
60 | LUI(0b001111),
61 | LW(0b100011),
62 | LWC1(0b110001),
63 | LWC2(0b110010),
64 | // LWC3(0b110011),
65 | LWL(0b100010),
66 | LWR(0b100110),
67 | // MADD, ... MFC2
68 | MFC0(Codes.COP0, 0b00000, false),
69 | MFHI(Codes.SPECIAL, 0b010000),
70 | MFLO(Codes.SPECIAL, 0b010010),
71 | MOVE,
72 | MOVN(Codes.SPECIAL, 0b001011),
73 | // MOVT
74 | MOVZ(Codes.SPECIAL, 0b001010),
75 | // MSUB, ... ,MTC2
76 | MTC0(Codes.COP0, 0b00100, false),
77 | MTHI(Codes.SPECIAL, 0b010001),
78 | MTLO(Codes.SPECIAL, 0b010011),
79 | // MUL
80 | MULT(Codes.SPECIAL, 0b011000),
81 | MULTU(Codes.SPECIAL, 0b011001),
82 | NOR(Codes.SPECIAL, 0b100111),
83 | NOP(),
84 | OR(Codes.SPECIAL, 0b100101),
85 | ORI(0b001101),
86 | PREF(0b110011),
87 | SB(0b101000),
88 | SC(0b111000),
89 | // SDBBP
90 | SDC1(0b111101),
91 | SDC2(0b111110),
92 | // SDL(0b101100),
93 | // SDR(0b101101),
94 | SH(0b101001),
95 | SLL(Codes.SPECIAL, 0b000000),
96 | SLLV(Codes.SPECIAL, 0b000100),
97 | SLT(Codes.SPECIAL, 0b101010),
98 | SLTI(0b001010),
99 | SLTIU(0b001011),
100 | SLTU(Codes.SPECIAL, 0b101011),
101 | SRA(Codes.SPECIAL, 0b000011),
102 | SRAV(Codes.SPECIAL, 0b000111),
103 | SRL(Codes.SPECIAL, 0b000010),
104 | SRLV(Codes.SPECIAL, 0b000110),
105 | // SSNOP
106 | SUB(Codes.SPECIAL, 0b100010),
107 | SUBU(Codes.SPECIAL, 0b100011),
108 | SW(0b101011),
109 | SWC1(0b111001),
110 | SWC2(0b111010),
111 | SWC3(0b111011),
112 | SWL(0b101010),
113 | SWR(0b101110),
114 | TLBP(Codes.COP0, 0b001000),
115 | TLBR(Codes.COP0, 0b000001),
116 | TLBWI(Codes.COP0, 0b000010),
117 | TLBWR(Codes.COP0, 0b000110),
118 | // TEQ, ... , TNEI
119 | SYSCALL(Codes.SPECIAL, 0b001100),
120 | WAIT(Codes.COP0, 0b100000),
121 | XOR(Codes.SPECIAL, 0b100110),
122 | XORI(0b001110);
123 |
124 | private static final int CODE_LENGTH = 6;
125 | private static final int FUNCTION_LENGTH = 6;
126 | private static final int SOURCE_LENGTH = 5;
127 | private static final int SOURCE2_LENGTH = 5;
128 |
129 | private BitArray code;
130 | private BitArray function;
131 | private BitArray source;
132 | private BitArray source2;
133 |
134 | private interface Codes {
135 | int SPECIAL = 0b000000;
136 | int REGIMM = 0b000001;
137 | int COP0 = 0b010000;
138 | int COP1 = 0b010001;
139 | int COP2 = 0b010010;
140 | }
141 |
142 | Operation(BitArray code, BitArray source, BitArray source2, BitArray function) {
143 | this.code = code;
144 | this.function = function;
145 | this.source = source;
146 | this.source2 = source2;
147 | }
148 |
149 | Operation(int code, int source, boolean isSource2) {
150 | this(BitArray.of(code, CODE_LENGTH), isSource2 ? null : BitArray.of(source, SOURCE_LENGTH),
151 | isSource2 ? BitArray.of(source, SOURCE2_LENGTH) : null, null);
152 | }
153 |
154 | Operation(int code, int function) {
155 | this(BitArray.of(code, CODE_LENGTH), null, null, BitArray.of(function, FUNCTION_LENGTH));
156 | }
157 |
158 | Operation(int code) {
159 | this(BitArray.of(code, CODE_LENGTH), null, null, null);
160 | }
161 |
162 | Operation() {
163 | this(null, null, null, null);
164 | }
165 |
166 | public static Operation of(BitArray code, BitArray source, BitArray source2, BitArray function) {
167 | for (Operation operation : values()) {
168 | if ((operation.code != null && operation.code.equals(code))
169 | && (operation.source == null || operation.source.equals(source))
170 | && (operation.source2 == null || operation.source2.equals(source2))
171 | && (operation.function == null || operation.function.equals(function))) {
172 | return operation;
173 | }
174 | }
175 | throw new IllegalArgumentException("Unknown operation, code: " + code + ", source: " + source + ", source2: "
176 | + source2 + ", function: " + function);
177 | }
178 |
179 | public BitArray getCode() {
180 | if (code == null) {
181 | throw new InternalException(new IllegalStateException("getCode() called on an Operation without a code"));
182 | }
183 | return code;
184 | }
185 |
186 | public BitArray getSource() {
187 | if (source == null) {
188 | throw new InternalException(new IllegalStateException(
189 | "getSource() called on an Operation without a source"));
190 | }
191 | return source;
192 | }
193 |
194 | public BitArray getSource2() {
195 | if (source2 == null) {
196 | throw new InternalException(new IllegalStateException(
197 | "getSource2() called on an Operation without a source2"));
198 | }
199 | return source2;
200 | }
201 |
202 | public BitArray getFunction() {
203 | if (function == null) {
204 | throw new InternalException(new IllegalStateException(
205 | "getFunction() called on an Operation without a function"));
206 | }
207 | return function;
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Register.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public enum Register implements Operand, AssemblyProvider {
11 |
12 | ZERO,
13 | AT,
14 | V0,
15 | V1,
16 | A0,
17 | A1,
18 | A2,
19 | A3,
20 | T0,
21 | T1,
22 | T2,
23 | T3,
24 | T4,
25 | T5,
26 | T6,
27 | T7,
28 | S0,
29 | S1,
30 | S2,
31 | S3,
32 | S4,
33 | S5,
34 | S6,
35 | S7,
36 | T8,
37 | T9,
38 | K0,
39 | K1,
40 | GP,
41 | SP,
42 | FP,
43 | RA;
44 |
45 | private static final int LENGTH = 5;
46 |
47 | public static Register of(int index) {
48 | return values()[index];
49 | }
50 |
51 | public BitArray assemble(AssemblyContext context) {
52 | return BitArray.of(ordinal(), LENGTH);
53 | }
54 |
55 | @Override
56 | public String toString() {
57 | return "$" + name().toLowerCase();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/ShiftAmount.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public class ShiftAmount implements Operand, AssemblyProvider {
11 |
12 | private static final int LENGTH = 5;
13 |
14 | public static final ShiftAmount ZERO = ShiftAmount.of(0);
15 |
16 | private BitArray value;
17 |
18 | private ShiftAmount(BitArray value) {
19 | this.value = value;
20 | }
21 |
22 | public static ShiftAmount of(BitArray value) {
23 | if (value.length() != LENGTH) {
24 | throw new IllegalArgumentException("Shift amount length != " + LENGTH + ": " + value.length());
25 | }
26 | return new ShiftAmount(BitArray.copyOf(value));
27 | }
28 |
29 | public static ShiftAmount of(int value) {
30 | return new ShiftAmount(BitArray.of(value, LENGTH));
31 | }
32 |
33 | public BitArray assemble(AssemblyContext context) {
34 | return value;
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return value.toDecimalString();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/SpaceDirective.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class SpaceDirective extends Directive {
9 |
10 | private int length;
11 |
12 | private SpaceDirective(int length) {
13 | this.length = length;
14 | }
15 |
16 | public static SpaceDirective of(int length) {
17 | return new SpaceDirective(length);
18 | }
19 |
20 | public int getLength() {
21 | return length;
22 | }
23 |
24 | @Override
25 | public void allocate(AssemblyContext context) {
26 | context.allocateSpace(length);
27 | }
28 |
29 | @Override
30 | public void write(AssemblyContext context) throws AssemblerException {
31 | context.writeSpace(length);
32 | }
33 |
34 | @Override
35 | public boolean equals(Object object) {
36 |
37 | if (this == object) {
38 | return true;
39 | } else if (object == null || getClass() != object.getClass()) {
40 | return false;
41 | }
42 |
43 | SpaceDirective that = (SpaceDirective) object;
44 | return length == that.length;
45 | }
46 |
47 | @Override
48 | public int hashCode() {
49 | return length;
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return "." + DirectiveInformation.SPACE.name().toLowerCase() + " " + length;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/StorageDirective.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.InternalException;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 |
12 | public class StorageDirective extends Directive {
13 |
14 | private BitArray value;
15 |
16 | private StorageDirective(BitArray value) {
17 | this.value = value;
18 | }
19 |
20 | public static StorageDirective of(BitArray value) {
21 | if (value.length() % Constants.BYTE_LENGTH != 0) {
22 | throw new IllegalArgumentException("Storage directive length not in bytes: " + value.length());
23 | }
24 | return new StorageDirective(BitArray.copyOf(value));
25 | }
26 |
27 | public static StorageDirective of(int value, int length) {
28 | return of(BitArray.of(value, length));
29 | }
30 |
31 | public BitArray getValue() {
32 | return value;
33 | }
34 |
35 | @Override
36 | public void allocate(AssemblyContext context) {
37 | context.allocateBits(value.length());
38 | }
39 |
40 | @Override
41 | public void write(AssemblyContext context) throws AssemblerException {
42 | context.writeBytes(value);
43 | }
44 |
45 | @Override
46 | public boolean equals(Object object) {
47 |
48 | if (this == object) {
49 | return true;
50 | } if (object == null || getClass() != object.getClass()) {
51 | return false;
52 | }
53 |
54 | StorageDirective storage = (StorageDirective) object;
55 | return value.equals(storage.value);
56 | }
57 |
58 | @Override
59 | public int hashCode() {
60 | return value.hashCode();
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | StringBuilder builder = new StringBuilder(".");
66 | switch (value.length()) {
67 | case Constants.BYTE_LENGTH:
68 | builder.append(DirectiveInformation.BYTE.name().toLowerCase());
69 | break;
70 | case Constants.HALF_WORD_LENGTH:
71 | builder.append(DirectiveInformation.HALF.name().toLowerCase());
72 | break;
73 | case Constants.WORD_LENGTH:
74 | builder.append(DirectiveInformation.WORD.name().toLowerCase());
75 | break;
76 | default:
77 | throw new InternalException("Illegal storage directive length: " + value.length());
78 | }
79 | builder.append(" ")
80 | .append(value.toHexString());
81 | return builder.toString();
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/Target.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public class Target implements Operand, AssemblyProvider {
11 |
12 | private boolean isLabel;
13 |
14 | private TargetLabel label;
15 |
16 | private InstructionIndex instructionIndex;
17 |
18 | public Target(boolean isLabel, TargetLabel label, InstructionIndex instructionIndex) {
19 | this.isLabel = isLabel;
20 | this.label = label;
21 | this.instructionIndex = instructionIndex;
22 | }
23 |
24 | public static Target of(TargetLabel label) {
25 | return new Target(true, label, null);
26 | }
27 |
28 | public static Target of(InstructionIndex instructionIndex) {
29 | return new Target(false, null, instructionIndex);
30 | }
31 |
32 | public boolean isLabel() {
33 | return isLabel;
34 | }
35 |
36 | public TargetLabel getLabel() {
37 | if (!isLabel) {
38 | throw new IllegalStateException("Not a label: " + instructionIndex);
39 | }
40 | return label;
41 | }
42 |
43 | public InstructionIndex getInstructionIndex() {
44 | if (isLabel) {
45 | throw new IllegalStateException("Not an instruction index: " + label);
46 | }
47 | return instructionIndex;
48 | }
49 |
50 | @Override
51 | public BitArray assemble(AssemblyContext context) throws AssemblerException {
52 | if (isLabel) {
53 | return label.assemble(context);
54 | } else {
55 | return instructionIndex.assemble(context);
56 | }
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return isLabel ? label.toString() : instructionIndex.toString();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/TargetLabel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.InternalException;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 |
12 | public class TargetLabel extends Label implements AssemblyProvider {
13 |
14 | private static final int LENGTH = 26;
15 |
16 | private TargetLabel(String name) {
17 | super(name);
18 | }
19 |
20 | public static TargetLabel of(String name) {
21 | checkName(name);
22 | return new TargetLabel(name);
23 | }
24 |
25 | // From MIPS 32 manual:
26 | // The low 28 bits of the target address is the instr_index field shifted left 2 bits.
27 | // The remaining upper bits are the corresponding bits of the address of the instruction in the delay slot (not
28 | // the branch itself).
29 | @Override
30 | public BitArray assemble(AssemblyContext context) throws AssemblerException {
31 | BitArray address = BitArray.of(context.getLabelAddress(this), Constants.ADDRESS_LENGTH);
32 | if (address.get(0) || address.get(1)) {
33 | throw new InternalException("Instruction alignment failed, label: " + getName() + ", address: " + address);
34 | }
35 | // TODO: NOP for delay slot is not implemented here.
36 | if (!address.subArray(2 + LENGTH, Constants.ADDRESS_LENGTH).equals(
37 | BitArray.of(context.getAddress() + Constants.BYTES_PER_INSTRUCTION, 2 + LENGTH,
38 | Constants.ADDRESS_LENGTH))) {
39 | throw new OffsetTooLargeException("Label name: " + getName() + ", address: " + address
40 | + ", current address: " + BitArray.of(context.getAddress(), Constants.ADDRESS_LENGTH));
41 | }
42 | return address
43 | .rightShift(2)
44 | .setLength(LENGTH);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/TextDirective.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class TextDirective extends Directive {
9 |
10 | private WordImmediate address;
11 |
12 | private TextDirective(WordImmediate address) {
13 | this.address = address;
14 | }
15 |
16 | public static TextDirective of(WordImmediate address) {
17 | return new TextDirective(address);
18 | }
19 |
20 | public WordImmediate getAddress() {
21 | return address;
22 | }
23 |
24 | @Override
25 | public void allocate(AssemblyContext context) {
26 | context.allocateToAddress(address);
27 | }
28 |
29 | @Override
30 | public void write(AssemblyContext context) throws AssemblerException {
31 | context.writeToAddress(address);
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return "." + DirectiveInformation.TEXT.name().toLowerCase() + " " + address;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/UndefinedLabelException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | public class UndefinedLabelException extends AssemblerException {
9 |
10 | public UndefinedLabelException() {}
11 |
12 | public UndefinedLabelException(String message) {
13 | super(message);
14 | }
15 |
16 | public UndefinedLabelException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public UndefinedLabelException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/assembler/WordImmediate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.assembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.util.BitArray;
10 |
11 | public class WordImmediate implements Operand {
12 |
13 | private BitArray value;
14 |
15 | private WordImmediate(BitArray value) {
16 | this.value = value;
17 | }
18 |
19 | public static WordImmediate of(int value) {
20 | return new WordImmediate(BitArray.of(value, Constants.WORD_LENGTH));
21 | }
22 |
23 | public BitArray getValue() {
24 | return value;
25 | }
26 |
27 | public BitArray getLower() {
28 | return value.subArray(0, Constants.HALF_WORD_LENGTH);
29 | }
30 |
31 | public BitArray getUpper() {
32 | return value.subArray(Constants.HALF_WORD_LENGTH);
33 | }
34 |
35 | @Override
36 | public boolean equals(Object object) {
37 |
38 | if (this == object) {
39 | return true;
40 | } if (object == null || getClass() != object.getClass()) {
41 | return false;
42 | }
43 |
44 | WordImmediate that = (WordImmediate) object;
45 | return value.equals(that.value);
46 | }
47 |
48 | @Override
49 | public int hashCode() {
50 | return value.hashCode();
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return value.toHexString();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/CoeReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.util.IoUtils;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 | import me.zhanghai.mipsasm.util.UnsignedCompat;
11 |
12 | import java.io.ByteArrayInputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.util.regex.Matcher;
16 | import java.util.regex.Pattern;
17 |
18 | public class CoeReader {
19 |
20 | private static String GROUP_RADIX = "radix";
21 | private static ThreadLocal RADIX_MATCHER =
22 | RegexUtils.makeThreadLocalMatcher("memory_initialization_radix\\s*=\\s*(?<" + GROUP_RADIX + ">.*?)\\s*;");
23 |
24 | private static String GROUP_VECTOR = "vector";
25 | private static ThreadLocal VECTOR_MATCHER = RegexUtils.makeThreadLocalMatcher(
26 | "memory_initialization_vector\\s*=\\s*(?<" + GROUP_VECTOR + ">.*?)\\s*;", Pattern.DOTALL);
27 |
28 | private static ThreadLocal VECTOR_IGNORE_MATCHER = RegexUtils.makeThreadLocalMatcher("[,\\s]+");
29 |
30 | public static ByteArrayInputStream coeToBytes(InputStream inputStream) throws IOException, CoeReaderException {
31 |
32 | String input = IoUtils.inputStreamToString(inputStream).toLowerCase();
33 | Matcher radixMatcher = RADIX_MATCHER.get().reset(input);
34 | if (!radixMatcher.find()) {
35 | throw new CoeReaderException("Radix not found");
36 | }
37 | int radix;
38 | try {
39 | radix = Integer.parseInt(radixMatcher.group(GROUP_RADIX));
40 | } catch (NumberFormatException e) {
41 | throw new CoeReaderException("Cannot parse radix", e);
42 | }
43 | Matcher vectorMatcher = VECTOR_MATCHER.get().reset(input);
44 | if (!vectorMatcher.find()) {
45 | throw new CoeReaderException("Vector not found");
46 | }
47 | String vector = vectorMatcher.group(GROUP_VECTOR);
48 | Matcher vectorIgnoreMatcher = VECTOR_IGNORE_MATCHER.get().reset(vector);
49 | vector = vectorIgnoreMatcher.replaceAll("");
50 |
51 | byte[] bytes;
52 | switch (radix) {
53 | case 2:
54 | bytes = new byte[(int) Math.ceil(vector.length() / 8d)];
55 | for (int i = 0, j = 0, k = 8; j < vector.length(); ++i, j = k, k += 8) {
56 | if (k > vector.length()) {
57 | k = vector.length();
58 | }
59 | bytes[i] = UnsignedCompat.parseUnsignedByte(vector.substring(j, k), radix);
60 | }
61 | break;
62 | case 16:
63 | bytes = new byte[(int) Math.ceil(vector.length() / 2d)];
64 | for (int i = 0, j = 0, k = 2; j < vector.length(); ++i, j = k, k += 2) {
65 | if (k > vector.length()) {
66 | k = vector.length();
67 | }
68 | bytes[i] = UnsignedCompat.parseUnsignedByte(vector.substring(j, k), radix);
69 | }
70 | break;
71 | default:
72 | throw new CoeReaderException("Unsupported radix: " + radix);
73 | }
74 | return new ByteArrayInputStream(bytes);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/CoeReaderException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | public class CoeReaderException extends Exception {
9 |
10 | public CoeReaderException() {}
11 |
12 | public CoeReaderException(String message) {
13 | super(message);
14 | }
15 |
16 | public CoeReaderException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public CoeReaderException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/Disassembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.Assemblable;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 | import me.zhanghai.mipsasm.util.IoUtils;
12 |
13 | import java.io.*;
14 | import java.nio.charset.StandardCharsets;
15 | import java.util.Map;
16 |
17 | public class Disassembler {
18 |
19 | public static void disassemble(InputStream inputStream, OutputStream outputStream)
20 | throws DisassemblerException {
21 |
22 | DisassemblyContext context = new DisassemblyContext();
23 |
24 | BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
25 | while (true) {
26 | BitArray bitArray;
27 | try {
28 | bitArray = IoUtils.readBitArray(bufferedInputStream);
29 | } catch (IOException e) {
30 | throw new DisassemblerException("Error reading", e);
31 | }
32 | if (bitArray == null) {
33 | break;
34 | }
35 | // 0 can be sll $zero, $zero, 0, making all spacing instructions. In this case we prefer interpreting it as
36 | // spacing.
37 | if (bitArray.length() == Constants.WORD_LENGTH && !bitArray.isZero()) {
38 | WordDisassembler.disassemble(bitArray, context);
39 | } else {
40 | StorageDirectiveDisassembler.disassemble(bitArray, context);
41 | }
42 | }
43 | context.packStorageDirective();
44 |
45 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
46 | for (Map.Entry entry : context.getAddressAssemblableMap().entrySet()) {
47 | Integer address = entry.getKey();
48 | String label = context.getLabel(address);
49 | if (label != null) {
50 | try {
51 | writer.write(label);
52 | writer.write(":");
53 | writer.newLine();
54 | } catch (IOException e) {
55 | throw new DisassemblerException("Error writing label: " + label, e);
56 | }
57 | }
58 | Assemblable assemblable = entry.getValue();
59 | String assemblableString = assemblable.toString();
60 | try {
61 | writer.write(assemblableString);
62 | writer.newLine();
63 | } catch (IOException e) {
64 | throw new DisassemblerException("Error writing assemblable: " + assemblableString, e);
65 | }
66 | }
67 | try {
68 | writer.flush();
69 | } catch (IOException e) {
70 | throw new DisassemblerException("Error writing", e);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/DisassemblerException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | public class DisassemblerException extends Exception {
9 |
10 | public DisassemblerException() {}
11 |
12 | public DisassemblerException(String message) {
13 | super(message);
14 | }
15 |
16 | public DisassemblerException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public DisassemblerException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/DisassemblyContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.Assemblable;
10 | import me.zhanghai.mipsasm.assembler.SpaceDirective;
11 | import me.zhanghai.mipsasm.assembler.StorageDirective;
12 | import me.zhanghai.mipsasm.util.BitArray;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.NavigableMap;
17 | import java.util.TreeMap;
18 |
19 | public class DisassemblyContext {
20 |
21 | private Integer labelIndex = 0;
22 |
23 | private NavigableMap addressLabelMap = new TreeMap<>();
24 |
25 | // WONTFIX: Maximum address can be checked when addLabel() is called, however this adds the overhead of knowing the
26 | // length of the input stream during the first pass.
27 | private Integer address = 0;
28 |
29 | private NavigableMap addressAssemblableMap = new TreeMap<>();
30 |
31 | private String makeLabelName() {
32 | String name = "label_" + labelIndex;
33 | ++labelIndex;
34 | return name;
35 | }
36 |
37 | public String addLabel(Integer address) {
38 | String name = addressLabelMap.get(address);
39 | if (name != null) {
40 | return name;
41 | }
42 | name = makeLabelName();
43 | addressLabelMap.put(address, name);
44 | return name;
45 | }
46 |
47 | public NavigableMap getAddressLabelMap() {
48 | return addressLabelMap;
49 | }
50 |
51 | public String getLabel(Integer address) {
52 | return addressLabelMap.get(address);
53 | }
54 |
55 | public NavigableMap getAddressAssemblableMap() {
56 | return addressAssemblableMap;
57 | }
58 |
59 | public Integer getAddress() {
60 | return address;
61 | }
62 |
63 | public void appendAssemblable(Assemblable assemblable, int length) {
64 | addressAssemblableMap.put(address, assemblable);
65 | address += length;
66 | }
67 |
68 | private boolean isByteStorageDirective(Assemblable assemblable) {
69 | return assemblable != null && assemblable instanceof StorageDirective
70 | && ((StorageDirective) assemblable).getValue().length() == Constants.BYTE_LENGTH;
71 | }
72 |
73 | private void packByteStorageDirective() {
74 |
75 | for (Integer address1 = addressAssemblableMap.firstKey(); address1 != null;
76 | address1 = addressAssemblableMap.higherKey(address1)) {
77 |
78 | if (address1 % Constants.BYTES_PER_WORD != 0) {
79 | continue;
80 | }
81 | Assemblable assemblable1 = addressAssemblableMap.get(address1);
82 | if (!isByteStorageDirective(assemblable1)) {
83 | continue;
84 | }
85 | Integer address2 = address1 + 1;
86 | if (addressLabelMap.containsKey(address2)) {
87 | continue;
88 | }
89 | Assemblable assemblable2 = addressAssemblableMap.get(address2);
90 | if (!isByteStorageDirective(assemblable2)) {
91 | continue;
92 | }
93 | Integer address3 = address2 + 1;
94 | if (addressLabelMap.containsKey(address3)) {
95 | continue;
96 | }
97 | Assemblable assemblable3 = addressAssemblableMap.get(address3);
98 | if (!isByteStorageDirective(assemblable3)) {
99 | continue;
100 | }
101 | Integer address4 = address3 + 1;
102 | if (addressLabelMap.containsKey(address4)) {
103 | continue;
104 | }
105 | Assemblable assemblable4 = addressAssemblableMap.get(address4);
106 | if (!isByteStorageDirective(assemblable4)) {
107 | continue;
108 | }
109 |
110 | StorageDirective storageDirective = StorageDirective.of(BitArray.of(
111 | ((StorageDirective) assemblable1).getValue(),
112 | ((StorageDirective) assemblable2).getValue(),
113 | ((StorageDirective) assemblable3).getValue(),
114 | ((StorageDirective) assemblable4).getValue()));
115 | addressAssemblableMap.put(address1, storageDirective);
116 | addressAssemblableMap.remove(address2);
117 | addressAssemblableMap.remove(address3);
118 | addressAssemblableMap.remove(address4);
119 | }
120 | }
121 |
122 | private boolean isZeroWordStorageDirective(Assemblable assemblable) {
123 | if (assemblable != null && assemblable instanceof StorageDirective) {
124 | BitArray value = ((StorageDirective) assemblable).getValue();
125 | if (value.length() == Constants.WORD_LENGTH && value.isZero()) {
126 | return true;
127 | }
128 | }
129 | return false;
130 | }
131 |
132 | private void packZeroWordStorageDirective() {
133 |
134 | List addressList = new ArrayList<>();
135 |
136 | for (Integer address = addressAssemblableMap.firstKey(); address != null;
137 | address = addressAssemblableMap.higherKey(address)) {
138 |
139 | if ((addressList.isEmpty() || !addressLabelMap.containsKey(address))
140 | && isZeroWordStorageDirective(addressAssemblableMap.get(address))) {
141 | addressList.add(address);
142 | continue;
143 | }
144 |
145 | if (addressList.size() > 1) {
146 | for (Integer listAddress : addressList) {
147 | addressAssemblableMap.remove(listAddress);
148 | }
149 | addressAssemblableMap.put(addressList.get(0),
150 | SpaceDirective.of(Constants.BYTES_PER_WORD * addressList.size()));
151 | }
152 | addressList.clear();
153 |
154 | if (isZeroWordStorageDirective(addressAssemblableMap.get(address))) {
155 | addressList.add(address);
156 | }
157 | }
158 | if (addressList.size() > 1) {
159 | for (Integer listAddress : addressList) {
160 | addressAssemblableMap.remove(listAddress);
161 | }
162 | addressAssemblableMap.put(addressList.get(0),
163 | SpaceDirective.of(Constants.BYTES_PER_WORD * addressList.size()));
164 | }
165 | }
166 |
167 | public void packStorageDirective() {
168 | packByteStorageDirective();
169 | packZeroWordStorageDirective();
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/InstructionDisassembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.assembler.InstructionInformation;
9 | import me.zhanghai.mipsasm.util.BitArray;
10 |
11 | public interface InstructionDisassembler {
12 | void disassemble(InstructionInformation information, BitArray bitArray, DisassemblyContext context);
13 | }
14 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/InstructionWordDisassembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.InternalException;
10 | import me.zhanghai.mipsasm.assembler.InstructionInformation;
11 | import me.zhanghai.mipsasm.assembler.Operation;
12 | import me.zhanghai.mipsasm.util.BitArray;
13 |
14 | public class InstructionWordDisassembler {
15 |
16 | public static void disassemble(BitArray bitArray, DisassemblyContext context) throws DisassemblerException {
17 |
18 | if (bitArray.length() != Constants.INSTRUCTION_LENGTH) {
19 | throw new InternalException(new IllegalArgumentException(
20 | "BitArray cannot be an instruction by its length, BitArray: " + bitArray));
21 | }
22 |
23 | BitArray operationCode = bitArray.subArray(26, 32);
24 | BitArray operationSource = bitArray.subArray(21, 26);
25 | BitArray operationSource2 = bitArray.subArray(16, 21);
26 | BitArray operationFunction = bitArray.subArray(0, 6);
27 | Operation operation;
28 | try {
29 | operation = Operation.of(operationCode, operationSource, operationSource2, operationFunction);
30 | } catch (IllegalArgumentException e) {
31 | throw new NoSuchOperationException("Instruction: " + bitArray, e);
32 | }
33 |
34 | InstructionInformation instructionInformation = InstructionInformation.ofOperation(operation);
35 | InstructionDisassembler instructionDisassembler;
36 | try {
37 | instructionDisassembler = instructionInformation.getDisassembler();
38 | } catch (InternalException e) {
39 | throw new DisassemblerException("Operation has no instruction disassembler: " + operation, e);
40 | }
41 | instructionDisassembler.disassemble(instructionInformation, bitArray, context);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/NoSuchOperationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | public class NoSuchOperationException extends DisassemblerException {
9 |
10 | public NoSuchOperationException() {}
11 |
12 | public NoSuchOperationException(String message) {
13 | super(message);
14 | }
15 |
16 | public NoSuchOperationException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public NoSuchOperationException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/StorageDirectiveDisassembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.StorageDirective;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 |
12 | public class StorageDirectiveDisassembler {
13 |
14 | // Storage directive must be disassemble to .byte s first so that labels can be at any byte address.
15 | public static void disassemble(BitArray bitArray, DisassemblyContext context) throws DisassemblerException {
16 | switch (bitArray.length()) {
17 | case 4 * Constants.BYTE_LENGTH:
18 | context.appendAssemblable(StorageDirective.of(bitArray.subArray(3 * Constants.BYTE_LENGTH,
19 | 4 * Constants.BYTE_LENGTH)), 1);
20 | // Fall through!
21 | case 3 * Constants.BYTE_LENGTH:
22 | context.appendAssemblable(StorageDirective.of(bitArray.subArray(2 * Constants.BYTE_LENGTH,
23 | 3 * Constants.BYTE_LENGTH)), 1);
24 | // Fall through!
25 | case 2 * Constants.BYTE_LENGTH:
26 | context.appendAssemblable(StorageDirective.of(bitArray.subArray(Constants.BYTE_LENGTH,
27 | 2 * Constants.BYTE_LENGTH)), 1);
28 | // Fall through
29 | case Constants.BYTE_LENGTH:
30 | context.appendAssemblable(StorageDirective.of(bitArray.subArray(0, Constants.BYTE_LENGTH)), 1);
31 | break;
32 | default:
33 | throw new DisassemblerException("Storage directive length is not 1 to 4 bytes: "
34 | + bitArray.length());
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/disassembler/WordDisassembler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.disassembler;
7 |
8 | import me.zhanghai.mipsasm.util.BitArray;
9 |
10 | public class WordDisassembler {
11 |
12 | public static void disassemble(BitArray bitArray, DisassemblyContext context) throws DisassemblerException {
13 | try {
14 | InstructionWordDisassembler.disassemble(bitArray, context);
15 | } catch (DisassemblerException e) {
16 | StorageDirectiveDisassembler.disassemble(bitArray, context);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/gui/AboutDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.gui;
7 |
8 | import org.eclipse.swt.SWT;
9 | import org.eclipse.swt.events.SelectionAdapter;
10 | import org.eclipse.swt.events.SelectionEvent;
11 | import org.eclipse.swt.graphics.Image;
12 | import org.eclipse.swt.layout.RowLayout;
13 | import org.eclipse.swt.program.Program;
14 | import org.eclipse.swt.widgets.*;
15 |
16 | import java.util.ResourceBundle;
17 |
18 | public class AboutDialog extends Dialog {
19 |
20 | private static final String WEBSITE_URL = "https://github.com/zhanghai/mipsasm";
21 |
22 | private static final String LICENSE_URL = "https://www.gnu.org/licenses/gpl.html";
23 |
24 | private Shell shell;
25 |
26 | private ResourceBundle resourceBundle;
27 |
28 | private Image icon;
29 |
30 | public AboutDialog(Shell shell, ResourceBundle resourceBundle, Image icon) {
31 | super(shell);
32 | this.resourceBundle = resourceBundle;
33 | this.icon = icon;
34 | }
35 |
36 | public AboutDialog(Shell shell, int style, ResourceBundle resourceBundle, Image icon) {
37 | super(shell, style);
38 | this.resourceBundle = resourceBundle;
39 | this.icon = icon;
40 | }
41 |
42 | public void open() {
43 |
44 | onCreateShell();
45 |
46 | shell.open();
47 | Display display = getParent().getDisplay();
48 | while (!shell.isDisposed()) {
49 | if (!display.readAndDispatch()) {
50 | display.sleep();
51 | }
52 | }
53 | }
54 |
55 | public void onCreateShell() {
56 |
57 | shell = new Shell(getParent());
58 |
59 | shell.setText(resourceBundle.getString("about.title"));
60 |
61 | RowLayout rowLayout = new RowLayout();
62 | rowLayout.marginWidth = rowLayout.marginHeight = 12;
63 | rowLayout.center = true;
64 | rowLayout.spacing = 12;
65 | rowLayout.type = SWT.VERTICAL;
66 | shell.setLayout(rowLayout);
67 |
68 | Label iconLabel = new Label(shell, SWT.NONE);
69 | iconLabel.setImage(icon);
70 |
71 | Label nameLabel = new Label(shell, SWT.NONE);
72 | nameLabel.setText(Display.getAppName());
73 | SwtUtils.setFontStyle(nameLabel, SWT.BOLD);
74 |
75 | Label versionLabel = new Label(shell, SWT.NONE);
76 | versionLabel.setText(Display.getAppVersion());
77 |
78 | Label descriptionLabel = new Label(shell, SWT.NONE);
79 | descriptionLabel.setText(resourceBundle.getString("about.description"));
80 |
81 | Link websiteLink = new Link(shell, SWT.NONE);
82 | websiteLink.setText("" + resourceBundle.getString("about.website") + "");
83 | websiteLink.addSelectionListener(new SelectionAdapter() {
84 | @Override
85 | public void widgetSelected(SelectionEvent e) {
86 | Program.launch(WEBSITE_URL);
87 | }
88 | });
89 |
90 | Label copyrightLabel = new Label(shell, SWT.NONE);
91 | copyrightLabel.setText(resourceBundle.getString("about.copyright"));
92 | SwtUtils.setFontHeight(copyrightLabel, 10);
93 |
94 | Composite licenseComposite = new Composite(shell, SWT.NONE);
95 | RowLayout licenseCompositeLayout = new RowLayout();
96 | licenseCompositeLayout.center = true;
97 | licenseCompositeLayout.type = SWT.VERTICAL;
98 | licenseComposite.setLayout(licenseCompositeLayout);
99 | Label warrantyLink = new Label(licenseComposite, SWT.NONE);
100 | warrantyLink.setText(resourceBundle.getString("about.warranty"));
101 | SwtUtils.setFontHeight(warrantyLink, 10);
102 | Link licenseLink = new Link(licenseComposite, SWT.NONE);
103 | licenseLink.setText(resourceBundle.getString("about.license"));
104 | licenseLink.addSelectionListener(new SelectionAdapter() {
105 | @Override
106 | public void widgetSelected(SelectionEvent e) {
107 | Program.launch(LICENSE_URL);
108 | }
109 | });
110 | SwtUtils.setFontHeight(licenseLink, 10);
111 |
112 | shell.pack();
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/gui/FontDataBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.gui;
7 |
8 | import org.eclipse.swt.graphics.FontData;
9 |
10 | public class FontDataBuilder {
11 |
12 | private boolean nameSet;
13 | private String name;
14 | private boolean heightSet;
15 | private int height;
16 | private boolean styleSet;
17 | private int style;
18 | private boolean localeSet;
19 | private String locale;
20 |
21 | public FontDataBuilder setName(String name) {
22 | this.name = name;
23 | nameSet = true;
24 | return this;
25 | }
26 |
27 | public FontDataBuilder setHeight(int height) {
28 | this.height = height;
29 | heightSet = true;
30 | return this;
31 | }
32 |
33 | public FontDataBuilder setStyle(int style) {
34 | this.style = style;
35 | styleSet = true;
36 | return this;
37 | }
38 |
39 | public FontDataBuilder setLocale(String locale) {
40 | this.locale = locale;
41 | localeSet = true;
42 | return this;
43 | }
44 |
45 | public FontData build() {
46 | FontData fontData = new FontData();
47 | if (nameSet) {
48 | fontData.setName(name);
49 | }
50 | if (heightSet) {
51 | fontData.setHeight(height);
52 | }
53 | if (styleSet) {
54 | fontData.setStyle(style);
55 | }
56 | if (localeSet) {
57 | fontData.setLocale(locale);
58 | }
59 | return fontData;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/gui/MenuItemBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.gui;
7 |
8 | import org.eclipse.swt.SWT;
9 | import org.eclipse.swt.events.SelectionListener;
10 | import org.eclipse.swt.widgets.Menu;
11 | import org.eclipse.swt.widgets.MenuItem;
12 |
13 | public class MenuItemBuilder {
14 |
15 | private Menu parentMenu;
16 | private int style;
17 |
18 | private boolean selectionListenerSet;
19 | private SelectionListener selectionListener;
20 | private boolean acceleratorSet;
21 | private int accelerator;
22 | private boolean menuSet;
23 | private Menu menu;
24 | private boolean textSet;
25 | private String text;
26 |
27 | public MenuItemBuilder(Menu parentMenu, int style) {
28 | this.parentMenu = parentMenu;
29 | this.style = style;
30 | }
31 |
32 | public MenuItemBuilder(Menu parentMenu) {
33 | this(parentMenu, SWT.NULL);
34 | }
35 |
36 | public MenuItemBuilder addSelectionListener(SelectionListener selectionListener) {
37 | this.selectionListener = selectionListener;
38 | selectionListenerSet = true;
39 | return this;
40 | }
41 |
42 | public MenuItemBuilder setAccelerator(int accelerator) {
43 | this.accelerator = accelerator;
44 | acceleratorSet = true;
45 | return this;
46 | }
47 |
48 | public MenuItemBuilder setMenu(Menu menu) {
49 | this.menu = menu;
50 | menuSet = true;
51 | return this;
52 | }
53 |
54 | public MenuItemBuilder setText(String text) {
55 | this.text = text;
56 | textSet = true;
57 | return this;
58 | }
59 |
60 | public MenuItem build() {
61 | MenuItem menuItem = new MenuItem(parentMenu, style);
62 | if (selectionListenerSet) {
63 | menuItem.addSelectionListener(selectionListener);
64 | }
65 | if (acceleratorSet) {
66 | menuItem.setAccelerator(accelerator);
67 | }
68 | if (menuSet) {
69 | menuItem.setMenu(menu);
70 | }
71 | if (textSet) {
72 | menuItem.setText(text);
73 | }
74 | return menuItem;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/gui/StyledTextUndoRedoHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.gui;
7 |
8 | import org.eclipse.swt.SWT;
9 | import org.eclipse.swt.custom.ExtendedModifyEvent;
10 | import org.eclipse.swt.custom.ExtendedModifyListener;
11 | import org.eclipse.swt.custom.StyledText;
12 | import org.eclipse.swt.events.KeyEvent;
13 | import org.eclipse.swt.events.KeyListener;
14 |
15 | import java.util.Stack;
16 |
17 | /**
18 | * Adds the Undo-Redo functionality (working Ctrl+Z and Ctrl+Y) to an instance of {@link StyledText}.
19 | *
20 | * @author Petr Bodnar
21 | * @see
22 | * http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTUndoRedo.htm - inspiration for this code, though not
23 | * really functioning - it mainly shows which listeners to use...
24 | * @see
25 | * http://stackoverflow.com/questions/7179464/swt-how-to-recreate-a-default-context-menu-for-text-fields -
26 | * "SWT's StyledText doesn't support Undo-Redo out-of-the-box"
27 | */
28 | public class StyledTextUndoRedoHelper implements KeyListener, ExtendedModifyListener {
29 |
30 | /**
31 | * Encapsulation of the Undo and Redo stack(s).
32 | */
33 | private static class UndoRedoStack {
34 |
35 | private Stack undo;
36 | private Stack redo;
37 |
38 | public UndoRedoStack() {
39 | undo = new Stack<>();
40 | redo = new Stack<>();
41 | }
42 |
43 | public void pushUndo(T delta) {
44 | undo.add(delta);
45 | }
46 |
47 | public void pushRedo(T delta) {
48 | redo.add(delta);
49 | }
50 |
51 | public T popUndo() {
52 | return undo.pop();
53 | }
54 |
55 | public T popRedo() {
56 | return redo.pop();
57 | }
58 |
59 | public void clearUndo() {
60 | undo.clear();
61 | }
62 |
63 | public void clearRedo() {
64 | redo.clear();
65 | }
66 |
67 | public void clear() {
68 | clearUndo();
69 | clearRedo();
70 | }
71 |
72 | public boolean hasUndo() {
73 | return !undo.isEmpty();
74 | }
75 |
76 | public boolean hasRedo() {
77 | return !redo.isEmpty();
78 | }
79 | }
80 |
81 | private StyledText styledText;
82 |
83 | private UndoRedoStack stack;
84 |
85 | private boolean isUndo;
86 |
87 | private boolean isRedo;
88 |
89 | /**
90 | * Creates a new instance of this class. Automatically starts listening to corresponding key and modify events
91 | * coming from the given styledText.
92 | *
93 | * @param styledText the text field to which the Undo-Redo functionality should be added
94 | */
95 | public StyledTextUndoRedoHelper(StyledText styledText) {
96 |
97 | this.styledText = styledText;
98 | stack = new UndoRedoStack<>();
99 |
100 | styledText.addExtendedModifyListener(this);
101 | styledText.addKeyListener(this);
102 | }
103 |
104 | /*
105 | * (non-Javadoc)
106 | *
107 | * @see
108 | * org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
109 | */
110 | @Override
111 | public void keyPressed(KeyEvent e) {
112 | // Listen to CTRL+Z for Undo, to CTRL+Y or CTRL+SHIFT+Z for Redo
113 | boolean isCtrl = (e.stateMask & SWT.CTRL) > 0;
114 | boolean isAlt = (e.stateMask & SWT.ALT) > 0;
115 | if (isCtrl && !isAlt) {
116 | boolean isShift = (e.stateMask & SWT.SHIFT) > 0;
117 | if (!isShift && e.keyCode == 'z') {
118 | undo();
119 | } else if (!isShift && e.keyCode == 'y' || isShift
120 | && e.keyCode == 'z') {
121 | redo();
122 | }
123 | }
124 | }
125 |
126 | /*
127 | * (non-Javadoc)
128 | *
129 | * @see
130 | * org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
131 | */
132 | @Override
133 | public void keyReleased(KeyEvent e) {}
134 |
135 | /**
136 | * Creates a corresponding Undo or Redo step from the given event and pushes it to the stack. The Redo stack is,
137 | * logically, emptied if the event comes from a normal user action.
138 | *
139 | * @param event The event
140 | * @see org.eclipse.swt.custom.ExtendedModifyListener#modifyText(org.eclipse.swt.custom.ExtendedModifyEvent)
141 | */
142 | @Override
143 | public void modifyText(ExtendedModifyEvent event) {
144 | if (isUndo) {
145 | stack.pushRedo(event);
146 | } else { // is Redo or a normal user action
147 | stack.pushUndo(event);
148 | if (!isRedo) {
149 | stack.clearRedo();
150 | // TODO Switch to treat consecutive characters as one event?
151 | }
152 | }
153 | }
154 |
155 | public boolean canUndo() {
156 | return stack.hasUndo();
157 | }
158 |
159 | public boolean canRedo() {
160 | return stack.hasRedo();
161 | }
162 |
163 | /**
164 | * Performs the Undo action. A new corresponding Redo step is automatically pushed to the stack.
165 | */
166 | public void undo() {
167 | if (canUndo()) {
168 | isUndo = true;
169 | revertEvent(stack.popUndo());
170 | isUndo = false;
171 | }
172 | }
173 |
174 | /**
175 | * Performs the Redo action. A new corresponding Undo step is automatically pushed to the stack.
176 | */
177 | public void redo() {
178 | if (canRedo()) {
179 | isRedo = true;
180 | revertEvent(stack.popRedo());
181 | isRedo = false;
182 | }
183 | }
184 |
185 | public void clear() {
186 | stack.clear();
187 | }
188 |
189 | /**
190 | * Reverts the given modify event, in the way as the Eclipse text editor does it.
191 | *
192 | * @param event The event
193 | */
194 | private void revertEvent(ExtendedModifyEvent event) {
195 | // This causes the modifyText() listener method to be called.
196 | styledText.replaceTextRange(event.start, event.length, event.replacedText);
197 | styledText.setSelectionRange(event.start, event.replacedText.length());
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/gui/SwtUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.gui;
7 |
8 | import me.zhanghai.mipsasm.util.IoUtils;
9 | import org.eclipse.swt.SWT;
10 | import org.eclipse.swt.events.DisposeEvent;
11 | import org.eclipse.swt.events.DisposeListener;
12 | import org.eclipse.swt.graphics.Color;
13 | import org.eclipse.swt.graphics.Font;
14 | import org.eclipse.swt.graphics.FontData;
15 | import org.eclipse.swt.graphics.Image;
16 | import org.eclipse.swt.widgets.Control;
17 | import org.eclipse.swt.widgets.Display;
18 |
19 | import java.io.File;
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.nio.file.Files;
23 | import java.nio.file.StandardCopyOption;
24 |
25 | public class SwtUtils {
26 |
27 | private SwtUtils() {}
28 |
29 | public static boolean isDarkTheme() {
30 | Color widgetBackground = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
31 | int meanComponent = (widgetBackground.getRed() + widgetBackground.getGreen() + widgetBackground.getBlue()) / 3;
32 | return meanComponent < 0x7F;
33 | }
34 |
35 | public static void loadFont(String resourceName) throws IOException {
36 | File file = File.createTempFile(SwtUtils.class.getPackage().getName() + ".", null);
37 | try (InputStream resourceInputStream = SwtUtils.class.getResourceAsStream(resourceName)) {
38 | Files.copy(resourceInputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
39 | }
40 | file.deleteOnExit();
41 | Display.getCurrent().loadFont(file.getPath());
42 | }
43 |
44 | public static Image loadImage(String resourceName) {
45 | InputStream inputStream = SwtUtils.class.getResourceAsStream(resourceName);
46 | Image image = new Image(Display.getCurrent(), inputStream);
47 | IoUtils.close(inputStream);
48 | return image;
49 | }
50 |
51 | public static Image[] loadImageArray(String[] resourceNameArray) {
52 | Image[] imageArray = new Image[resourceNameArray.length];
53 | for (int i = 0; i < resourceNameArray.length; ++i) {
54 | imageArray[i] = loadImage(resourceNameArray[i]);
55 | }
56 | return imageArray;
57 | }
58 |
59 | public static void setFontHeight(Control control, int height) {
60 | Font oldFont = control.getFont();
61 | FontData[] fontDataArray = oldFont.getFontData();
62 | for (FontData fontData : fontDataArray) {
63 | fontData.setHeight(height);
64 | }
65 | final Font newFont = new Font(Display.getCurrent(), fontDataArray);
66 | control.setFont(newFont);
67 | control.addDisposeListener(new DisposeListener() {
68 | @Override
69 | public void widgetDisposed(DisposeEvent disposeEvent) {
70 | newFont.dispose();
71 | }
72 | });
73 | }
74 |
75 | public static void setFontStyle(Control control, int style) {
76 | Font oldFont = control.getFont();
77 | FontData[] fontDataArray = oldFont.getFontData();
78 | for (FontData fontData : fontDataArray) {
79 | fontData.setStyle(style);
80 | }
81 | final Font newFont = new Font(Display.getCurrent(), fontDataArray);
82 | control.setFont(newFont);
83 | control.addDisposeListener(new DisposeListener() {
84 | @Override
85 | public void widgetDisposed(DisposeEvent disposeEvent) {
86 | newFont.dispose();
87 | }
88 | });
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/gui/Utf8Control.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.gui;
7 |
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.InputStreamReader;
11 | import java.net.URL;
12 | import java.net.URLConnection;
13 | import java.nio.charset.StandardCharsets;
14 | import java.security.AccessController;
15 | import java.security.PrivilegedActionException;
16 | import java.security.PrivilegedExceptionAction;
17 | import java.util.Locale;
18 | import java.util.PropertyResourceBundle;
19 | import java.util.ResourceBundle;
20 |
21 | public class Utf8Control extends ResourceBundle.Control {
22 | @Override
23 | public ResourceBundle newBundle(String baseName, Locale locale, String format, final ClassLoader loader, final boolean reload)
24 | throws IllegalAccessException, InstantiationException, IOException {
25 | final String resourceName = toResourceName(toBundleName(baseName, locale), "properties");
26 | ResourceBundle bundle = null;
27 | InputStream stream;
28 | try {
29 | stream = AccessController.doPrivileged(
30 | new PrivilegedExceptionAction() {
31 | public InputStream run() throws IOException {
32 | InputStream is = null;
33 | if (reload) {
34 | URL url = loader.getResource(resourceName);
35 | if (url != null) {
36 | URLConnection connection = url.openConnection();
37 | if (connection != null) {
38 | // Disable caches to get fresh data for
39 | // reloading.
40 | connection.setUseCaches(false);
41 | is = connection.getInputStream();
42 | }
43 | }
44 | } else {
45 | is = loader.getResourceAsStream(resourceName);
46 | }
47 | return is;
48 | }
49 | });
50 | } catch (PrivilegedActionException e) {
51 | throw (IOException) e.getException();
52 | }
53 | if (stream != null) {
54 | try {
55 | bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8));
56 | } finally {
57 | stream.close();
58 | }
59 | }
60 | return bundle;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/AsciiDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 | import me.zhanghai.mipsasm.assembler.StorageDirective;
11 | import me.zhanghai.mipsasm.util.BitArray;
12 | import me.zhanghai.mipsasm.util.RegexUtils;
13 | import me.zhanghai.mipsasm.util.StringUtils;
14 | import me.zhanghai.mipsasm.util.UnsignedCompat;
15 |
16 | import java.nio.charset.StandardCharsets;
17 | import java.util.regex.Matcher;
18 |
19 | public class AsciiDirectiveParser {
20 |
21 | private static final ThreadLocal STRING_MATCHER = RegexUtils.makeThreadLocalMatcher(
22 | "(?0; found: 0");
30 | }
31 |
32 | Matcher stringMatcher = STRING_MATCHER.get();
33 | for (String operandString : operandStringList) {
34 | stringMatcher.reset(operandString);
35 | if (!stringMatcher.matches()) {
36 | throw new IllegalOperandException("Operand is not a string in double quotation marks: "
37 | + operandString);
38 | }
39 | String string = stringMatcher.group(1);
40 | string = StringUtils.unescapeMips(string);
41 | for (byte b : string.getBytes(StandardCharsets.US_ASCII)) {
42 | StorageDirective storage;
43 | storage = StorageDirective.of(BitArray.of(UnsignedCompat.unsignedByteToInt(b), Constants.BYTE_LENGTH));
44 | context.appendAssemblable(storage);
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/AsciizDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 | import me.zhanghai.mipsasm.assembler.StorageDirective;
11 | import me.zhanghai.mipsasm.util.BitArray;
12 |
13 | public class AsciizDirectiveParser {
14 |
15 | private AsciizDirectiveParser() {}
16 |
17 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
18 |
19 | for (String operandString : operandStringList) {
20 |
21 | AsciiDirectiveParser.parse(new String[]{operandString}, context);
22 |
23 | StorageDirective storage;
24 | storage = StorageDirective.of(BitArray.of(0, Constants.BYTE_LENGTH));
25 | context.appendAssemblable(storage);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/ByteDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 |
11 | public class ByteDirectiveParser {
12 |
13 | private ByteDirectiveParser() {}
14 |
15 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
16 | StorageDirectiveParser.parse(operandStringList, context, Constants.BYTE_LENGTH);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/CoprocessorFunctionParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.CoprocessorFunction;
9 |
10 | import javax.script.ScriptException;
11 |
12 | public class CoprocessorFunctionParser {
13 |
14 | private CoprocessorFunctionParser() {}
15 |
16 | public static CoprocessorFunction parse(String coprocessorFunctionString) throws ParserException {
17 | try {
18 | return CoprocessorFunction.of(JavaScriptParser.parseUnsignedInteger(coprocessorFunctionString));
19 | } catch (ScriptException | NumberFormatException e) {
20 | throw new IllegalOperandException("Unable to parse coprocessor function: " + coprocessorFunctionString, e);
21 | } catch (IllegalArgumentException e) {
22 | throw new IllegalOperandException("coprocessor function length too long: " + coprocessorFunctionString, e);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/DataDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.assembler.BackwardAddressException;
10 | import me.zhanghai.mipsasm.assembler.DataDirective;
11 | import me.zhanghai.mipsasm.assembler.WordImmediate;
12 |
13 | import javax.script.ScriptException;
14 | import java.util.Arrays;
15 |
16 | public class DataDirectiveParser {
17 |
18 | private DataDirectiveParser() {}
19 |
20 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
21 |
22 | if (operandStringList.length != 1) {
23 | throw new OperandCountMismatchException("Expected: [Address], found: "
24 | + Arrays.toString(operandStringList));
25 | }
26 |
27 | String addressString = operandStringList[0];
28 | WordImmediate address;
29 | try {
30 | address = WordImmediate.of(JavaScriptParser.parseUnsignedInteger(addressString));
31 | } catch (ScriptException | IllegalArgumentException e) {
32 | throw new IllegalOperandException("Address: " + addressString, e);
33 | }
34 | if (address.getValue().get(0) || address.getValue().get(1)) {
35 | throw new IllegalOperandException("Address is not word aligned: " + addressString);
36 | }
37 | try {
38 | context.appendAssemblable(DataDirective.of(address));
39 | } catch (BackwardAddressException e) {
40 | throw new IllegalOperandException("Address moves backward", e);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/DirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.assembler.DirectiveInformation;
10 | import me.zhanghai.mipsasm.util.RegexUtils;
11 |
12 | import java.util.regex.Matcher;
13 |
14 | public class DirectiveParser {
15 |
16 | private static final ThreadLocal MATCHER = RegexUtils.makeThreadLocalMatcher("(\\S+)(?:\\s+(.*))?");
17 |
18 | private DirectiveParser() {}
19 |
20 | public static void parse(String directiveString, AssemblyContext context) throws ParserException {
21 |
22 | Matcher matcher = MATCHER.get().reset(directiveString);
23 | if (!matcher.matches()) {
24 | throw new IllegalInstructionException("Instruction: " + directiveString);
25 | }
26 |
27 | String directiveName = matcher.group(1);
28 | DirectiveInformation directiveInformation;
29 | try {
30 | directiveInformation = DirectiveInformation.valueOf(directiveName.toUpperCase());
31 | } catch (IllegalArgumentException e) {
32 | throw new NoSuchDirectiveException("Directive: " + directiveName);
33 | }
34 |
35 | String operandListString = matcher.group(2);
36 | String[] operandStringList = ParserSplitUtils.splitOperands(operandListString);
37 | directiveInformation.parse(operandStringList, context);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/EchoDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 |
10 | import javax.script.ScriptException;
11 |
12 | public class EchoDirectiveParser {
13 |
14 | private EchoDirectiveParser() {}
15 |
16 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
17 |
18 | if (operandStringList.length == 0) {
19 | throw new OperandCountMismatchException("Expected: >0; found: 0");
20 | }
21 |
22 | for (String operandString : operandStringList) {
23 | String line;
24 | try {
25 | line = JavaScriptParser.eval(operandString).toString();
26 | } catch (ScriptException e) {
27 | throw new ParserException("Error evaluating JavaScript", e);
28 | }
29 | try {
30 | LineParser.parse(line, context);
31 | } catch (ParserException e) {
32 | throw new ParserException("Error assembling echoed line: " + line, e);
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/EvalDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 |
10 | import javax.script.ScriptException;
11 |
12 | public class EvalDirectiveParser {
13 |
14 | private EvalDirectiveParser() {}
15 |
16 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
17 |
18 | if (operandStringList.length == 0) {
19 | throw new OperandCountMismatchException("Expected: >0; found: 0");
20 | }
21 |
22 | for (String operandString : operandStringList) {
23 | try {
24 | JavaScriptParser.eval(operandString);
25 | } catch (ScriptException e) {
26 | throw new ParserException("Error evaluating JavaScript", e);
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/HalfWordDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 |
11 | public class HalfWordDirectiveParser {
12 |
13 | private HalfWordDirectiveParser() {}
14 |
15 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
16 | StorageDirectiveParser.parse(operandStringList, context, Constants.HALF_WORD_LENGTH);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/IllegalDirectiveException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class IllegalDirectiveException extends ParserException {
9 |
10 | public IllegalDirectiveException() {}
11 |
12 | public IllegalDirectiveException(String message) {
13 | super(message);
14 | }
15 |
16 | public IllegalDirectiveException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public IllegalDirectiveException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/IllegalInstructionException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class IllegalInstructionException extends ParserException {
9 |
10 | public IllegalInstructionException() {}
11 |
12 | public IllegalInstructionException(String message) {
13 | super(message);
14 | }
15 |
16 | public IllegalInstructionException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public IllegalInstructionException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/IllegalLabelException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class IllegalLabelException extends ParserException {
9 |
10 | public IllegalLabelException() {}
11 |
12 | public IllegalLabelException(String message) {
13 | super(message);
14 | }
15 |
16 | public IllegalLabelException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public IllegalLabelException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/IllegalOperandException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class IllegalOperandException extends ParserException {
9 |
10 | public IllegalOperandException() {}
11 |
12 | public IllegalOperandException(String message) {
13 | super(message);
14 | }
15 |
16 | public IllegalOperandException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public IllegalOperandException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/IllegalStatementException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class IllegalStatementException extends ParserException {
9 |
10 | public IllegalStatementException() {}
11 |
12 | public IllegalStatementException(String message) {
13 | super(message);
14 | }
15 |
16 | public IllegalStatementException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public IllegalStatementException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/ImmediateParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.Immediate;
9 |
10 | import javax.script.ScriptException;
11 |
12 | public class ImmediateParser {
13 |
14 | private ImmediateParser() {}
15 |
16 | public static Immediate parse(String immediateString) throws ParserException {
17 | try {
18 | return Immediate.of(JavaScriptParser.parseInteger(immediateString));
19 | } catch (ScriptException | NumberFormatException e) {
20 | throw new IllegalOperandException("Unable to parse immediate: " + immediateString, e);
21 | } catch (IllegalArgumentException e) {
22 | throw new IllegalOperandException("Immediate length too long: " + immediateString, e);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/InstructionParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.*;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 |
13 | public class InstructionParser {
14 |
15 | private static final ThreadLocal MATCHER = RegexUtils.makeThreadLocalMatcher("(\\S+)(?:\\s+(.*))?");
16 |
17 | private InstructionParser() {}
18 |
19 | public static void parse(String instructionString, AssemblyContext context) throws ParserException {
20 |
21 | Matcher matcher = MATCHER.get().reset(instructionString);
22 | if (!matcher.matches()) {
23 | throw new IllegalInstructionException(instructionString);
24 | }
25 |
26 | String operationName = matcher.group(1);
27 | Operation operation;
28 | try {
29 | operation = Operation.valueOf(operationName.toUpperCase());
30 | } catch (IllegalArgumentException e) {
31 | throw new NoSuchOperationException(operationName);
32 | }
33 |
34 | String operandListString = matcher.group(2);
35 | String[] operandStringList = ParserSplitUtils.splitOperands(operandListString);
36 | OperandInstance[] operandInstances = OperandListParser.parse(operandStringList,
37 | InstructionInformation.ofOperation(operation).getOperandListPrototype());
38 |
39 | context.appendAssemblable(Instruction.of(operation, operandInstances));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/JavaScriptParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.util.IoUtils;
9 |
10 | import javax.script.ScriptEngine;
11 | import javax.script.ScriptEngineManager;
12 | import javax.script.ScriptException;
13 |
14 | public class JavaScriptParser {
15 |
16 | private static final ScriptEngine JAVA_SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("JavaScript");
17 |
18 | private JavaScriptParser() {}
19 |
20 | public static Object eval(String script) throws ScriptException {
21 | return JAVA_SCRIPT_ENGINE.eval(script);
22 | }
23 |
24 | private static String evalForInteger(String script) throws ScriptException {
25 | Object result = eval(script);
26 | // Double is default return type for Number.
27 | if (result instanceof Double && result.equals(Math.rint((Double) result))) {
28 | // Java's signed int will make 0x7FFFFFFF for values larger than that if we use Double.intValue().
29 | result = ((Double) result).longValue();
30 | }
31 | return result.toString();
32 | }
33 |
34 | public static int parseSignedInteger(String expression) throws ScriptException {
35 | try {
36 | return IoUtils.parseSignedInteger(expression);
37 | } catch (NumberFormatException e) {
38 | expression = evalForInteger(expression);
39 | return IoUtils.parseSignedInteger(expression);
40 | }
41 | }
42 |
43 | public static int parseUnsignedInteger(String expression) throws ScriptException {
44 | try {
45 | return IoUtils.parseUnsignedInteger(expression);
46 | } catch (NumberFormatException e) {
47 | expression = evalForInteger(expression);
48 | return IoUtils.parseUnsignedInteger(expression);
49 | }
50 | }
51 |
52 | public static int parseInteger(String expression) throws ScriptException {
53 | try {
54 | return IoUtils.parseInteger(expression);
55 | } catch (NumberFormatException e) {
56 | expression = evalForInteger(expression);
57 | return IoUtils.parseInteger(expression);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/LabelAlreadyDefinedException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class LabelAlreadyDefinedException extends ParserException {
9 |
10 | public LabelAlreadyDefinedException() {}
11 |
12 | public LabelAlreadyDefinedException(String message) {
13 | super(message);
14 | }
15 |
16 | public LabelAlreadyDefinedException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public LabelAlreadyDefinedException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/LabelOperandParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.Label;
9 |
10 | public class LabelOperandParser {
11 |
12 | private LabelOperandParser() {}
13 |
14 | public static Label parse(String labelString) throws ParserException {
15 | try {
16 | return Label.of(labelString);
17 | } catch (IllegalArgumentException e) {
18 | throw new IllegalLabelException("Label name: " + labelString, e);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/LabelParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 |
13 | public class LabelParser {
14 |
15 | private static final ThreadLocal MATCHER = RegexUtils.makeThreadLocalMatcher(Tokens.IDENTIFIER_REGEX);
16 |
17 | private LabelParser() {}
18 |
19 | public static void parse(String labelString, AssemblyContext context) throws ParserException {
20 |
21 | Matcher matcher = MATCHER.get().reset(labelString);
22 | if (!matcher.matches()) {
23 | throw new IllegalLabelException("Label: " + labelString);
24 | }
25 |
26 | context.setPendingLabel(labelString);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/LineParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 |
13 | public class LineParser {
14 |
15 | private static final ThreadLocal COMMENT_MATCHER = RegexUtils.makeThreadLocalMatcher(Tokens.COMMENT_REGEX);
16 |
17 | private LineParser() {}
18 |
19 | public static void parse(String line, AssemblyContext context) throws ParserException {
20 |
21 | line = COMMENT_MATCHER.get().reset(line).replaceAll("");
22 |
23 | for (String statementString : ParserSplitUtils.splitStatements(line)) {
24 | statementString = statementString.trim();
25 | if (statementString.isEmpty()) {
26 | continue;
27 | }
28 | StatementParser.parse(statementString, context);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/MigratorException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class MigratorException extends Exception {
9 |
10 | public MigratorException() {}
11 |
12 | public MigratorException(String message) {
13 | super(message);
14 | }
15 |
16 | public MigratorException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public MigratorException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/MultiplePendingLabelException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class MultiplePendingLabelException extends ParserException {
9 |
10 | public MultiplePendingLabelException() {}
11 |
12 | public MultiplePendingLabelException(String message) {
13 | super(message);
14 | }
15 |
16 | public MultiplePendingLabelException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public MultiplePendingLabelException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/NoSuchDirectiveException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class NoSuchDirectiveException extends ParserException {
9 |
10 | public NoSuchDirectiveException() {}
11 |
12 | public NoSuchDirectiveException(String message) {
13 | super(message);
14 | }
15 |
16 | public NoSuchDirectiveException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public NoSuchDirectiveException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/NoSuchOperationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class NoSuchOperationException extends ParserException {
9 |
10 | public NoSuchOperationException() {}
11 |
12 | public NoSuchOperationException(String message) {
13 | super(message);
14 | }
15 |
16 | public NoSuchOperationException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public NoSuchOperationException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/OffsetBaseParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.Immediate;
9 | import me.zhanghai.mipsasm.assembler.OffsetBase;
10 | import me.zhanghai.mipsasm.assembler.Register;
11 | import me.zhanghai.mipsasm.util.RegexUtils;
12 |
13 | import javax.script.ScriptException;
14 | import java.util.regex.Matcher;
15 |
16 | public class OffsetBaseParser {
17 |
18 | private static final ThreadLocal MATCHER =
19 | RegexUtils.makeThreadLocalMatcher("(\\S*)\\s*\\(\\s*(\\S+)\\s*\\)");
20 |
21 | private OffsetBaseParser() {}
22 |
23 | public static OffsetBase parse(String offsetBaseString) throws ParserException {
24 |
25 | Matcher offsetBaseMatcher = MATCHER.get().reset(offsetBaseString);
26 |
27 | if (!offsetBaseMatcher.matches()) {
28 | throw new IllegalOperandException("Cannot parse offset and base: " + offsetBaseString);
29 | }
30 |
31 | Immediate offset;
32 | String offsetString = offsetBaseMatcher.group(1);
33 | if (offsetString.isEmpty()) {
34 | offset = Immediate.of(0);
35 | } else {
36 | try {
37 | offset = Immediate.of(JavaScriptParser.parseSignedInteger(offsetString));
38 | } catch (ScriptException | NumberFormatException e) {
39 | throw new IllegalOperandException("Offset cannot be parsed: " + offsetString, e);
40 | } catch (IllegalArgumentException e) {
41 | throw new IllegalOperandException("Offset length to long: " + offsetString, e);
42 | }
43 | }
44 |
45 | Register base;
46 | String baseString = offsetBaseMatcher.group(2);
47 | base = RegisterParser.parse(baseString);
48 |
49 | return OffsetBase.of(base, offset);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/OffsetParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.Immediate;
9 | import me.zhanghai.mipsasm.assembler.Offset;
10 | import me.zhanghai.mipsasm.assembler.OffsetLabel;
11 |
12 | import javax.script.ScriptException;
13 |
14 | public class OffsetParser {
15 |
16 | private OffsetParser() {}
17 |
18 | public static Offset parse(String offsetString) throws ParserException {
19 | try {
20 | return Offset.of(Immediate.of(JavaScriptParser.parseSignedInteger(offsetString)));
21 | } catch (ScriptException | NumberFormatException e) {
22 | try {
23 | return Offset.of(OffsetLabel.of(offsetString));
24 | } catch (IllegalArgumentException ex) {
25 | throw new IllegalLabelException("Offset label name: " + offsetString, ex);
26 | }
27 | } catch (IllegalArgumentException e) {
28 | throw new IllegalOperandException("Offset value length too long", e);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/OperandCountMismatchException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class OperandCountMismatchException extends ParserException {
9 |
10 | public OperandCountMismatchException() {}
11 |
12 | public OperandCountMismatchException(String message) {
13 | super(message);
14 | }
15 |
16 | public OperandCountMismatchException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public OperandCountMismatchException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/OperandListParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.Operand;
9 | import me.zhanghai.mipsasm.assembler.OperandInstance;
10 | import me.zhanghai.mipsasm.assembler.OperandPrototype;
11 |
12 | import java.util.Arrays;
13 |
14 | public class OperandListParser {
15 |
16 | private OperandListParser() {}
17 |
18 | public static OperandInstance[] parse(String[] operandStringList, OperandPrototype[] operandListPrototype)
19 | throws ParserException {
20 |
21 | if (operandStringList.length != operandListPrototype.length) {
22 | throw new OperandCountMismatchException("Expected: " + Arrays.toString(operandListPrototype) + ", found: "
23 | + Arrays.toString(operandStringList));
24 | }
25 |
26 | int operandCount = operandListPrototype.length;
27 | OperandInstance[] operandListInstance = new OperandInstance[operandCount];
28 | for (int i = 0; i < operandCount; ++i) {
29 | OperandPrototype operandPrototype = operandListPrototype[i];
30 | String operandString = operandStringList[i];
31 | Operand operand;
32 | switch (operandPrototype.getType()) {
33 | case REGISTER:
34 | operand = RegisterParser.parse(operandString);
35 | break;
36 | case IMMEDIATE:
37 | operand = ImmediateParser.parse(operandString);
38 | break;
39 | case OFFSET:
40 | operand = OffsetParser.parse(operandString);
41 | break;
42 | case COPROCESSOR_FUNCTION:
43 | operand = CoprocessorFunctionParser.parse(operandString);
44 | break;
45 | case SHIFT_AMOUNT:
46 | operand = ShiftAmountParser.parse(operandString);
47 | break;
48 | case TARGET:
49 | operand = TargetParser.parse(operandString);
50 | break;
51 | case OFFSET_BASE:
52 | operand = OffsetBaseParser.parse(operandString);
53 | break;
54 | case WORD_IMMEDIATE:
55 | operand = WordImmediateParser.parse(operandString);
56 | break;
57 | case LABEL:
58 | operand = LabelOperandParser.parse(operandString);
59 | break;
60 | default:
61 | // Never happens.
62 | throw new RuntimeException("Unknown operand type: " + operandPrototype.getType());
63 | }
64 | operandListInstance[i] = OperandInstance.fromPrototype(operandPrototype, operand);
65 | }
66 |
67 | return operandListInstance;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/Parser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 |
10 | import java.io.BufferedReader;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.io.InputStreamReader;
14 | import java.nio.charset.StandardCharsets;
15 |
16 | public class Parser {
17 |
18 | private static final String CONTINUATION_STRING = "\\";
19 |
20 | private Parser() {}
21 |
22 | public static void parse(InputStream inputStream, AssemblyContext context) throws ParserException {
23 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
24 | int lineNumber = 0;
25 | String line = "";
26 | boolean hasContinuation = false;
27 | while (true) {
28 | ++lineNumber;
29 | try {
30 | if (hasContinuation) {
31 | line += reader.readLine();
32 | } else {
33 | line = reader.readLine();
34 | }
35 | } catch (IOException e) {
36 | throw new ParserException("Line " + lineNumber, e);
37 | }
38 | if (line == null) {
39 | break;
40 | }
41 | hasContinuation = line.endsWith(CONTINUATION_STRING);
42 | if (hasContinuation) {
43 | line = line.substring(0, line.length() - CONTINUATION_STRING.length());
44 | } else {
45 | try {
46 | LineParser.parse(line, context);
47 | } catch (ParserException e) {
48 | throw new ParserException("Line " + lineNumber + ": " + line, e);
49 | }
50 | }
51 | }
52 | context.finishAllocation();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/ParserException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class ParserException extends Exception {
9 |
10 | public ParserException() {}
11 |
12 | public ParserException(String message) {
13 | super(message);
14 | }
15 |
16 | public ParserException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public ParserException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/ParserSplitUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.util.StringUtils;
9 |
10 | import java.util.regex.Matcher;
11 |
12 | public class ParserSplitUtils {
13 |
14 | private static final String SPLIT_DEFAULT_STATEMENT_REGEX = "\\s*" + Tokens.STATEMENT_SEPARATOR_REGEX + "\\s*";
15 | private static final String SPLIT_DEFAULT_OPERAND_REGEX = "\\s*" + Tokens.OPERAND_SEPARATOR_REGEX + "\\s*";
16 | private static final String[] SPLIT_DEFAULT_QUOTES_REGEX = new String[] {"\"", "'"};
17 | private static final String[] SPLIT_DEFAULT_LEFT_BRACKET_REGEX = new String[] {"\\(", "\\[", "\\{"};
18 | private static final String[] SPLIT_DEFAULT_RIGHT_BRACKET_REGEX = new String[] {"\\)", "\\]", "\\}"};
19 | private static final ThreadLocal SPLIT_DEFAULT_STATEMENT_DELIMITER_MATCHER = new ThreadLocal() {
20 | @Override
21 | protected Matcher initialValue() {
22 | return StringUtils.prepareMatcherForSplit(SPLIT_DEFAULT_STATEMENT_REGEX, SPLIT_DEFAULT_QUOTES_REGEX,
23 | SPLIT_DEFAULT_LEFT_BRACKET_REGEX, SPLIT_DEFAULT_RIGHT_BRACKET_REGEX);
24 | }
25 | };
26 | private static final ThreadLocal SPLIT_DEFAULT_OPERAND_DELIMITER_MATCHER = new ThreadLocal() {
27 | @Override
28 | protected Matcher initialValue() {
29 | return StringUtils.prepareMatcherForSplit(SPLIT_DEFAULT_OPERAND_REGEX, SPLIT_DEFAULT_QUOTES_REGEX,
30 | SPLIT_DEFAULT_LEFT_BRACKET_REGEX, SPLIT_DEFAULT_RIGHT_BRACKET_REGEX);
31 | }
32 | };
33 |
34 | public static final String[] EMPTY_ARRAY = new String[] {};
35 |
36 | private ParserSplitUtils() {}
37 |
38 | private static String[] trimEmptyArray(String[] array) {
39 | if (array.length == 1 && array[0].isEmpty()) {
40 | return EMPTY_ARRAY;
41 | } else {
42 | return array;
43 | }
44 | }
45 |
46 | public static String[] splitStatements(String string) {
47 | if (string == null) {
48 | return EMPTY_ARRAY;
49 | }
50 | return trimEmptyArray(StringUtils.split(string, SPLIT_DEFAULT_STATEMENT_REGEX, SPLIT_DEFAULT_QUOTES_REGEX,
51 | SPLIT_DEFAULT_LEFT_BRACKET_REGEX, SPLIT_DEFAULT_RIGHT_BRACKET_REGEX,
52 | SPLIT_DEFAULT_STATEMENT_DELIMITER_MATCHER.get()));
53 | }
54 |
55 | public static String[] splitOperands(String string) {
56 | if (string == null) {
57 | return EMPTY_ARRAY;
58 | }
59 | return trimEmptyArray(StringUtils.split(string, SPLIT_DEFAULT_OPERAND_REGEX, SPLIT_DEFAULT_QUOTES_REGEX,
60 | SPLIT_DEFAULT_LEFT_BRACKET_REGEX, SPLIT_DEFAULT_RIGHT_BRACKET_REGEX,
61 | SPLIT_DEFAULT_OPERAND_DELIMITER_MATCHER.get()));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/PendingLabelException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class PendingLabelException extends ParserException {
9 |
10 | public PendingLabelException() {}
11 |
12 | public PendingLabelException(String message) {
13 | super(message);
14 | }
15 |
16 | public PendingLabelException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public PendingLabelException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/RegisterParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.Register;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 |
13 | public class RegisterParser {
14 |
15 | private static final ThreadLocal MATCHER = RegexUtils.makeThreadLocalMatcher("\\$(\\S+)");
16 |
17 | private RegisterParser() {}
18 |
19 | public static Register parse(String registerString) throws ParserException {
20 |
21 | Matcher matcher = MATCHER.get().reset(registerString);
22 | if (!matcher.matches()) {
23 | throw new IllegalOperandException("Cannot parse register: " + registerString);
24 | }
25 |
26 | String registerName = matcher.group(1);
27 | try {
28 | return Register.values()[Integer.parseInt(registerName)];
29 | } catch (IndexOutOfBoundsException e) {
30 | throw new IllegalOperandException("Register index out of bounds: " + registerName, e);
31 | } catch (NumberFormatException ignored) {
32 | try {
33 | return Register.valueOf(registerName.toUpperCase());
34 | } catch (IllegalArgumentException e) {
35 | throw new IllegalOperandException("Invalid register name: " + registerName, e);
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/ShiftAmountParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.ShiftAmount;
9 |
10 | import javax.script.ScriptException;
11 |
12 | public class ShiftAmountParser {
13 |
14 | private ShiftAmountParser() {}
15 |
16 | public static ShiftAmount parse(String shiftAmountString) throws ParserException {
17 | try {
18 | return ShiftAmount.of(JavaScriptParser.parseUnsignedInteger(shiftAmountString));
19 | } catch (ScriptException | NumberFormatException e) {
20 | throw new IllegalOperandException("Unable to parse shift amount: " + shiftAmountString, e);
21 | } catch (IllegalArgumentException e) {
22 | throw new IllegalOperandException("Shift amount length too long: " + shiftAmountString, e);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/SpaceDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.assembler.SpaceDirective;
10 |
11 | import javax.script.ScriptException;
12 | import java.util.Arrays;
13 |
14 | public class SpaceDirectiveParser {
15 |
16 | private SpaceDirectiveParser() {}
17 |
18 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
19 |
20 | if (operandStringList.length != 1) {
21 | throw new OperandCountMismatchException("Expected: [ByteCount], found: "
22 | + Arrays.toString(operandStringList));
23 | }
24 |
25 | String byteCountString = operandStringList[0];
26 | SpaceDirective space;
27 | try {
28 | space = SpaceDirective.of(JavaScriptParser.parseUnsignedInteger(byteCountString));
29 | } catch (ScriptException | IllegalArgumentException e) {
30 | throw new IllegalOperandException("ByteCount: " + byteCountString, e);
31 | }
32 | context.appendAssemblable(space);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/SqsMigrator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.util.IoUtils;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 | import java.util.regex.Pattern;
13 |
14 | public class SqsMigrator {
15 |
16 | // RegexMigrator is case insensitive.
17 | private static final Migrator[] MIGRATORS = new Migrator[] {
18 | new RegexMigrator("#baseAddr", ".text"),
19 | new ColonedDirectiveMigrator("#DataAddre", "data"),
20 | new RegexMigrator("\\bdb\\b", ".byte"),
21 | new RegexMigrator("\\bdw\\b", ".half"),
22 | new RegexMigrator("\\bdd\\b", ".word"),
23 | new RegexMigrator("\\bresb\\b", ".space"),
24 | new RegexMigrator("\\bRESW\\b", ".space 2 *"),
25 | new RegexMigrator("\\bRESD\\b", ".space 4 *"),
26 | new MultiplicationMigrator(),
27 | new RegexMigrator("(? matcher;
54 | private String replacement;
55 |
56 | public RegexMigrator(String regex, String replacement) {
57 | this.matcher = RegexUtils.makeThreadLocalMatcher(regex, Pattern.CASE_INSENSITIVE);
58 | this.replacement = replacement;
59 | }
60 |
61 | @Override
62 | public String migrate(String text) {
63 | return matcher.get().reset(text).replaceAll(replacement);
64 | }
65 | }
66 |
67 | private static class ColonedDirectiveMigrator implements Migrator {
68 |
69 | private RegexMigrator migrator1, migrator2;
70 |
71 | protected ColonedDirectiveMigrator(RegexMigrator migrator1, RegexMigrator migrator2) {
72 | this.migrator1 = migrator1;
73 | this.migrator2 = migrator2;
74 | }
75 |
76 | public ColonedDirectiveMigrator(String colonedDirective, String directive) {
77 | migrator1 = new RegexMigrator(colonedDirective + ":(?=\\S)", "." + directive + " ");
78 | migrator2 = new RegexMigrator(colonedDirective + ":", "." + directive);
79 | }
80 |
81 | @Override
82 | public String migrate(String text) throws MigratorException {
83 | text = migrator1.migrate(text);
84 | return migrator2.migrate(text);
85 | }
86 | }
87 |
88 | private static class MultiplyingColonedDirectiveMigrator extends ColonedDirectiveMigrator {
89 |
90 | public MultiplyingColonedDirectiveMigrator(String colonedDirective, String directive, int multiplier) {
91 | super(new RegexMigrator(colonedDirective + ":(\\s+)", "." + directive + "$1" + multiplier + " * "),
92 | new RegexMigrator(colonedDirective + ":", "." + directive + multiplier + " * "));
93 | }
94 | }
95 |
96 | private static class MultiplicationMigrator implements Migrator {
97 | @Override
98 | public String migrate(String text) throws MigratorException {
99 | // HACK: For ignoring comment.
100 | Matcher matcher = Pattern.compile("(?
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.util.RegexUtils;
10 |
11 | import java.util.regex.Matcher;
12 |
13 | public class StatementParser {
14 |
15 | private static final String GROUP_LABEL = "label";
16 | private static final String GROUP_DIRECTIVE_OR_INSTRUCTION = "directiveOrInstruction";
17 | private static final ThreadLocal MATCHER = RegexUtils.makeThreadLocalMatcher(
18 | "(?:(?<" + GROUP_LABEL + ">\\S+):)?\\s*(?<" + GROUP_DIRECTIVE_OR_INSTRUCTION + ">.+)?");
19 |
20 | private static final String DIRECTIVE_PREFIX = ".";
21 |
22 | private StatementParser() {}
23 |
24 | public static void parse(String statement, AssemblyContext context) throws ParserException {
25 |
26 | Matcher matcher = MATCHER.get().reset(statement);
27 |
28 | if (!matcher.matches()) {
29 | throw new IllegalStatementException("Statement: " + statement);
30 | }
31 |
32 | String labelString = matcher.group(GROUP_LABEL);
33 | if (labelString != null) {
34 | LabelParser.parse(labelString, context);
35 | }
36 |
37 | String directiveOrInstructionString = matcher.group(GROUP_DIRECTIVE_OR_INSTRUCTION);
38 | if (directiveOrInstructionString != null) {
39 | if (directiveOrInstructionString.startsWith(DIRECTIVE_PREFIX)) {
40 | String directiveString = directiveOrInstructionString.substring(DIRECTIVE_PREFIX.length());
41 | DirectiveParser.parse(directiveString, context);
42 | } else {
43 | String instructionString = directiveOrInstructionString;
44 | InstructionParser.parse(instructionString, context);
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/StorageDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.assembler.StorageDirective;
10 |
11 | import javax.script.ScriptException;
12 |
13 | public abstract class StorageDirectiveParser {
14 |
15 | private StorageDirectiveParser() {}
16 |
17 | static void parse(String[] operandStringList, AssemblyContext context, int length) throws ParserException {
18 |
19 | if (operandStringList.length == 0) {
20 | throw new OperandCountMismatchException("Expected: >0; found: 0");
21 | }
22 |
23 | for (String operandString : operandStringList) {
24 | StorageDirective storage;
25 | try {
26 | storage = StorageDirective.of(JavaScriptParser.parseUnsignedInteger(operandString), length);
27 | } catch (ScriptException | IllegalArgumentException e) {
28 | throw new IllegalOperandException("Operand: " + operandString, e);
29 | }
30 | context.appendAssemblable(storage);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/TargetLabelParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.TargetLabel;
9 |
10 | public class TargetLabelParser {
11 |
12 | private TargetLabelParser() {}
13 |
14 | public static TargetLabel parse(String labelString) throws ParserException {
15 | try {
16 | return TargetLabel.of(labelString);
17 | } catch (IllegalArgumentException e) {
18 | throw new IllegalOperandException("Illegal label name: " + labelString, e);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/TargetParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.InstructionIndex;
9 | import me.zhanghai.mipsasm.assembler.Target;
10 | import me.zhanghai.mipsasm.assembler.TargetLabel;
11 |
12 | import javax.script.ScriptException;
13 |
14 | public class TargetParser {
15 |
16 | private TargetParser() {}
17 |
18 | public static Target parse(String targetString) throws ParserException {
19 | try {
20 | return Target.of(InstructionIndex.of(JavaScriptParser.parseUnsignedInteger(targetString)));
21 | } catch (ScriptException | NumberFormatException e) {
22 | try {
23 | return Target.of(TargetLabel.of(targetString));
24 | } catch (IllegalArgumentException ex) {
25 | throw new IllegalLabelException("Target label name: " + targetString, ex);
26 | }
27 | } catch (IllegalArgumentException e) {
28 | throw new IllegalOperandException("Target value length too long", e);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/TextDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.assembler.BackwardAddressException;
10 | import me.zhanghai.mipsasm.assembler.TextDirective;
11 | import me.zhanghai.mipsasm.assembler.WordImmediate;
12 |
13 | import javax.script.ScriptException;
14 | import java.util.Arrays;
15 |
16 | public class TextDirectiveParser {
17 |
18 | private TextDirectiveParser() {}
19 |
20 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
21 |
22 | if (operandStringList.length != 1) {
23 | throw new OperandCountMismatchException("Expected: [Address], found: "
24 | + Arrays.toString(operandStringList));
25 | }
26 |
27 | String addressString = operandStringList[0];
28 | WordImmediate address;
29 | try {
30 | address = WordImmediate.of(JavaScriptParser.parseUnsignedInteger(addressString));
31 | } catch (ScriptException | IllegalArgumentException e) {
32 | throw new IllegalOperandException("Address: " + addressString, e);
33 | }
34 | if (address.getValue().get(0) || address.getValue().get(1)) {
35 | throw new IllegalOperandException("Address is not word aligned: " + addressString);
36 | }
37 | try {
38 | context.appendAssemblable(TextDirective.of(address));
39 | } catch (BackwardAddressException e) {
40 | throw new IllegalOperandException("Address moves backward", e);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/Tokens.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | public class Tokens {
9 |
10 | private Tokens() {}
11 |
12 | public static final String COMMENT_REGEX = "(?:#.*)|(?://.*)|(?:/\\*.*?\\*/)";
13 |
14 | public static final String IDENTIFIER_REGEX = "[a-zA-Z._$][0-9a-zA-Z._$]*";
15 |
16 | public static final String STATEMENT_SEPARATOR_REGEX = ";";
17 |
18 | public static final String OPERAND_SEPARATOR_REGEX = ",";
19 |
20 | public static final String STRING_QUOTATION = "\"";
21 | }
22 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/WordDirectiveParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 |
11 | public class WordDirectiveParser {
12 |
13 | private WordDirectiveParser() {}
14 |
15 | public static void parse(String[] operandStringList, AssemblyContext context) throws ParserException {
16 | StorageDirectiveParser.parse(operandStringList, context, Constants.WORD_LENGTH);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/parser/WordImmediateParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.parser;
7 |
8 | import me.zhanghai.mipsasm.assembler.WordImmediate;
9 |
10 | import javax.script.ScriptException;
11 |
12 | public class WordImmediateParser {
13 |
14 | private WordImmediateParser() {}
15 |
16 | public static WordImmediate parse(String wordImmediateString) throws ParserException {
17 | try {
18 | return WordImmediate.of(JavaScriptParser.parseInteger(wordImmediateString));
19 | } catch (ScriptException | NumberFormatException e) {
20 | throw new IllegalOperandException("Unable to parse word immediate: " + wordImmediateString, e);
21 | } catch (IllegalArgumentException e) {
22 | throw new IllegalOperandException("Word immediate length too long: " + wordImmediateString, e);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/util/HexUnescaper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.util;
7 |
8 | import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
9 |
10 | import java.io.IOException;
11 | import java.io.Writer;
12 |
13 | public class HexUnescaper extends CharSequenceTranslator {
14 |
15 | @Override
16 | public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
17 |
18 | int remaining = input.length() - index - 1; // how many characters left, ignoring the leading \
19 | StringBuilder builder = new StringBuilder();
20 |
21 | if(input.charAt(index) == '\\' && remaining > 0 && isX(input.charAt(index + 1))) {
22 |
23 | int next2 = index + 2;
24 | int next3 = index + 3;
25 |
26 | if (remaining > 1 && isHexDigit(input.charAt(next2))) {
27 | builder.append(input.charAt(next2));
28 | if(remaining > 2 && isHexDigit(input.charAt(next3))) {
29 | builder.append(input.charAt(next3));
30 | }
31 | }
32 |
33 | out.write(Integer.parseInt(builder.toString(), 16));
34 | return 2 + builder.length();
35 | }
36 | return 0;
37 | }
38 |
39 | private boolean isX(char ch) {
40 | return ch == 'x' || ch == 'X';
41 | }
42 |
43 | private boolean isHexDigit(char ch) {
44 | return ch >= '0' && ch <= '7';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/util/RegexUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.util;
7 |
8 | import java.util.regex.Matcher;
9 | import java.util.regex.Pattern;
10 |
11 | public class RegexUtils {
12 |
13 | private RegexUtils() {}
14 |
15 | public static ThreadLocal makeThreadLocalMatcher(final String regex) {
16 | return new ThreadLocal() {
17 | @Override
18 | protected Matcher initialValue() {
19 | return Pattern.compile(regex).matcher("");
20 | }
21 | };
22 | }
23 |
24 | public static ThreadLocal makeThreadLocalMatcher(final String regex, final int flags) {
25 | return new ThreadLocal() {
26 | @Override
27 | protected Matcher initialValue() {
28 | return Pattern.compile(regex, flags).matcher("");
29 | }
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/writer/BinaryWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.writer;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.util.BitArray;
10 |
11 | import java.io.DataOutputStream;
12 | import java.io.IOException;
13 | import java.io.OutputStream;
14 |
15 | public class BinaryWriter {
16 |
17 | public static void write(OutputStream outputStream, AssemblyContext context) throws WriterException {
18 |
19 | DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
20 | for (BitArray assembly : context.getAssembly()) {
21 | try {
22 | dataOutputStream.writeInt(assembly.value());
23 | } catch (IOException e) {
24 | throw new WriterException("Error writing " + String.format("%08X", assembly), e);
25 | }
26 | }
27 |
28 | try {
29 | dataOutputStream.flush();
30 | } catch (IOException e) {
31 | throw new WriterException("Error flushing", e);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/writer/CoeWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.writer;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 | import me.zhanghai.mipsasm.util.BitArray;
10 | import me.zhanghai.mipsasm.util.IoUtils;
11 |
12 | import java.io.BufferedWriter;
13 | import java.io.IOException;
14 | import java.io.OutputStream;
15 | import java.io.OutputStreamWriter;
16 | import java.nio.charset.StandardCharsets;
17 |
18 | public class CoeWriter {
19 |
20 | private static final int WORD_PER_LINE = 8;
21 |
22 | private CoeWriter() {}
23 |
24 | public static void write(OutputStream outputStream, AssemblyContext context) throws WriterException {
25 |
26 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
27 |
28 | try {
29 | writer.write("memory_initialization_radix=16;");
30 | writer.newLine();
31 | writer.write("memory_initialization_vector=");
32 | writer.newLine();
33 | } catch (IOException e) {
34 | throw new WriterException("Error writing header", e);
35 | }
36 |
37 | int wordIndex = 0;
38 | for (BitArray assembly : context.getAssembly()) {
39 | String assemblyString = IoUtils.wordToHexString(assembly.value());
40 | try {
41 | if (wordIndex != 0) {
42 | if (wordIndex % WORD_PER_LINE == 0) {
43 | writer.write(",");
44 | writer.newLine();
45 | } else {
46 | writer.write(", ");
47 | }
48 | }
49 | writer.write(assemblyString);
50 | ++wordIndex;
51 | } catch (IOException e) {
52 | throw new WriterException("Error writing " + assemblyString, e);
53 | }
54 | }
55 | try {
56 | writer.write(";");
57 | writer.newLine();
58 | } catch (IOException e) {
59 | throw new WriterException("Error writing footer", e);
60 | }
61 |
62 | try {
63 | writer.flush();
64 | } catch (IOException e) {
65 | throw new WriterException("Error flushing", e);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/writer/DebugWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.writer;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 | import me.zhanghai.mipsasm.util.IoUtils;
12 |
13 | import java.io.BufferedWriter;
14 | import java.io.IOException;
15 | import java.io.OutputStream;
16 | import java.io.OutputStreamWriter;
17 | import java.nio.charset.StandardCharsets;
18 |
19 | public class DebugWriter {
20 |
21 | private DebugWriter() {}
22 |
23 | public static void write(OutputStream outputStream, AssemblyContext context) throws WriterException {
24 |
25 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
26 |
27 | int address = 0;
28 | for (BitArray assembly : context.getAssembly()) {
29 | String assemblyString = IoUtils.wordToBinaryString(assembly.value());
30 | try {
31 | if (address % Constants.BYTES_PER_WORD == 0) {
32 | if (address != 0) {
33 | writer.newLine();
34 | }
35 | writer.write(IoUtils.wordToHexString(address));
36 | writer.write(": ");
37 | }
38 | writer.write(assemblyString);
39 | } catch (IOException e) {
40 | throw new WriterException("Error writing " + assemblyString, e);
41 | }
42 | address += assembly.length() / Constants.BYTE_LENGTH;
43 | }
44 |
45 | try {
46 | writer.newLine();
47 | writer.flush();
48 | } catch (IOException e) {
49 | throw new WriterException("Error writing", e);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/writer/HexDebugWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.writer;
7 |
8 | import me.zhanghai.mipsasm.Constants;
9 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
10 | import me.zhanghai.mipsasm.util.BitArray;
11 | import me.zhanghai.mipsasm.util.IoUtils;
12 |
13 | import java.io.BufferedWriter;
14 | import java.io.IOException;
15 | import java.io.OutputStream;
16 | import java.io.OutputStreamWriter;
17 | import java.nio.charset.StandardCharsets;
18 |
19 | public class HexDebugWriter {
20 |
21 | private HexDebugWriter() {}
22 |
23 | public static void write(OutputStream outputStream, AssemblyContext context) throws WriterException {
24 |
25 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
26 |
27 | int address = 0;
28 | for (BitArray assembly : context.getAssembly()) {
29 | String assemblyString = IoUtils.wordToHexString(assembly.value());
30 | try {
31 | if (address % (4 * Constants.BYTES_PER_WORD) == 0) {
32 | if (address != 0) {
33 | writer.newLine();
34 | }
35 | writer.write(IoUtils.wordToHexString(address));
36 | writer.write(":");
37 | }
38 | writer.write(" ");
39 | writer.write(assemblyString);
40 | } catch (IOException e) {
41 | throw new WriterException("Error writing " + assemblyString, e);
42 | }
43 | address += assembly.length() / Constants.BYTE_LENGTH;
44 | }
45 |
46 | try {
47 | writer.newLine();
48 | writer.flush();
49 | } catch (IOException e) {
50 | throw new WriterException("Error writing", e);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/writer/Writer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.writer;
7 |
8 | import me.zhanghai.mipsasm.assembler.AssemblyContext;
9 |
10 | import java.io.OutputStream;
11 |
12 | public enum Writer {
13 |
14 | BINARY,
15 | COE,
16 | DEBUG,
17 | HEXDEBUG;
18 |
19 | public void write(OutputStream outputStream, AssemblyContext context) throws WriterException {
20 | switch (this) {
21 | case BINARY:
22 | BinaryWriter.write(outputStream, context);
23 | break;
24 | case COE:
25 | CoeWriter.write(outputStream, context);
26 | break;
27 | case DEBUG:
28 | DebugWriter.write(outputStream, context);
29 | break;
30 | case HEXDEBUG:
31 | HexDebugWriter.write(outputStream, context);
32 | break;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/me/zhanghai/mipsasm/writer/WriterException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 Zhang Hai
3 | * All Rights Reserved.
4 | */
5 |
6 | package me.zhanghai.mipsasm.writer;
7 |
8 | public class WriterException extends Exception {
9 |
10 | public WriterException() {}
11 |
12 | public WriterException(String message) {
13 | super(message);
14 | }
15 |
16 | public WriterException(String message, Throwable cause) {
17 | super(message, cause);
18 | }
19 |
20 | public WriterException(Throwable cause) {
21 | super(cause);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/res/drawable/mipside_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_128.png
--------------------------------------------------------------------------------
/src/res/drawable/mipside_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_16.png
--------------------------------------------------------------------------------
/src/res/drawable/mipside_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_256.png
--------------------------------------------------------------------------------
/src/res/drawable/mipside_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_32.png
--------------------------------------------------------------------------------
/src/res/drawable/mipside_48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_48.png
--------------------------------------------------------------------------------
/src/res/drawable/mipside_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_512.png
--------------------------------------------------------------------------------
/src/res/drawable/mipside_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/drawable/mipside_64.png
--------------------------------------------------------------------------------
/src/res/font/SourceCodePro-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/font/SourceCodePro-Bold.ttf
--------------------------------------------------------------------------------
/src/res/font/SourceCodePro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhanghai/mipsasm/c919e5ac81a4f39adfda07c655d8182497f9eccc/src/res/font/SourceCodePro-Regular.ttf
--------------------------------------------------------------------------------
/src/res/string/mipside.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2015 Zhang Hai
3 | # All Rights Reserved.
4 | #
5 |
6 | app_name=MIPS Assembly IDE
7 |
8 | menu.file=&File
9 | menu.file.open=&Open…\tCtrl+O
10 | menu.file.open.filter_names=Assembly files (*.s, *.asm)|Text files (*.txt)|All files
11 | menu.file.import=&Import…\tCtrl+Alt+O
12 | menu.file.disassemble=&Disassemble…\tCtrl+Shift+O
13 | menu.file.disassemble.filter_names=Assembly output files (*.bin, *.coe)|Binary files (*.bin)|COE files(*.coe)|All files
14 | menu.file.save=&Save\tCtrl+S
15 | menu.file.save_as=Save &As…\tCtrl+Shift+S
16 | menu.file.save_as.filter_names=Assembly files (*.s)|Assembly files (*.asm)|Text files (*.txt)|All files
17 | menu.file.print=&Print…\tCtrl+P
18 | menu.file.exit=E&xit\tAlt+F4
19 | menu.edit=&Edit
20 | menu.edit.undo=&Undo\tCtrl+Z
21 | menu.edit.redo=&Redo\tCtrl+Y
22 | menu.edit.cut=Cu&t\tCtrl+Z
23 | menu.edit.copy=&Copy\tCtrl+C
24 | menu.edit.paste=&Paste\tCtrl+V
25 | menu.edit.delete=&Delete
26 | menu.edit.select_all=Select &All\tCtrl+A
27 | menu.assemble=&Assemble
28 | menu.assemble.binary=&Binary File\tF9
29 | menu.assemble.coe=&COE File\tF10
30 | menu.assemble.debug=&Debug File\tF11
31 | menu.assemble.all=&All\tF12
32 | menu.assemble.open_directory=&Open Output Directory\tF8
33 | menu.assemble.enable_delay_slot=&Enable Delay Slot
34 | menu.help=&Help
35 | menu.help.about=&About\tF1
36 | file.unsaved_document=Unsaved Document
37 | file.open_without_saving=You have unsaved changes. Are you sure to open another file?
38 | file.exit_without_saving=You have unsaved changes. Are you sure to exit?
39 | file.overwrite=File %s already exists. Overwrite?
40 | assemble.ok=Assemble saved to %s
41 | assemble.error=Error assembling %s
42 |
43 | about.title=About
44 | about.description=Developed for College of Computer Science, Zhejiang University
45 | about.website=View project on GitHub
46 | about.copyright=Copyright © 2015 Zhang Hai
47 | about.warranty=This program comes with absolutely no warranty.
48 | about.license=See the GNU General Public License, version 3 or later for details.
49 |
--------------------------------------------------------------------------------
/src/res/string/mipside_zh_CN.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2015 Zhang Hai
3 | # All Rights Reserved.
4 | #
5 |
6 | app_name=MIPS 汇编集成开发环境
7 |
8 | menu.file=文件(&F)
9 | menu.file.open=打开(&O)…\tCtrl+O
10 | menu.file.open.filter_names=汇编文件(*.s,*.asm)|文本文件(*.txt)|所有文件
11 | menu.file.import=导入(&I)…\tCtrl+Alt+O
12 | menu.file.disassemble=反汇编(&D)…\tCtrl+Shift+O
13 | menu.file.disassemble.filter_names=汇编输出文件(*.bin,*.coe)|二进制文件(*.bin)|COE 文件(*.coe)|所有文件
14 | menu.file.save=保存(&S)\tCtrl+S
15 | menu.file.save_as=另存为(&A)…\tCtrl+Shift+S
16 | menu.file.save_as.filter_names=汇编文件(*.s)|汇编文件(*.asm)|文本文件(*.txt)|所有文件
17 | menu.file.print=打印(&P)…\tCtrl+P
18 | menu.file.exit=退出(&X)\tAlt+F4
19 | menu.edit=编辑(&E)
20 | menu.edit.undo=撤销(&U)\tCtrl+Z
21 | menu.edit.redo=重做(&R)\tCtrl+Y
22 | menu.edit.cut=剪切(&T)\tCtrl+X
23 | menu.edit.copy=复制(&C)\tCtrl+C
24 | menu.edit.paste=粘贴(&P)\tCtrl+V
25 | menu.edit.delete=删除(&D)
26 | menu.edit.select_all=全选(&A)\tCtrl+A
27 | menu.assemble=汇编(&A)
28 | menu.assemble.binary=二进制文件(&B)\tF9
29 | menu.assemble.coe=COE 文件(&C)\tF10
30 | menu.assemble.debug=调试文件(&D)\tF11
31 | menu.assemble.all=全部(&A)\tF12
32 | menu.assemble.open_directory=打开输出目录(&O)\tF8
33 | menu.assemble.enable_delay_slot=启用延时槽(&E)
34 | menu.help=帮助(&H)
35 | menu.help.about=关于(&A)\tF1
36 | file.unsaved_document=未保存文档
37 | file.open_without_saving=更改尚未保存。确定要打开另一个文件吗?
38 | file.exit_without_saving=更改尚未保存。确定要退出吗?
39 | file.overwrite=文件 %s 已经存在。是否覆盖?
40 | assemble.ok=汇编结果已保存至 %s
41 | assemble.error=汇编 %s 时发生错误
42 |
43 | about.title=关于
44 | about.description=为浙江大学计算机科学与技术学院开发
45 | about.website=在 GitHub 上浏览本项目
46 | about.copyright=版权所有 © 2015 张海
47 | about.warranty=本程序无任何担保。
48 | about.license=详情见 GNU 通用公共许可证,第三版或以上。
49 |
--------------------------------------------------------------------------------
/test/.gitignore:
--------------------------------------------------------------------------------
1 | *.bin
2 | *.coe
3 |
--------------------------------------------------------------------------------
/test/hello_world.s:
--------------------------------------------------------------------------------
1 | # "Hello World" in MIPS assembly
2 | # From: http://labs.cs.upt.ro/labs/so2/html/resources/nachos-doc/mipsf.html
3 |
4 | # All program code is placed after the
5 | # .text assembler directive
6 | .text 0x0
7 |
8 | # The label 'main' represents the starting point
9 | main:
10 | # Run the print_string syscall which has code 4
11 | li $v0, 4 # Code for syscall: print_string
12 | la $a0, msg # Pointer to string (load the address of msg)
13 | syscall
14 | li $v0, 10 # Code for syscall: exit
15 | syscall
16 |
17 | # All memory structures are placed after the
18 | # .data assembler directive
19 | .data 0x20
20 |
21 | # The .asciiz assembler directive creates
22 | # an ASCII string in memory terminated by
23 | # the null character. Note that strings are
24 | # surrounded by double-quotes
25 |
26 | msg: .asciiz "Hello World!\n"
27 |
--------------------------------------------------------------------------------
/test/js.s:
--------------------------------------------------------------------------------
1 | .text 1 + 3 - 4
2 | .data {eval("a = 8"), Math.floor(Math.log(Math.pow(Math.E, 4)))}
3 | .text a + 8
4 | .eval a = [-1 + 2, 2, 4 - 1]
5 | .echo "mfc" + (a[0] - 1) + " $zero, $" + a[2]
6 |
--------------------------------------------------------------------------------
/test/migrate.s:
--------------------------------------------------------------------------------
1 | #baseAddr 0000
2 | j start;// 0
3 | add r0, r31, r15; //4
4 | // add $zero, $zero, $zero;//4
5 | add $zero, $zero, $zero;//8
6 | add $zero, $zero, $zero; // C
7 | add $zero, $zero, $zero; // 10
8 | add $zero, $zero, $zero; // 14
9 | add $zero, $zero, $zero; // 18
10 | add $zero, $zero, $zero; // 1C
11 |
12 | start: // 标号,可以不换行,后面直接跟代码
13 | nor $at, $zero, $zero; // r1=FFFFFFFF
14 | add $v1, $at, $at; // r3=FFFFFFFE
15 | add $v1, $v1, $v1; // r3=FFFFFFFC
16 | add $v1, $v1, $v1; // r3=FFFFFFF8
17 | add $v1, $v1, $v1; // r3=FFFFFFF0
18 |
19 | add $v1, $v1, $v1; // r3=FFFFFFE0
20 | add $v1, $v1, $v1; // r3=FFFFFFC0
21 | nor $s4, $v1, $zero;// r20=0000003F
22 | add $v1, $v1, $v1; // r3=FFFFFF80
23 | add $v1, $v1, $v1; // r3=FFFFFF00
24 |
25 | add $v1, $v1, $v1;// r3=FFFFFE00
26 | add $v1, $v1, $v1;// r3=FFFFFC00
27 | add $v1, $v1, $v1;// r3=FFFFF800
28 | add $v1, $v1, $v1;// r3=FFFFF000
29 |
30 | add $v1, $v1, $v1;// r3=FFFFE000
31 | add $v1, $v1, $v1;// r3=FFFFC000
32 | add $v1, $v1, $v1;// r3=FFFF8000
33 | add $v1, $v1, $v1;// r3=FFFF0000
34 |
35 | add $v1, $v1, $v1;// r3=FFFE0000
36 | add $v1, $v1, $v1;// r3=FFFC0000
37 | add $v1, $v1, $v1;// r3=FFF80000
38 | add $v1, $v1, $v1;// r3=FFF00000
39 |
40 | add $v1, $v1, $v1; // r3=FFE00000
41 | add $v1, $v1, $v1; // r3=FFC00000
42 | add $v1, $v1, $v1; // r3=FF800000
43 | add $v1, $v1, $v1; // r3=FF000000
44 |
45 | add $v1, $v1, $v1;// r3=FE000000
46 | add $v1, $v1, $v1;// r3=FC000000
47 | add $a2, $v1, $v1;// r6=F8000000
48 | add $v1, $a2, $a2;// r3=F0000000
49 |
50 | add $a0, $v1, $v1; // r4=E0000000
51 |
52 | add $t5, $a0, $a0; // r13=C0000000
53 | add $t0, $t5, $t5; // r8=80000000
54 |
55 | loop: // 标号,可以不换行,后面直接跟代码
56 | slt $v0, $zero, $at; // r2=00000001
57 | add $t6, $v0, $v0;
58 | add $t6, $t6, $t6; // r14=4
59 | nor $t2, $zero, $zero;// r10=FFFFFFFF
60 | add $t2, $t2, $t2; // r10=FFFFFFFE
61 |
62 | loop1:
63 | sw $a2, 4($v1); // 计数器端口:F0000004,送计数常数 r6=F8000000
64 | lw $a1, 0($v1);
65 | add $a1, $a1, $a1; // 左移
66 | add $a1, $a1, $a1;
67 | sw $a1, 0($v1);
68 |
69 | add $t1, $t1, $v0; // r9=r9+1
70 | sw $t1, 0($a0); // r9 送 r4=E0000000 七段码端口
71 | lw $t5, 14($zero); // 取存储器 20 单元预存数据至 r13,程序计数延时常数
72 |
73 | loop2: // 标号,可以不换行,后面直接跟代码
74 | lw $a1, 0($v1); // 读 GPIO 端口 F0000000 状态
75 | add $a1, $a1, $a1;
76 | add $a1, $a1, $a1; // 左移 2 位将 SW 与 LED 对齐,同时 D1D0 置 00,选择计数器 通道 0
77 | sw $a1, 0($v1); // r5 输 出 到 GPIO 端 口 F0000000,计数器通道 counter_set=00
78 |
79 | lw $a1, 0($v1); // 再读 GPIO 端口 F0000000 状态
80 | and $t3, $a1, $t0; // 取最高位=out0,屏蔽其余位送 r11
81 | // beq $t3, $t0, C_init; // out0=0,Counter 通道 0 溢出, 转计数器初始化, 修改 7 段码显示:C_init
82 | add $t5, $t5, $v0; // 程序计数延时
83 | beq $t5, $zero, C_init; // 程序计数 r13=0,转计数器初始化,修改 7 段码显示:C_init
84 |
85 | l_next:
86 | lw $a1, 0($v1); // 判断 7 段码显示模式:SW[4:3]控制
87 | add $s2, $t6, $t6; // 再读 GPIO 端口 F0000000 开关 SW 状态
88 | add $s6, $s2, $s2; // r14=4,r18=00000008
89 | add $s2, $s2, $s6; // r22=00000010
90 | and $t3, $a1, $s2; // r18=00000018(00011000)
91 | beq $t3, $zero, L20;// 取 SW[4:3]
92 | beq $t3, $s2, L21; // SW[4:3]=00,7 段显示"点"循环移位:L20, SW0=0
93 | add $s2, $t6, $t6; // SW[4:3]=11,显示七段图形,L21,SW0=0
94 | beq $t3, $s2, L22; // r18=8
95 | sw $t1, 0($a0); // SW[4:3]=01, 七段显示预置数字,L22, SW0=1
96 | j loop2; // SW[4:3]=10,显示 r9,SW0=1
97 |
98 | L20:
99 | beq $t2, $at, L4;
100 | j L3; // r10=ffffffff,转移 L4
101 |
102 |
103 | L4:
104 | nor $t2, $zero, $zero; // r10=ffffffff
105 | add $t2, $t2, $t2; // r10=fffffffe
106 |
107 | L3:
108 | sw $t2, 0($a0); // SW[4:3]=00,7 段显示点移位后显示
109 | j loop2;
110 |
111 | L21:
112 | lw $t1, 60($s1); // SW[4:3]=11,从内存取预存七段图形
113 | sw $t1, 0($a0); // SW[4:3]=11,显示七段图形
114 | j loop2;
115 |
116 | L22:
117 | lw $t1, 20($s1); // SW[4:3]=01,从内存取预存数字
118 | sw $t1, 0($a0); // SW[4:3]=01,七段显示预置数字
119 | j loop2;
120 |
121 | C_init:
122 | lw $t5, 14($zero); // 取程序计数延时初始化常数
123 | add $t2, $t2, $t2; // r10=fffffffc,7 段图形点左移
124 | or $t2, $t2, $v0; // r10 末位置 1,对应右上角不显示
125 | add $s1, $s1, $t6; // r17=00000004,LED 图形访存地址+4
126 | and $s1, $s1, $s4; // r17=000000XX,屏蔽地址高位,只取 6 位 add $t1, $t1, $v0
127 | add $t1, $t1, $v0; // r9+1
128 | beq $t1, $at, L6; // 若 r9=ffffffff,重置 r9=5
129 | j L7;
130 |
131 | L6:
132 | add $t1, $zero, $t6; // r9=4
133 | add $t1, $t1, $v0; // 重置 r9=5
134 |
135 | L7:
136 | lw $a1, 0($v1); // 读 GPIO 端口 F0000000 状态
137 | add $t3, $a1, $a1;
138 | add $t3, $t3, $t3; // 左移 2 位将 SW 与 LED 对齐,同时 D1D0 置 00,选择计数器通道 0
139 | sw $t3, 0($v1); // r5 输出到 GPIO 端口 F0000000,计数器通道 counter_set=00
140 | sw $a2, 4($v1); // 计数器端口:F0000004,送计数常数 r6=F8000000
141 |
142 | j l_next;
143 | // 从此处-0000FFFC 填“00000000”。
144 |
145 | #DataAddre: 00001000; // 数据地址,此处 00001000H 开始定义数据
146 | Data1: // 数据区 1, 标号
147 | dd 0xFFFFFF00, 0x000002AB, 0x80000000, 0x0000003F, 0x00000001, 0xFFFF0000, 0x0000FFFF, 0x80000000, 0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888, 0x99999999, 0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD, 0xEEEEEEEE, 0xFFFFFFFF;
148 | db 0x55, 0x56, 0x57, 0x58; // db伪指令,定义数据0x55...在00001060
149 | dw 'ab', 0x1234;// dw伪指令,定义数据0x41, 0x42, 0x1234在000010604
150 | dd 0x12345678; // dd伪指令,定义数据0x12345678在00001068
151 |
152 | data2:
153 | RESB 16; // data2是标号,从0000106C开始定义16个字节空间
154 | // 此处 00001070-00001FFC 填“00000000”。
155 |
156 | #DataAddre: 00002000; // 数据地址,此处 00002000H 开始定义数据
157 | Data2: // 数据区 2, 标号
158 | dd 0x557EF7E0, 0xD7BDFBD9, 0xD7DBFDB9, 0xDFCFFCFB, 0xDFCFBFFF, 0xF7F3DFFF, 0xFFFFDF3D, 0xFFFF9DB9, 0XFFFFBCFB, 0XDFCFFCFB, 0XDFCFBFFF, 0XD7DB9FFF, 0XD7DBFDB9, 0XD7BDFBD9, 0XFFFF07E0, 0X007E0FFF, 0X03BDF020, 0X03DEF820, 0X08002300;
159 | // 此处从0000204C-0000BFFC填“00000000”。
160 |
161 | #DataAddre: 0x0000C000; // 数据地址,此处0000C000H开始定义数据
162 | buffer:
163 | RESD 32; // 数据区3,buffer标号=0000C000,定义32个32位字空间,到 0000C080 结束
164 |
--------------------------------------------------------------------------------
/test/test.s:
--------------------------------------------------------------------------------
1 | .text 0x00000000
2 | j start; // 0
3 | add $zero, $zero, $zero; // 4
4 | add $zero, $zero, $zero; // 8
5 | add $zero, $zero, $zero; // C
6 | add $zero, $zero, $zero; // 10
7 | add $zero, $zero, $zero; // 14
8 | add $zero, $zero, $zero; // 18
9 | add $zero, $zero, $zero; // 1C
10 |
11 | start: // 标号,可以不换行,后面直接跟代码
12 | nor $at, $zero, $zero; // r1=FFFFFFFF
13 | add $v1, $at, $at; // r3=FFFFFFFE
14 | add $v1, $v1, $v1; // r3=FFFFFFFC
15 | add $v1, $v1, $v1; // r3=FFFFFFF8
16 | add $v1, $v1, $v1; // r3=FFFFFFF0
17 |
18 | add $v1, $v1, $v1; // r3=FFFFFFE0
19 | add $v1, $v1, $v1; // r3=FFFFFFC0
20 | nor $s4, $v1, $zero;// r20=0000003F
21 | add $v1, $v1, $v1; // r3=FFFFFF80
22 | add $v1, $v1, $v1; // r3=FFFFFF00
23 |
24 | add $v1, $v1, $v1;// r3=FFFFFE00
25 | add $v1, $v1, $v1;// r3=FFFFFC00
26 | add $v1, $v1, $v1;// r3=FFFFF800
27 | add $v1, $v1, $v1;// r3=FFFFF000
28 |
29 | add $v1, $v1, $v1;// r3=FFFFE000
30 | add $v1, $v1, $v1;// r3=FFFFC000
31 | add $v1, $v1, $v1;// r3=FFFF8000
32 | add $v1, $v1, $v1;// r3=FFFF0000
33 |
34 | add $v1, $v1, $v1;// r3=FFFE0000
35 | add $v1, $v1, $v1;// r3=FFFC0000
36 | add $v1, $v1, $v1;// r3=FFF80000
37 | add $v1, $v1, $v1;// r3=FFF00000
38 |
39 | add $v1, $v1, $v1; // r3=FFE00000
40 | add $v1, $v1, $v1; // r3=FFC00000
41 | add $v1, $v1, $v1; // r3=FF800000
42 | add $v1, $v1, $v1; // r3=FF000000
43 |
44 | add $v1, $v1, $v1;// r3=FE000000
45 | add $v1, $v1, $v1;// r3=FC000000
46 | add $a2, $v1, $v1;// r6=F8000000
47 | add $v1, $a2, $a2;// r3=F0000000
48 |
49 | add $a0, $v1, $v1; // r4=E0000000
50 |
51 | add $t5, $a0, $a0; // r13=C0000000
52 | add $t0, $t5, $t5; // r8=80000000
53 |
54 | loop: // 标号,可以不换行,后面直接跟代码
55 | slt $v0, $zero, $at; // r2=00000001
56 | add $t6, $v0, $v0;
57 | add $t6, $t6, $t6; // r14=4
58 | nor $t2, $zero, $zero;// r10=FFFFFFFF
59 | add $t2, $t2, $t2; // r10=FFFFFFFE
60 |
61 | loop1:
62 | sw $a2, 4($v1); // 计数器端口:F0000004,送计数常数 r6=F8000000
63 | lw $a1, 0($v1);
64 | add $a1, $a1, $a1; // 左移
65 | add $a1, $a1, $a1;
66 | sw $a1, 0($v1);
67 |
68 | add $t1, $t1, $v0; // r9=r9+1
69 | sw $t1, 0($a0); // r9 送 r4=E0000000 七段码端口
70 | lw $t5, 14($zero); // 取存储器 20 单元预存数据至 r13,程序计数延时常数
71 |
72 | loop2: // 标号,可以不换行,后面直接跟代码
73 | lw $a1, 0($v1); // 读 GPIO 端口 F0000000 状态
74 | add $a1, $a1, $a1;
75 | add $a1, $a1, $a1; // 左移 2 位将 SW 与 LED 对齐,同时 D1D0 置 00,选择计数器 通道 0
76 | sw $a1, 0($v1); // r5 输 出 到 GPIO 端 口 F0000000,计数器通道 counter_set=00
77 |
78 | lw $a1, 0($v1); // 再读 GPIO 端口 F0000000 状态
79 | and $t3, $a1, $t0; // 取最高位=out0,屏蔽其余位送 r11
80 | // beq $t3, $t0, C_init; // out0=0,Counter 通道 0 溢出, 转计数器初始化, 修改 7 段码显示:C_init
81 | add $t5, $t5, $v0; // 程序计数延时
82 | beq $t5, $zero, C_init; // 程序计数 r13=0,转计数器初始化,修改 7 段码显示:C_init
83 |
84 | l_next:
85 | lw $a1, 0($v1); // 判断 7 段码显示模式:SW[4:3]控制
86 | add $s2, $t6, $t6; // 再读 GPIO 端口 F0000000 开关 SW 状态
87 | add $s6, $s2, $s2; // r14=4,r18=00000008
88 | add $s2, $s2, $s6; // r22=00000010
89 | and $t3, $a1, $s2; // r18=00000018(00011000)
90 | beq $t3, $zero, L20;// 取 SW[4:3]
91 | beq $t3, $s2, L21; // SW[4:3]=00,7 段显示"点"循环移位:L20, SW0=0
92 | add $s2, $t6, $t6; // SW[4:3]=11,显示七段图形,L21,SW0=0
93 | beq $t3, $s2, L22; // r18=8
94 | sw $t1, 0($a0); // SW[4:3]=01, 七段显示预置数字,L22, SW0=1
95 | j loop2; // SW[4:3]=10,显示 r9,SW0=1
96 |
97 | L20:
98 | beq $t2, $at, L4;
99 | j L3; // r10=ffffffff,转移 L4
100 |
101 |
102 | L4:
103 | nor $t2, $zero, $zero; // r10=ffffffff
104 | add $t2, $t2, $t2; // r10=fffffffe
105 |
106 | L3:
107 | sw $t2, 0($a0); // SW[4:3]=00,7 段显示点移位后显示
108 | j loop2;
109 |
110 | L21:
111 | lw $t1, 60($s1); // SW[4:3]=11,从内存取预存七段图形
112 | sw $t1, 0($a0); // SW[4:3]=11,显示七段图形
113 | j loop2;
114 |
115 | L22:
116 | lw $t1, 20($s1); // SW[4:3]=01,从内存取预存数字
117 | sw $t1, 0($a0); // SW[4:3]=01,七段显示预置数字
118 | j loop2;
119 |
120 | C_init:
121 | lw $t5, 14($zero); // 取程序计数延时初始化常数
122 | add $t2, $t2, $t2; // r10=fffffffc,7 段图形点左移
123 | or $t2, $t2, $v0; // r10 末位置 1,对应右上角不显示
124 | add $s1, $s1, $t6; // r17=00000004,LED 图形访存地址+4
125 | and $s1, $s1, $s4; // r17=000000XX,屏蔽地址高位,只取 6 位 add $t1, $t1, $v0
126 | add $t1, $t1, $v0; // r9+1
127 | beq $t1, $at, L6; // 若 r9=ffffffff,重置 r9=5
128 | j L7;
129 |
130 | L6:
131 | add $t1, $zero, $t6; // r9=4
132 | add $t1, $t1, $v0; // 重置 r9=5
133 |
134 | L7:
135 | lw $a1, 0($v1); // 读 GPIO 端口 F0000000 状态
136 | add $t3, $a1, $a1;
137 | add $t3, $t3, $t3; // 左移 2 位将 SW 与 LED 对齐,同时 D1D0 置 00,选择计数器通道 0
138 | sw $t3, 0($v1); // r5 输出到 GPIO 端口 F0000000,计数器通道 counter_set=00
139 | sw $a2, 4($v1); // 计数器端口:F0000004,送计数常数 r6=F8000000
140 |
141 | j l_next;
142 | // 从此处-0000FFFC 填“00000000”。
143 |
144 | .data 0x00001000; // 数据地址,此处 00001000H 开始定义数据
145 | Data1: // 数据区 1, 标号
146 | .word 0xFFFFFF00, 0x000002AB, 0x80000000, 0x0000003F, 0x00000001, 0xFFFF0000, 0x0000FFFF, 0x80000000, 0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888, 0x99999999, 0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD, 0xEEEEEEEE, 0xFFFFFFFF;
147 | .byte 0x55, 0x56, 0x57, 0x58; // db伪指令,定义数据0x55...在00001060
148 | .ascii "ab";
149 | .half 0x1234;// dw伪指令,定义数据0x41, 0x42, 0x1234在000010604
150 | .word 0x12345678; // dd伪指令,定义数据0x12345678在00001068
151 |
152 | data2:
153 | .space 16; // data2是标号,从0000106C开始定义16个字节空间
154 | // 此处 00001070-00001FFC 填“00000000”。
155 |
156 | .data 0x00002000; // 数据地址,此处 00002000H 开始定义数据
157 | Data2: // 数据区 2, 标号
158 | .word 0x557EF7E0, 0xD7BDFBD9, 0xD7DBFDB9, 0xDFCFFCFB, 0xDFCFBFFF, 0xF7F3DFFF, 0xFFFFDF3D, 0xFFFF9DB9, 0XFFFFBCFB, 0XDFCFFCFB, 0XDFCFBFFF, 0XD7DB9FFF, 0XD7DBFDB9, 0XD7BDFBD9, 0XFFFF07E0, 0X007E0FFF, 0X03BDF020, 0X03DEF820, 0X08002300;
159 | // 此处从0000204C-0000BFFC填“00000000”。
160 |
161 | .data 0x0000C000; // 数据地址,此处0000C000H开始定义数据
162 | buffer:
163 | .space 128; // 数据区3,buffer标号=0000C000,定义32个32位字空间,到 0000C080 结束
164 |
--------------------------------------------------------------------------------