/* * Create section mappings in the 1-1 mapping area for the largest RAM bank */ static void lpae_map_1to1_ram() { unsigned as_off = AS_NULL_OFF; paddr32_t base = 0; unsigned size = 0; uintptr_t vaddr; while ((as_off = as_find(as_off, "ram", 0)) != AS_NULL_OFF) { struct asinfo_entry *as = (struct asinfo_entry *)((uintptr_t)lsp.asinfo.p + as_off); unsigned sz = as->end - as->start + 1; if (as->start >= ARM_LPAE_4G_BOUNDARY) { // 1-to-1 has to be below 4GB; ignore this region continue; } if (sz > size) { base = (paddr32_t)as->start; size = sz; } } if (size == 0) { crash("no ram entry in asinfo?"); } if (base & ARM_LPAE_BMASK) { if (debug_flag) { kprintf("WARNING: RAM base at %x - not using 1to1 area\n", base); } return; } /* * Limit mapping to 256MB */ if (size > ARM_1TO1_SIZE) { size = ARM_1TO1_SIZE; } // With LPAE we map in block-sized chunks size = (size + ARM_LPAE_BMASK) & ~ARM_LPAE_BMASK; as_add(base, base + size - 1, AS_ATTR_RAM, "1to1", as_default()); for (vaddr = ARM_1TO1_BASE; size; vaddr += ARM_LPAE_BSIZE, base += ARM_LPAE_BSIZE, size -= ARM_LPAE_BSIZE) { arm_lpae_bmap(vaddr, base, ARM_PTE_RW | ARM_PTE_CB); // Block map } }
/* * Create section mappings in the 1-1 mapping area for the largest RAM bank */ static void map_1to1_ram() { unsigned as_off = AS_NULL_OFF; unsigned base = 0; unsigned size = 0; unsigned vaddr; while ((as_off = as_find(as_off, "ram", 0)) != AS_NULL_OFF) { struct asinfo_entry *as = (struct asinfo_entry *)((uintptr_t)lsp.asinfo.p + as_off); unsigned sz = as->end - as->start + 1; if (sz > size) { base = (unsigned)as->start; size = sz; } } if (size == 0) { crash("no ram entry in asinfo?"); } if (base & ARM_SCMASK) { if (debug_flag) { kprintf("WARNING: RAM base at %x - not using 1to1 area\n", base); } return; } /* * Limit mapping to 256MB */ if (size > ARM_1TO1_SIZE) { size = ARM_1TO1_SIZE; } size = (size + ARM_SCMASK) & ~ARM_SCMASK; as_add(base, base + size - 1, AS_ATTR_RAM, "1to1", as_default()); for (vaddr = ARM_1TO1_BASE; size; vaddr += ARM_SCSIZE, base += ARM_SCSIZE, size -= ARM_SCSIZE) { arm_scmap(vaddr, base, ARM_PTE_RW | ARM_PTE_CB); // Section map } }
void test_arithmetic_instructions() { asm_p as = &(asm_t){ 0 }; char* disassembly = NULL; as_new(as); as_clear(as); for(size_t i = 0; i < 16; i++) as_add(as, reg(i), reg(i)); for(size_t i = 0; i < 16; i++) as_add(as, reg(i), imm(0x7abbccdd)); disassembly = disassemble(as); st_check_str(disassembly, "add rax,rax\n" "add rcx,rcx\n" "add rdx,rdx\n" "add rbx,rbx\n" "add rsp,rsp\n" "add rbp,rbp\n" "add rsi,rsi\n" "add rdi,rdi\n" "add r8,r8\n" "add r9,r9\n" "add r10,r10\n" "add r11,r11\n" "add r12,r12\n" "add r13,r13\n" "add r14,r14\n" "add r15,r15\n" "add rax,0x7abbccdd\n" "add rcx,0x7abbccdd\n" "add rdx,0x7abbccdd\n" "add rbx,0x7abbccdd\n" "add rsp,0x7abbccdd\n" "add rbp,0x7abbccdd\n" "add rsi,0x7abbccdd\n" "add rdi,0x7abbccdd\n" "add r8,0x7abbccdd\n" "add r9,0x7abbccdd\n" "add r10,0x7abbccdd\n" "add r11,0x7abbccdd\n" "add r12,0x7abbccdd\n" "add r13,0x7abbccdd\n" "add r14,0x7abbccdd\n" "add r15,0x7abbccdd\n" ); as_clear(as); for(size_t i = 0; i < 16; i++) as_sub(as, reg(i), reg(i)); for(size_t i = 0; i < 16; i++) as_sub(as, reg(i), imm(0x7abbccdd)); disassembly = disassemble(as); st_check_str(disassembly, "sub rax,rax\n" "sub rcx,rcx\n" "sub rdx,rdx\n" "sub rbx,rbx\n" "sub rsp,rsp\n" "sub rbp,rbp\n" "sub rsi,rsi\n" "sub rdi,rdi\n" "sub r8,r8\n" "sub r9,r9\n" "sub r10,r10\n" "sub r11,r11\n" "sub r12,r12\n" "sub r13,r13\n" "sub r14,r14\n" "sub r15,r15\n" "sub rax,0x7abbccdd\n" "sub rcx,0x7abbccdd\n" "sub rdx,0x7abbccdd\n" "sub rbx,0x7abbccdd\n" "sub rsp,0x7abbccdd\n" "sub rbp,0x7abbccdd\n" "sub rsi,0x7abbccdd\n" "sub rdi,0x7abbccdd\n" "sub r8,0x7abbccdd\n" "sub r9,0x7abbccdd\n" "sub r10,0x7abbccdd\n" "sub r11,0x7abbccdd\n" "sub r12,0x7abbccdd\n" "sub r13,0x7abbccdd\n" "sub r14,0x7abbccdd\n" "sub r15,0x7abbccdd\n" ); as_clear(as); for(size_t i = 0; i < 16; i++) as_mul(as, reg(i)); for(size_t i = 0; i < 16; i++) as_mul(as, memrd(reg(i), 0xbeba)); disassembly = disassemble(as); st_check_str(disassembly, "mul rax\n" "mul rcx\n" "mul rdx\n" "mul rbx\n" "mul rsp\n" "mul rbp\n" "mul rsi\n" "mul rdi\n" "mul r8\n" "mul r9\n" "mul r10\n" "mul r11\n" "mul r12\n" "mul r13\n" "mul r14\n" "mul r15\n" "mul QWORD PTR [rax+0xbeba]\n" "mul QWORD PTR [rcx+0xbeba]\n" "mul QWORD PTR [rdx+0xbeba]\n" "mul QWORD PTR [rbx+0xbeba]\n" "mul QWORD PTR [rsp+0xbeba]\n" "mul QWORD PTR [rbp+0xbeba]\n" "mul QWORD PTR [rsi+0xbeba]\n" "mul QWORD PTR [rdi+0xbeba]\n" "mul QWORD PTR [r8+0xbeba]\n" "mul QWORD PTR [r9+0xbeba]\n" "mul QWORD PTR [r10+0xbeba]\n" "mul QWORD PTR [r11+0xbeba]\n" "mul QWORD PTR [r12+0xbeba]\n" "mul QWORD PTR [r13+0xbeba]\n" "mul QWORD PTR [r14+0xbeba]\n" "mul QWORD PTR [r15+0xbeba]\n" ); as_clear(as); for(size_t i = 0; i < 16; i++) as_div(as, reg(i)); for(size_t i = 0; i < 16; i++) as_div(as, memrd(reg(i), 0xbeba)); disassembly = disassemble(as); st_check_str(disassembly, "div rax\n" "div rcx\n" "div rdx\n" "div rbx\n" "div rsp\n" "div rbp\n" "div rsi\n" "div rdi\n" "div r8\n" "div r9\n" "div r10\n" "div r11\n" "div r12\n" "div r13\n" "div r14\n" "div r15\n" "div QWORD PTR [rax+0xbeba]\n" "div QWORD PTR [rcx+0xbeba]\n" "div QWORD PTR [rdx+0xbeba]\n" "div QWORD PTR [rbx+0xbeba]\n" "div QWORD PTR [rsp+0xbeba]\n" "div QWORD PTR [rbp+0xbeba]\n" "div QWORD PTR [rsi+0xbeba]\n" "div QWORD PTR [rdi+0xbeba]\n" "div QWORD PTR [r8+0xbeba]\n" "div QWORD PTR [r9+0xbeba]\n" "div QWORD PTR [r10+0xbeba]\n" "div QWORD PTR [r11+0xbeba]\n" "div QWORD PTR [r12+0xbeba]\n" "div QWORD PTR [r13+0xbeba]\n" "div QWORD PTR [r14+0xbeba]\n" "div QWORD PTR [r15+0xbeba]\n" ); free(disassembly); }
unsigned as_default() { return as_add(0, 0xffffffff, AS_ATTR_NONE, "memory", AS_NULL_OFF); }