diff --git a/core/src/riscv2zisk_context.rs b/core/src/riscv2zisk_context.rs index c25afb47e..d3cf369e9 100644 --- a/core/src/riscv2zisk_context.rs +++ b/core/src/riscv2zisk_context.rs @@ -75,6 +75,9 @@ const FLOAT_HANDLER_RETURN_ADDR: u64 = FLOAT_HANDLER_ADDR + 4 * 34; // 31 regs + /// Mask to apply to the target address of JALR instructions, to ensure the least significant bit is 0 const JALR_MASK: u64 = 0xfffffffffffffffe; +#[cfg(not(feature = "float"))] +const NO_FLOAT_ECALL_ADDR: u64 = ROM_EXIT + 0x58; + /// Context to store the list of converted ZisK instructions, including their program address and a /// map to store the instructions pub struct Riscv2ZiskContext<'a> { @@ -1261,7 +1264,15 @@ impl Riscv2ZiskContext<'_> { pub fn ecall(&mut self, i: &RiscvInstruction) { let mut zib = ZiskInstBuilder::new_from_riscv(i.rom_address, i.inst.clone()); zib.src_a("imm", 0, false); + // If the float feature is enabled, we use the MTVEC register as the address to jump to for + // the ecall. If not, we use a fixed address (NO_FLOAT_ECALL_ADDR) for the ecall. This + // allows us to handle system calls differently based on whether floating-point operations + // are supported or not. When float is disabled, this avoids the only dynamic jump to the + // lower addresses space, improving the performance of dynamic jumps in general. + #[cfg(feature = "float")] zib.src_b("mem", MTVEC, false); + #[cfg(not(feature = "float"))] + zib.src_b("imm", NO_FLOAT_ECALL_ADDR, false); zib.op("copyb").unwrap(); zib.store_pc("reg", 1, false); zib.set_pc(); @@ -2432,7 +2443,11 @@ pub fn add_entry_exit_jmp(rom: &mut ZiskRom, addr: u64) { // Calculate the trap handler rom pc address as an offset from the current instruction address // to the beginning of the ecall section + #[cfg(not(feature = "float"))] + assert!(rom.next_init_inst_addr == ROM_EXIT + 4); let trap_handler: u64 = rom.next_init_inst_addr + 0x54; + #[cfg(not(feature = "float"))] + assert!(trap_handler == NO_FLOAT_ECALL_ADDR); // :0000 we note the rom pc address offset from the first address for each instruction // Store the Zisk architecture ID into memory diff --git a/core/src/zisk_rom_2_asm.rs b/core/src/zisk_rom_2_asm.rs index 67287ea79..39f093b07 100644 --- a/core/src/zisk_rom_2_asm.rs +++ b/core/src/zisk_rom_2_asm.rs @@ -7907,8 +7907,11 @@ impl ZiskRom2Asm { high_address, ctx.comment_str("is pc a low address?") ); - *code += &format!("\tcmp {REG_PC}, {REG_ADDRESS}\n"); - *code += &format!("\tjb pc_{:x}_jump_to_low_address\n", ctx.pc); + #[cfg(feature = "float")] + { + *code += &format!("\tcmp {REG_PC}, {REG_ADDRESS}\n"); + *code += &format!("\tjb pc_{:x}_jump_to_low_address\n", ctx.pc); + } *code += &format!("\tsub {}, {} {}\n", REG_PC, REG_ADDRESS, ctx.comment_str("pc -= ROM_ADDR")); *code += &format!( @@ -7925,21 +7928,24 @@ impl ZiskRom2Asm { ctx.comment_str("address = map[pc]") ); *code += &format!("\tjmp {} {}\n", REG_ADDRESS, ctx.comment_str("jump to address")); - *code += &format!("pc_{:x}_jump_to_low_address:\n", ctx.pc); - *code += &format!("\tsub {}, 0x1000 {}\n", REG_PC, ctx.comment_str("pc -= ROM_ENTRY")); - *code += &format!( - "\tlea {}, [map_pc_1000] {}\n", - REG_ADDRESS, - ctx.comment_str("address = map[ROM_ENTRY]") - ); - *code += &format!( - "\tmov {}, [{} + {}*2] {}\n", - REG_ADDRESS, - REG_ADDRESS, - REG_PC, - ctx.comment_str("address = map[pc]") - ); - *code += &format!("\tjmp {} {}\n", REG_ADDRESS, ctx.comment_str("jump to address")); + #[cfg(feature = "float")] + { + *code += &format!("pc_{:x}_jump_to_low_address:\n", ctx.pc); + *code += &format!("\tsub {}, 0x1000 {}\n", REG_PC, ctx.comment_str("pc -= ROM_ENTRY")); + *code += &format!( + "\tlea {}, [map_pc_1000] {}\n", + REG_ADDRESS, + ctx.comment_str("address = map[ROM_ENTRY]") + ); + *code += &format!( + "\tmov {}, [{} + {}*2] {}\n", + REG_ADDRESS, + REG_ADDRESS, + REG_PC, + ctx.comment_str("address = map[pc]") + ); + *code += &format!("\tjmp {} {}\n", REG_ADDRESS, ctx.comment_str("jump to address")); + } } /*************/