compiler: Format RV64 instructions with checked local buffers
648ff424c6b3a79aed6bb7e37e69f66ef6d5c18acdd58a1e73740df6616dca70
1 parent
59c7667a
compiler/radiance.rad
+1 -1
| 1327 | 1327 | let result = try lowerAndGenerateAllPackages(ctx, res, fnArena, CodegenOptions { |
|
| 1328 | 1328 | logPath: nil, |
|
| 1329 | 1329 | debug: false, |
|
| 1330 | 1330 | entryMode: CodegenEntryMode::None, |
|
| 1331 | 1331 | }); |
|
| 1332 | - | printer::printCodeTo(&mut out, entryPkg.name, result.code, result.funcs, res.arena); |
|
| 1332 | + | printer::printCodeTo(&mut out, entryPkg.name, result.code, result.funcs); |
|
| 1333 | 1333 | io::print("\n"); |
|
| 1334 | 1334 | ||
| 1335 | 1335 | return; |
|
| 1336 | 1336 | } |
|
| 1337 | 1337 | // Generate binary output if path specified. |
lib/std/arch/rv64/asm/tests.rad
+19 -12
| 13 | 13 | ||
| 14 | 14 | static ASM_ARENA_STORAGE: [u8; 65536] = [0; 65536]; |
|
| 15 | 15 | static ASM_TEXT_STORAGE: [u32; 256] = [0; 256]; |
|
| 16 | 16 | static ASM_DATA_STORAGE: [u8; 1024] = [0; 1024]; |
|
| 17 | 17 | unsafe static ASM_STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 }; |
|
| 18 | - | static PRINT_ARENA_STORAGE: [u8; 1024] = [0; 1024]; |
|
| 19 | - | static PRINT_BUFFER: [u8; 128] = [0; 128]; |
|
| 20 | 18 | ||
| 21 | 19 | /// The retired-instruction CSR assembles to its exact architectural encoding. |
|
| 22 | 20 | @test unsafe fn retiredCounter() throws (testing::TestError) { |
|
| 23 | 21 | let program = try assembleSource(".text;\ncsrr %a0 instret;\n"); |
|
| 24 | 22 | assert program.text.len == 1 and program.text[0] == 0xc0202573; |
| 71 | 69 | return; |
|
| 72 | 70 | }; |
|
| 73 | 71 | throw testing::TestError::Failed; |
|
| 74 | 72 | } |
|
| 75 | 73 | ||
| 76 | - | unsafe fn printInstrText(instr: u32) -> *[u8] { |
|
| 77 | - | let mut arena = alloc::new(&mut PRINT_ARENA_STORAGE[..]); |
|
| 78 | - | let mut pos: u32 = 0; |
|
| 79 | - | let bytes: 'output = &mut PRINT_BUFFER[..] in { |
|
| 74 | + | /// Compare the instruction text with the expected bytes. |
|
| 75 | + | fn expectInstrText(instr: u32, expected: &[u8]) throws (testing::TestError) { |
|
| 76 | + | let mut buffer: [u8; 128] = [0; 128]; |
|
| 77 | + | let bytes: 'output = &mut buffer[..] in { |
|
| 80 | 78 | let mut out = sexpr::Buffer 'output { buf: bytes, pos: 0 }; |
|
| 81 | - | printer::printInstr(&mut out, &mut arena, instr); |
|
| 82 | - | set pos = out.pos; |
|
| 79 | + | printer::printInstr(&mut out, instr); |
|
| 80 | + | try testing::expectBytesEq(&out.buf[..out.pos], expected); |
|
| 83 | 81 | } |
|
| 84 | - | return &PRINT_BUFFER[..pos]; |
|
| 85 | 82 | } |
|
| 86 | 83 | ||
| 87 | 84 | @test unsafe fn testAssemblePercentPrefixedRegisters() throws (testing::TestError) { |
|
| 88 | 85 | let program = try assembleSource( |
|
| 89 | 86 | ".text;\naddi %a0 %zero 42;\nsd %a0 8(%sp);\n" |
| 292 | 289 | try expectAssembleFail( |
|
| 293 | 290 | ".text;\ncsrsi mstatus 32;\n" |
|
| 294 | 291 | ); |
|
| 295 | 292 | } |
|
| 296 | 293 | ||
| 297 | - | @test unsafe fn testPrintInstrUsesPercentPrefixedRegisters() throws (testing::TestError) { |
|
| 298 | - | let text = printInstrText(encode::addi(rv64::A0, rv64::SP, 42)); |
|
| 299 | - | try testing::expect(mem::eq(text, "addi %a0, %sp, 42")); |
|
| 294 | + | @test fn testPrintInstrUsesPercentPrefixedRegisters() throws (testing::TestError) { |
|
| 295 | + | try expectInstrText(encode::addi(rv64::A0, rv64::SP, 42), "addi %a0, %sp, 42"); |
|
| 296 | + | } |
|
| 297 | + | ||
| 298 | + | /// Immediate operands preserve signs, separators, and address syntax. |
|
| 299 | + | @test fn testSafePrintImmediates() throws (testing::TestError) { |
|
| 300 | + | try expectInstrText(encode::addi(rv64::A0, rv64::ZERO, -2048), "li %a0, -2048"); |
|
| 301 | + | try expectInstrText(encode::ld(rv64::A0, rv64::SP, -8), "ld %a0, -8(%sp)"); |
|
| 302 | + | try expectInstrText(encode::sd(rv64::A0, rv64::SP, 16), "sd %a0, 16(%sp)"); |
|
| 303 | + | try expectInstrText(encode::beq(rv64::A0, rv64::SP, -4), "beq %a0, %sp, -4"); |
|
| 304 | + | try expectInstrText(encode::bne(rv64::A0, rv64::ZERO, 4), "bnez %a0, 4"); |
|
| 305 | + | try expectInstrText(encode::jal(rv64::ZERO, -4), "j -4"); |
|
| 306 | + | try expectInstrText(0xFFFFFFFF, "unknown(4294967295)"); |
|
| 300 | 307 | } |
lib/std/arch/rv64/printer.rad
+78 -72
| 1 | 1 | //! RV64 instruction printer. |
|
| 2 | 2 | //! |
|
| 3 | 3 | //! Prints 32-bit instructions in assembly text format. |
|
| 4 | 4 | ||
| 5 | 5 | use std::fmt; |
|
| 6 | - | use std::mem; |
|
| 7 | - | use std::lang::alloc; |
|
| 8 | 6 | use std::lang::gen; |
|
| 9 | 7 | use std::lang::sexpr; |
|
| 10 | 8 | use std::lang::gen::types; |
|
| 11 | 9 | ||
| 12 | 10 | use super::decode; |
| 42 | 40 | /// Write a string to output. |
|
| 43 | 41 | fn write(out: &mut opaque sexpr::Output, s: &[u8]) { |
|
| 44 | 42 | sexpr::write(out, s); |
|
| 45 | 43 | } |
|
| 46 | 44 | ||
| 47 | - | /// Format `i32` into arena. |
|
| 48 | - | unsafe fn formatI32(a: &mut alloc::Arena, val: i32) -> *[u8] { |
|
| 49 | - | let mut digits: [u8; 12] = undefined; |
|
| 45 | + | /// Write an `i32` before its stack buffer leaves scope. |
|
| 46 | + | fn writeI32(out: &mut opaque sexpr::Output, val: i32) { |
|
| 47 | + | let mut digits: [u8; 12] = [0; 12]; |
|
| 50 | 48 | let start = fmt::formatI32(val, &mut digits[..]); |
|
| 51 | - | let slice = try! alloc::allocSlice(a, 1, 1, digits.len - start) as *mut [u8]; |
|
| 52 | - | try! mem::copy(slice, &digits[start..]); |
|
| 53 | - | ||
| 54 | - | return slice; |
|
| 49 | + | write(out, &digits[start..]); |
|
| 55 | 50 | } |
|
| 56 | 51 | ||
| 57 | - | /// Format `u32` into arena. |
|
| 58 | - | unsafe fn formatU32(a: &mut alloc::Arena, val: u32) -> *[u8] { |
|
| 59 | - | let mut digits: [u8; 10] = undefined; |
|
| 52 | + | /// Write a `u32` before its stack buffer leaves scope. |
|
| 53 | + | fn writeU32(out: &mut opaque sexpr::Output, val: u32) { |
|
| 54 | + | let mut digits: [u8; 10] = [0; 10]; |
|
| 60 | 55 | let start = fmt::formatU32(val, &mut digits[..]); |
|
| 61 | - | let slice = try! alloc::allocSlice(a, 1, 1, digits.len - start) as *mut [u8]; |
|
| 62 | - | try! mem::copy(slice, &digits[start..]); |
|
| 63 | - | ||
| 64 | - | return slice; |
|
| 56 | + | write(out, &digits[start..]); |
|
| 65 | 57 | } |
|
| 66 | 58 | ||
| 67 | 59 | /////////////////////////////// |
|
| 68 | 60 | // Instruction Printing // |
|
| 69 | 61 | /////////////////////////////// |
| 107 | 99 | writeMnem(out, m); |
|
| 108 | 100 | writeDelim(out, &[regNameR(rd), regNameR(rs1), regNameR(rs2)]); |
|
| 109 | 101 | } |
|
| 110 | 102 | ||
| 111 | 103 | /// I-type: `op rd, rs1, imm`. |
|
| 112 | - | unsafe fn fmtI(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], rd: gen::Reg, rs1: gen::Reg, imm: i32) { |
|
| 104 | + | fn fmtI(out: &mut opaque sexpr::Output, m: *[u8], rd: gen::Reg, rs1: gen::Reg, imm: i32) { |
|
| 113 | 105 | writeMnem(out, m); |
|
| 114 | - | writeDelim(out, &[regNameR(rd), regNameR(rs1), formatI32(a, imm)]); |
|
| 106 | + | writeDelim(out, &[regNameR(rd), regNameR(rs1)]); |
|
| 107 | + | write(out, ", "); |
|
| 108 | + | writeI32(out, imm); |
|
| 115 | 109 | } |
|
| 116 | 110 | ||
| 117 | 111 | /// 2-reg: `op rd, rs`. |
|
| 118 | 112 | fn fmt2R(out: &mut opaque sexpr::Output, m: *[u8], rd: gen::Reg, rs: gen::Reg) { |
|
| 119 | 113 | writeMnem(out, m); |
|
| 120 | 114 | writeDelim(out, &[regNameR(rd), regNameR(rs)]); |
|
| 121 | 115 | } |
|
| 122 | 116 | ||
| 123 | 117 | /// reg + imm: `op rd, imm`. |
|
| 124 | - | unsafe fn fmtRI(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], rd: gen::Reg, imm: i32) { |
|
| 118 | + | fn fmtRI(out: &mut opaque sexpr::Output, m: *[u8], rd: gen::Reg, imm: i32) { |
|
| 125 | 119 | writeMnem(out, m); |
|
| 126 | - | writeDelim(out, &[regNameR(rd), formatI32(a, imm)]); |
|
| 120 | + | write(out, regNameR(rd)); |
|
| 121 | + | write(out, ", "); |
|
| 122 | + | writeI32(out, imm); |
|
| 127 | 123 | } |
|
| 128 | 124 | ||
| 129 | 125 | /// imm only: `op imm`. |
|
| 130 | - | unsafe fn fmtImm(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], imm: i32) { |
|
| 126 | + | fn fmtImm(out: &mut opaque sexpr::Output, m: *[u8], imm: i32) { |
|
| 131 | 127 | writeMnem(out, m); |
|
| 132 | - | write(out, formatI32(a, imm)); |
|
| 128 | + | writeI32(out, imm); |
|
| 133 | 129 | } |
|
| 134 | 130 | ||
| 135 | 131 | /// 1-reg: `op rs`. |
|
| 136 | 132 | fn fmt1R(out: &mut opaque sexpr::Output, m: *[u8], rs: gen::Reg) { |
|
| 137 | 133 | writeMnem(out, m); |
|
| 138 | 134 | write(out, regNameR(rs)); |
|
| 139 | 135 | } |
|
| 140 | 136 | ||
| 141 | 137 | /// Load: `op rd, imm(rs1)`. |
|
| 142 | - | unsafe fn fmtLoad(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], rd: gen::Reg, rs1: gen::Reg, imm: i32) { |
|
| 138 | + | fn fmtLoad(out: &mut opaque sexpr::Output, m: *[u8], rd: gen::Reg, rs1: gen::Reg, imm: i32) { |
|
| 143 | 139 | writeMnem(out, m); |
|
| 144 | - | writeDelim(out, &[regNameR(rd), formatI32(a, imm)]); |
|
| 140 | + | write(out, regNameR(rd)); |
|
| 141 | + | write(out, ", "); |
|
| 142 | + | writeI32(out, imm); |
|
| 145 | 143 | writeParens(out, regNameR(rs1)); |
|
| 146 | 144 | } |
|
| 147 | 145 | ||
| 148 | 146 | /// Store: `op rs2, imm(rs1)`. |
|
| 149 | - | unsafe fn fmtStore(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], rs2: gen::Reg, rs1: gen::Reg, imm: i32) { |
|
| 147 | + | fn fmtStore(out: &mut opaque sexpr::Output, m: *[u8], rs2: gen::Reg, rs1: gen::Reg, imm: i32) { |
|
| 150 | 148 | writeMnem(out, m); |
|
| 151 | - | writeDelim(out, &[regNameR(rs2), formatI32(a, imm)]); |
|
| 149 | + | write(out, regNameR(rs2)); |
|
| 150 | + | write(out, ", "); |
|
| 151 | + | writeI32(out, imm); |
|
| 152 | 152 | writeParens(out, regNameR(rs1)); |
|
| 153 | 153 | } |
|
| 154 | 154 | ||
| 155 | 155 | /// Branch: `op rs1, rs2, imm`. |
|
| 156 | - | unsafe fn fmtB(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], rs1: gen::Reg, rs2: gen::Reg, imm: i32) { |
|
| 156 | + | fn fmtB(out: &mut opaque sexpr::Output, m: *[u8], rs1: gen::Reg, rs2: gen::Reg, imm: i32) { |
|
| 157 | 157 | writeMnem(out, m); |
|
| 158 | - | writeDelim(out, &[regNameR(rs1), regNameR(rs2), formatI32(a, imm)]); |
|
| 158 | + | writeDelim(out, &[regNameR(rs1), regNameR(rs2)]); |
|
| 159 | + | write(out, ", "); |
|
| 160 | + | writeI32(out, imm); |
|
| 159 | 161 | } |
|
| 160 | 162 | ||
| 161 | 163 | /// Branch zero: `op rs1, imm`. |
|
| 162 | - | unsafe fn fmtBz(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, m: *[u8], rs1: gen::Reg, imm: i32) { |
|
| 164 | + | fn fmtBz(out: &mut opaque sexpr::Output, m: *[u8], rs1: gen::Reg, imm: i32) { |
|
| 163 | 165 | writeMnem(out, m); |
|
| 164 | - | writeDelim(out, &[regNameR(rs1), formatI32(a, imm)]); |
|
| 166 | + | write(out, regNameR(rs1)); |
|
| 167 | + | write(out, ", "); |
|
| 168 | + | writeI32(out, imm); |
|
| 165 | 169 | } |
|
| 166 | 170 | ||
| 167 | 171 | /// Print a single instruction to output buffer. |
|
| 168 | - | export unsafe fn printInstr(out: &mut opaque sexpr::Output, a: &mut alloc::Arena, instr: u32) { |
|
| 172 | + | export fn printInstr(out: &mut opaque sexpr::Output, instr: u32) { |
|
| 169 | 173 | let decoded = decode::decode(instr); |
|
| 170 | 174 | ||
| 171 | 175 | match decoded { |
|
| 172 | - | case decode::Instr::Lui { rd, imm } => fmtRI(out, a, "lui", rd, imm), |
|
| 173 | - | case decode::Instr::Auipc { rd, imm } => fmtRI(out, a, "auipc", rd, imm), |
|
| 176 | + | case decode::Instr::Lui { rd, imm } => fmtRI(out, "lui", rd, imm), |
|
| 177 | + | case decode::Instr::Auipc { rd, imm } => fmtRI(out, "auipc", rd, imm), |
|
| 174 | 178 | case decode::Instr::Jal { rd, imm } => { |
|
| 175 | 179 | if *rd == 0 { |
|
| 176 | - | fmtImm(out, a, "j", imm); |
|
| 180 | + | fmtImm(out, "j", imm); |
|
| 177 | 181 | } else { |
|
| 178 | - | fmtRI(out, a, "jal", rd, imm); |
|
| 182 | + | fmtRI(out, "jal", rd, imm); |
|
| 179 | 183 | } |
|
| 180 | 184 | }, |
|
| 181 | 185 | case decode::Instr::Jalr { rd, rs1, imm } => { |
|
| 182 | 186 | if *rd == 0 and *rs1 == 1 and imm == 0 { |
|
| 183 | 187 | write(out, "ret"); |
|
| 184 | 188 | } else if *rd == 0 and imm == 0 { |
|
| 185 | 189 | fmt1R(out, "jr", rs1); |
|
| 186 | 190 | } else { |
|
| 187 | - | fmtI(out, a, "jalr", rd, rs1, imm); |
|
| 191 | + | fmtI(out, "jalr", rd, rs1, imm); |
|
| 188 | 192 | } |
|
| 189 | 193 | }, |
|
| 190 | 194 | case decode::Instr::Beq { rs1, rs2, imm } => { |
|
| 191 | 195 | if *rs2 == 0 { |
|
| 192 | - | fmtBz(out, a, "beqz", rs1, imm); |
|
| 196 | + | fmtBz(out, "beqz", rs1, imm); |
|
| 193 | 197 | } else { |
|
| 194 | - | fmtB(out, a, "beq", rs1, rs2, imm); |
|
| 198 | + | fmtB(out, "beq", rs1, rs2, imm); |
|
| 195 | 199 | } |
|
| 196 | 200 | }, |
|
| 197 | 201 | case decode::Instr::Bne { rs1, rs2, imm } => { |
|
| 198 | 202 | if *rs2 == 0 { |
|
| 199 | - | fmtBz(out, a, "bnez", rs1, imm); |
|
| 203 | + | fmtBz(out, "bnez", rs1, imm); |
|
| 200 | 204 | } else { |
|
| 201 | - | fmtB(out, a, "bne", rs1, rs2, imm); |
|
| 205 | + | fmtB(out, "bne", rs1, rs2, imm); |
|
| 202 | 206 | } |
|
| 203 | 207 | }, |
|
| 204 | - | case decode::Instr::Blt { rs1, rs2, imm } => fmtB(out, a, "blt", rs1, rs2, imm), |
|
| 205 | - | case decode::Instr::Bge { rs1, rs2, imm } => fmtB(out, a, "bge", rs1, rs2, imm), |
|
| 206 | - | case decode::Instr::Bltu { rs1, rs2, imm } => fmtB(out, a, "bltu", rs1, rs2, imm), |
|
| 207 | - | case decode::Instr::Bgeu { rs1, rs2, imm } => fmtB(out, a, "bgeu", rs1, rs2, imm), |
|
| 208 | - | case decode::Instr::Lb { rd, rs1, imm } => fmtLoad(out, a, "lb", rd, rs1, imm), |
|
| 209 | - | case decode::Instr::Lh { rd, rs1, imm } => fmtLoad(out, a, "lh", rd, rs1, imm), |
|
| 210 | - | case decode::Instr::Lw { rd, rs1, imm } => fmtLoad(out, a, "lw", rd, rs1, imm), |
|
| 211 | - | case decode::Instr::Ld { rd, rs1, imm } => fmtLoad(out, a, "ld", rd, rs1, imm), |
|
| 212 | - | case decode::Instr::Lbu { rd, rs1, imm } => fmtLoad(out, a, "lbu", rd, rs1, imm), |
|
| 213 | - | case decode::Instr::Lhu { rd, rs1, imm } => fmtLoad(out, a, "lhu", rd, rs1, imm), |
|
| 214 | - | case decode::Instr::Lwu { rd, rs1, imm } => fmtLoad(out, a, "lwu", rd, rs1, imm), |
|
| 215 | - | case decode::Instr::Sb { rs2, rs1, imm } => fmtStore(out, a, "sb", rs2, rs1, imm), |
|
| 216 | - | case decode::Instr::Sh { rs2, rs1, imm } => fmtStore(out, a, "sh", rs2, rs1, imm), |
|
| 217 | - | case decode::Instr::Sw { rs2, rs1, imm } => fmtStore(out, a, "sw", rs2, rs1, imm), |
|
| 218 | - | case decode::Instr::Sd { rs2, rs1, imm } => fmtStore(out, a, "sd", rs2, rs1, imm), |
|
| 208 | + | case decode::Instr::Blt { rs1, rs2, imm } => fmtB(out, "blt", rs1, rs2, imm), |
|
| 209 | + | case decode::Instr::Bge { rs1, rs2, imm } => fmtB(out, "bge", rs1, rs2, imm), |
|
| 210 | + | case decode::Instr::Bltu { rs1, rs2, imm } => fmtB(out, "bltu", rs1, rs2, imm), |
|
| 211 | + | case decode::Instr::Bgeu { rs1, rs2, imm } => fmtB(out, "bgeu", rs1, rs2, imm), |
|
| 212 | + | case decode::Instr::Lb { rd, rs1, imm } => fmtLoad(out, "lb", rd, rs1, imm), |
|
| 213 | + | case decode::Instr::Lh { rd, rs1, imm } => fmtLoad(out, "lh", rd, rs1, imm), |
|
| 214 | + | case decode::Instr::Lw { rd, rs1, imm } => fmtLoad(out, "lw", rd, rs1, imm), |
|
| 215 | + | case decode::Instr::Ld { rd, rs1, imm } => fmtLoad(out, "ld", rd, rs1, imm), |
|
| 216 | + | case decode::Instr::Lbu { rd, rs1, imm } => fmtLoad(out, "lbu", rd, rs1, imm), |
|
| 217 | + | case decode::Instr::Lhu { rd, rs1, imm } => fmtLoad(out, "lhu", rd, rs1, imm), |
|
| 218 | + | case decode::Instr::Lwu { rd, rs1, imm } => fmtLoad(out, "lwu", rd, rs1, imm), |
|
| 219 | + | case decode::Instr::Sb { rs2, rs1, imm } => fmtStore(out, "sb", rs2, rs1, imm), |
|
| 220 | + | case decode::Instr::Sh { rs2, rs1, imm } => fmtStore(out, "sh", rs2, rs1, imm), |
|
| 221 | + | case decode::Instr::Sw { rs2, rs1, imm } => fmtStore(out, "sw", rs2, rs1, imm), |
|
| 222 | + | case decode::Instr::Sd { rs2, rs1, imm } => fmtStore(out, "sd", rs2, rs1, imm), |
|
| 219 | 223 | case decode::Instr::Addi { rd, rs1, imm } => { |
|
| 220 | 224 | if *rd == 0 and *rs1 == 0 and imm == 0 { |
|
| 221 | 225 | write(out, "nop"); |
|
| 222 | 226 | } else if imm == 0 { |
|
| 223 | 227 | fmt2R(out, "mv", rd, rs1); |
|
| 224 | 228 | } else if *rs1 == 0 { |
|
| 225 | - | fmtRI(out, a, "li", rd, imm); |
|
| 229 | + | fmtRI(out, "li", rd, imm); |
|
| 226 | 230 | } else { |
|
| 227 | - | fmtI(out, a, "addi", rd, rs1, imm); |
|
| 231 | + | fmtI(out, "addi", rd, rs1, imm); |
|
| 228 | 232 | } |
|
| 229 | 233 | }, |
|
| 230 | - | case decode::Instr::Slti { rd, rs1, imm } => fmtI(out, a, "slti", rd, rs1, imm), |
|
| 234 | + | case decode::Instr::Slti { rd, rs1, imm } => fmtI(out, "slti", rd, rs1, imm), |
|
| 231 | 235 | case decode::Instr::Sltiu { rd, rs1, imm } => { |
|
| 232 | 236 | if imm == 1 { |
|
| 233 | 237 | fmt2R(out, "seqz", rd, rs1); |
|
| 234 | 238 | } else { |
|
| 235 | - | fmtI(out, a, "sltiu", rd, rs1, imm); |
|
| 239 | + | fmtI(out, "sltiu", rd, rs1, imm); |
|
| 236 | 240 | } |
|
| 237 | 241 | }, |
|
| 238 | 242 | case decode::Instr::Xori { rd, rs1, imm } => { |
|
| 239 | 243 | if imm == -1 { |
|
| 240 | 244 | fmt2R(out, "not", rd, rs1); |
|
| 241 | 245 | } else { |
|
| 242 | - | fmtI(out, a, "xori", rd, rs1, imm); |
|
| 246 | + | fmtI(out, "xori", rd, rs1, imm); |
|
| 243 | 247 | } |
|
| 244 | 248 | }, |
|
| 245 | - | case decode::Instr::Ori { rd, rs1, imm } => fmtI(out, a, "ori", rd, rs1, imm), |
|
| 246 | - | case decode::Instr::Andi { rd, rs1, imm } => fmtI(out, a, "andi", rd, rs1, imm), |
|
| 247 | - | case decode::Instr::Slli { rd, rs1, shamt } => fmtI(out, a, "slli", rd, rs1, shamt), |
|
| 248 | - | case decode::Instr::Srli { rd, rs1, shamt } => fmtI(out, a, "srli", rd, rs1, shamt), |
|
| 249 | - | case decode::Instr::Srai { rd, rs1, shamt } => fmtI(out, a, "srai", rd, rs1, shamt), |
|
| 249 | + | case decode::Instr::Ori { rd, rs1, imm } => fmtI(out, "ori", rd, rs1, imm), |
|
| 250 | + | case decode::Instr::Andi { rd, rs1, imm } => fmtI(out, "andi", rd, rs1, imm), |
|
| 251 | + | case decode::Instr::Slli { rd, rs1, shamt } => fmtI(out, "slli", rd, rs1, shamt), |
|
| 252 | + | case decode::Instr::Srli { rd, rs1, shamt } => fmtI(out, "srli", rd, rs1, shamt), |
|
| 253 | + | case decode::Instr::Srai { rd, rs1, shamt } => fmtI(out, "srai", rd, rs1, shamt), |
|
| 250 | 254 | case decode::Instr::Add { rd, rs1, rs2 } => fmtR(out, "add", rd, rs1, rs2), |
|
| 251 | 255 | case decode::Instr::Sub { rd, rs1, rs2 } => { |
|
| 252 | 256 | if *rs1 == 0 { |
|
| 253 | 257 | fmt2R(out, "neg", rd, rs2); |
|
| 254 | 258 | } else { |
| 279 | 283 | case decode::Instr::Remu { rd, rs1, rs2 } => fmtR(out, "remu", rd, rs1, rs2), |
|
| 280 | 284 | case decode::Instr::Addiw { rd, rs1, imm } => { |
|
| 281 | 285 | if imm == 0 { |
|
| 282 | 286 | fmt2R(out, "sext.w", rd, rs1); |
|
| 283 | 287 | } else { |
|
| 284 | - | fmtI(out, a, "addiw", rd, rs1, imm); |
|
| 288 | + | fmtI(out, "addiw", rd, rs1, imm); |
|
| 285 | 289 | } |
|
| 286 | 290 | }, |
|
| 287 | - | case decode::Instr::Slliw { rd, rs1, shamt } => fmtI(out, a, "slliw", rd, rs1, shamt), |
|
| 288 | - | case decode::Instr::Srliw { rd, rs1, shamt } => fmtI(out, a, "srliw", rd, rs1, shamt), |
|
| 289 | - | case decode::Instr::Sraiw { rd, rs1, shamt } => fmtI(out, a, "sraiw", rd, rs1, shamt), |
|
| 291 | + | case decode::Instr::Slliw { rd, rs1, shamt } => fmtI(out, "slliw", rd, rs1, shamt), |
|
| 292 | + | case decode::Instr::Srliw { rd, rs1, shamt } => fmtI(out, "srliw", rd, rs1, shamt), |
|
| 293 | + | case decode::Instr::Sraiw { rd, rs1, shamt } => fmtI(out, "sraiw", rd, rs1, shamt), |
|
| 290 | 294 | case decode::Instr::Addw { rd, rs1, rs2 } => fmtR(out, "addw", rd, rs1, rs2), |
|
| 291 | 295 | case decode::Instr::Subw { rd, rs1, rs2 } => fmtR(out, "subw", rd, rs1, rs2), |
|
| 292 | 296 | case decode::Instr::Sllw { rd, rs1, rs2 } => fmtR(out, "sllw", rd, rs1, rs2), |
|
| 293 | 297 | case decode::Instr::Srlw { rd, rs1, rs2 } => fmtR(out, "srlw", rd, rs1, rs2), |
|
| 294 | 298 | case decode::Instr::Sraw { rd, rs1, rs2 } => fmtR(out, "sraw", rd, rs1, rs2), |
| 319 | 323 | case decode::Instr::FenceI => write(out, "fence.i"), |
|
| 320 | 324 | case decode::Instr::Ecall => write(out, "ecall"), |
|
| 321 | 325 | case decode::Instr::Ebreak => write(out, "ebreak"), |
|
| 322 | 326 | case decode::Instr::Unknown { bits } => { |
|
| 323 | 327 | write(out, "unknown"); |
|
| 324 | - | writeParens(out, formatU32(a, bits)); |
|
| 328 | + | write(out, "("); |
|
| 329 | + | writeU32(out, bits); |
|
| 330 | + | write(out, ")"); |
|
| 325 | 331 | }, |
|
| 326 | 332 | } |
|
| 327 | 333 | } |
|
| 328 | 334 | ||
| 329 | 335 | /// Print code with labels to the given output. |
|
| 330 | - | export unsafe fn printCodeTo(out: &mut opaque sexpr::Output, pkgName: *[u8], code: *[u32], funcs: *[types::FuncAddr], arena: &mut alloc::Arena) { |
|
| 336 | + | export fn printCodeTo(out: &mut opaque sexpr::Output, pkgName: *[u8], code: *[u32], funcs: *[types::FuncAddr]) { |
|
| 331 | 337 | // Package header. |
|
| 332 | 338 | write(out, "# package `"); |
|
| 333 | 339 | write(out, pkgName); |
|
| 334 | 340 | write(out, "`\n\n"); |
|
| 335 | 341 |
| 337 | 343 | if let name = findFunc(funcs, i) { |
|
| 338 | 344 | write(out, "\n# "); |
|
| 339 | 345 | write(out, name); |
|
| 340 | 346 | write(out, "\n\n"); |
|
| 341 | 347 | } |
|
| 342 | - | printInstr(out, arena, instr); |
|
| 348 | + | printInstr(out, instr); |
|
| 343 | 349 | write(out, "\n"); |
|
| 344 | 350 | } |
|
| 345 | 351 | } |
|
| 346 | 352 | ||
| 347 | 353 | /// Find function at given instruction index. |