code wiki / _hdl_build / nx_rv64_asm.nx

nx_rv64_asm.nx source

↩ module page · 179 lines · 17509 B

1// nx_rv64_asm.nx -- SOVEREIGN RV64 BARE-METAL TEXT-ASSEMBLER. Two-pass (collect labels -> encode with resolved 2// branch/jump offsets) assembler emitting a FLAT binary whose entry is at offset 0 (loads at 0x80000000 via QEMU 3// `-bios`, no syscall trampoline; a guest halts via the SiFive test finisher). Reuses the RV64 format encoders proven 4// in nx_rv64_runproof_gate + adds U-type (lui) + B-type (branches). This is the tool for writing REAL device drivers 5// that boot in qemu-system-riscv64 -- readable .s text, correct bytes. license_tier: ORIGINAL 6// API: rvasm_assemble(src: *u8, n: i64, out: *u8, cap: i64) -> nbytes (or negative on error) 7// Supported: lui li addi add sub and or xor sll srl slli srli andi ori lw lbu lhu ld sw sb sh sd 8// beq bne blt bge bltu bgeu jal j mv ret nop ecall (branch/jal targets are LABELS) 9import "nx_syscalls.nx" 10const RA_MAGIC_2047: i64 = 2047 11const RA_MAGIC_2048: i64 = 2048 12 13func ra_isws(c: i64) -> i64 { if c==32 { return 1 } if c==9 { return 1 } if c==13 { return 1 } if c==10 { return 1 } return 0 } 14func ra_isdig(c: i64) -> i64 { if c>=48 { if c<=57 { return 1 } } return 0 } 15func ra_ishex(c: i64) -> i64 { if ra_isdig(c)==1 { return 1 } if c>=97 { if c<=102 { return 1 } } if c>=65 { if c<=70 { return 1 } } return 0 } 16func ra_hexval(c: i64) -> i64 { if c>=48 { if c<=57 { return c-48 } } if c>=97 { if c<=102 { return c-87 } } if c>=65 { if c<=70 { return c-55 } } return 0 } 17 18// ---- RV64 format encoders (R/I/S from the proven runproof gate; U/B added) ---- 19func ra_r(op: i64, f3: i64, f7: i64, rd: i64, rs1: i64, rs2: i64) -> i64 { return (f7<<25)|((rs2&0x1F)<<20)|((rs1&0x1F)<<15)|(f3<<12)|((rd&0x1F)<<7)|op } 20func ra_i(op: i64, f3: i64, rd: i64, rs1: i64, imm: i64) -> i64 { return ((imm&0xFFF)<<20)|((rs1&0x1F)<<15)|(f3<<12)|((rd&0x1F)<<7)|op } 21func ra_s(op: i64, f3: i64, rs1: i64, rs2: i64, imm: i64) -> i64 { return (((imm>>5)&0x7F)<<25)|((rs2&0x1F)<<20)|((rs1&0x1F)<<15)|(f3<<12)|((imm&0x1F)<<7)|op } 22func ra_u(op: i64, rd: i64, imm: i64) -> i64 { return ((imm&0xFFFFF)<<12)|((rd&0x1F)<<7)|op } 23func ra_b(f3: i64, rs1: i64, rs2: i64, imm: i64) -> i64 { return (((imm>>12)&1)<<31)|(((imm>>5)&0x3F)<<25)|((rs2&0x1F)<<20)|((rs1&0x1F)<<15)|((f3&7)<<12)|(((imm>>1)&0xF)<<8)|(((imm>>11)&1)<<7)|0x63 } 24func ra_j(rd: i64, imm: i64) -> i64 { return 0x6F|((rd&0x1F)<<7)|(((imm>>12)&0xFF)<<12)|(((imm>>11)&0x1)<<20)|(((imm>>1)&0x3FF)<<21)|(((imm>>20)&0x1)<<31) } 25func ra_put(out: *u8, o: i64, w: i64) -> i64 { out[o]=(w&0xff) as u8; out[o+1]=((w>>8)&0xff) as u8; out[o+2]=((w>>16)&0xff) as u8; out[o+3]=((w>>24)&0xff) as u8; return o+4 } 26// FAIL-LOUD guard: a 12-bit signed immediate (li/addi/andi/ori) must fit [-2048,2047] or the assembler REFUSES 27// (returns 1=ok / 0=out-of-range). This is the durable fix for the "li reg, 4096 silently truncates to 0" bug -- 28// a too-big immediate now fails the assemble instead of emitting wrong code (use lui for values >= 4096). 29func ra_imm12(im: i64) -> i64 { if im > RA_MAGIC_2047 { return 0 } if im < (0 - RA_MAGIC_2048) { return 0 } return 1 } 30// shift amounts (slli/srli) must fit [0,63] on RV64. 31func ra_sh6(im: i64) -> i64 { if im < 0 { return 0 } if im > 63 { return 0 } return 1 } 32 33// ---- cursor parsing ---- 34func ra_skipsep(s: *u8, cur: *i64) -> i64 { var p: i64=cur[0]; var go: i64=1; while go==1 { let c: i64=s[p] as i64; if c==44 { p=p+1 } else { if ra_isws(c)==1 { p=p+1 } else { go=0 } } } cur[0]=p; return p } 35func ra_num(s: *u8, cur: *i64) -> i64 { var p: i64=cur[0]; var v: i64=0; while ra_isdig(s[p] as i64)==1 { v=v*10+((s[p] as i64)-48); p=p+1 } cur[0]=p; return v } 36func ra_imm(s: *u8, cur: *i64) -> i64 { 37 ra_skipsep(s,cur); var p: i64=cur[0]; var neg: i64=0 38 if (s[p] as i64)==45 { neg=1; p=p+1 } 39 var v: i64=0 40 if (s[p] as i64)==48 { if (s[p+1] as i64)==120 { p=p+2; while ra_ishex(s[p] as i64)==1 { v=v*16+ra_hexval(s[p] as i64); p=p+1 } cur[0]=p; if neg==1 { return 0-v } return v } } 41 while ra_isdig(s[p] as i64)==1 { v=v*10+((s[p] as i64)-48); p=p+1 } 42 cur[0]=p; if neg==1 { return 0-v } return v 43} 44func ra_past(s: *u8, cur: *i64, ch: i64) -> i64 { var p: i64=cur[0]; var go: i64=1; while go==1 { let c: i64=s[p] as i64; if c==0 { go=0 } else { if c==ch { p=p+1; go=0 } else { p=p+1 } } } cur[0]=p; return p } 45// ABI register name -> number 46func ra_reg(s: *u8, cur: *i64) -> i64 { 47 ra_skipsep(s,cur); var p: i64=cur[0] 48 let c0: i64=s[p] as i64; let c1: i64=s[p+1] as i64 49 if c0==115 { if c1==112 { cur[0]=p+2; return 2 } } // sp 50 if c0==114 { if c1==97 { cur[0]=p+2; return 1 } } // ra 51 if c0==122 { cur[0]=p+4; return 0 } // zero 52 if c0==102 { if c1==112 { cur[0]=p+2; return 8 } } // fp 53 cur[0]=p+1 54 let n: i64=ra_num(s,cur) 55 if c0==97 { return 10+n } // aN 56 if c0==116 { if n<=2 { return 5+n } return 25+n } // tN 57 if c0==115 { if n==0 { return 8 } if n==1 { return 9 } return 16+n } // sN 58 return 0 59} 60func ra_word_is(s: *u8, p: i64, lit: *u8) -> i64 { var i: i64=0; while (lit[i] as i64)!=0 { if (s[p+i] as i64)!=(lit[i] as i64) { return 0 } i=i+1 } let nc: i64=s[p+i] as i64; if ra_isws(nc)==1 { return 1 } if nc==0 { return 1 } return 0 } 61func ra_afterword(s: *u8, p: i64) -> i64 { var q: i64=p; var go: i64=1; while go==1 { let c: i64=s[q] as i64; if c==0 { go=0 } else { if ra_isws(c)==1 { go=0 } else { q=q+1 } } } return q } 62 63// label table (module-shared via params) 64func ra_find_label(s: *u8, ts: i64, tlen: i64, lst: *i64, lln: *i64, lab: *i64, nl: i64) -> i64 { 65 var j: i64=0 66 while j<nl { if lln[j]==tlen { var k: i64=0; var eq: i64=1; while k<tlen { if (s[ts+k] as i64)!=(s[(lst[j])+k] as i64) { eq=0; k=tlen } else { k=k+1 } } if eq==1 { return lab[j] } } j=j+1 } 67 return 0-1 68} 69// parse a label operand (name) at cur -> its address (or -1) 70func ra_label_target(s: *u8, cur: *i64, lst: *i64, lln: *i64, lab: *i64, nl: i64) -> i64 { 71 ra_skipsep(s,cur); let ts: i64=cur[0]; let te: i64=ra_afterword(s,ts); cur[0]=te 72 return ra_find_label(s, ts, te-ts, lst, lln, lab, nl) 73} 74 75// encode ONE instruction at line-offset fp, whose address is `abs`. returns the 32-bit word or -1. 76func ra_encode(s: *u8, fp: i64, abs: i64, lst: *i64, lln: *i64, lab: *i64, nl: i64) -> i64 { 77 let cur: *i64=sys_mmap(8) as *i64; cur[0]=ra_afterword(s,fp) 78 if ra_word_is(s,fp,"lui" as *u8)==1 { let d: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); return ra_u(0x37,d,im) } 79 if ra_word_is(s,fp,"li" as *u8)==1 { let d: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_imm12(im)==0 { return 0-1 } return ra_i(0x13,0,d,0,im) } 80 if ra_word_is(s,fp,"addi" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_imm12(im)==0 { return 0-1 } return ra_i(0x13,0,d,a,im) } 81 if ra_word_is(s,fp,"andi" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_imm12(im)==0 { return 0-1 } return ra_i(0x13,7,d,a,im) } 82 if ra_word_is(s,fp,"ori" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_imm12(im)==0 { return 0-1 } return ra_i(0x13,6,d,a,im) } 83 if ra_word_is(s,fp,"slli" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_sh6(im)==0 { return 0-1 } return ra_i(0x13,1,d,a,im) } 84 if ra_word_is(s,fp,"srli" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_sh6(im)==0 { return 0-1 } return ra_i(0x13,5,d,a,im) } 85 if ra_word_is(s,fp,"add" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,0,0,d,a,b) } 86 if ra_word_is(s,fp,"sub" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,0,0x20,d,a,b) } 87 if ra_word_is(s,fp,"and" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,7,0,d,a,b) } 88 if ra_word_is(s,fp,"or" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,6,0,d,a,b) } 89 if ra_word_is(s,fp,"xor" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,4,0,d,a,b) } 90 if ra_word_is(s,fp,"sll" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,1,0,d,a,b) } 91 if ra_word_is(s,fp,"srl" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,5,0,d,a,b) } 92 // M extension (funct7=0x01): the assembler now emits everything the emulator executes (ISA-consistent toolchain). 93 if ra_word_is(s,fp,"mulhu" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,3,0x01,d,a,b) } 94 if ra_word_is(s,fp,"mulhsu" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,2,0x01,d,a,b) } 95 if ra_word_is(s,fp,"mulh" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,1,0x01,d,a,b) } 96 if ra_word_is(s,fp,"mul" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,0,0x01,d,a,b) } 97 if ra_word_is(s,fp,"divu" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,5,0x01,d,a,b) } 98 if ra_word_is(s,fp,"div" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,4,0x01,d,a,b) } 99 if ra_word_is(s,fp,"remu" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,7,0x01,d,a,b) } 100 if ra_word_is(s,fp,"rem" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x33,6,0x01,d,a,b) } 101 // *W (32-bit word) ops -- OP-32 (0x3B) register + OP-IMM-32 (0x1B) immediate. ISA-consistent: fk/JIT execute these. 102 if ra_word_is(s,fp,"addiw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); if ra_imm12(im)==0 { return 0-1 } return ra_i(0x1B,0,d,a,im) } 103 if ra_word_is(s,fp,"slliw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); return ra_i(0x1B,1,d,a,im) } 104 if ra_word_is(s,fp,"srliw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); return ra_i(0x1B,5,d,a,im) } 105 if ra_word_is(s,fp,"sraiw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); return ra_i(0x1B,5,d,a,0x400|im) } 106 if ra_word_is(s,fp,"addw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,0,0,d,a,b) } 107 if ra_word_is(s,fp,"subw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,0,0x20,d,a,b) } 108 if ra_word_is(s,fp,"sllw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,1,0,d,a,b) } 109 if ra_word_is(s,fp,"srlw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,5,0,d,a,b) } 110 if ra_word_is(s,fp,"sraw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,5,0x20,d,a,b) } 111 if ra_word_is(s,fp,"mulw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,0,0x01,d,a,b) } 112 if ra_word_is(s,fp,"divuw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,5,0x01,d,a,b) } 113 if ra_word_is(s,fp,"divw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,4,0x01,d,a,b) } 114 if ra_word_is(s,fp,"remuw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,7,0x01,d,a,b) } 115 if ra_word_is(s,fp,"remw" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); return ra_r(0x3B,6,0x01,d,a,b) } 116 if ra_word_is(s,fp,"lw" as *u8)==1 { let d: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_i(0x03,2,d,a,im) } 117 if ra_word_is(s,fp,"lbu" as *u8)==1 { let d: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_i(0x03,4,d,a,im) } 118 if ra_word_is(s,fp,"lhu" as *u8)==1 { let d: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_i(0x03,5,d,a,im) } 119 if ra_word_is(s,fp,"ld" as *u8)==1 { let d: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_i(0x03,3,d,a,im) } 120 if ra_word_is(s,fp,"sw" as *u8)==1 { let v: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_s(0x23,2,a,v,im) } 121 if ra_word_is(s,fp,"sb" as *u8)==1 { let v: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_s(0x23,0,a,v,im) } 122 if ra_word_is(s,fp,"sh" as *u8)==1 { let v: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_s(0x23,1,a,v,im) } 123 if ra_word_is(s,fp,"sd" as *u8)==1 { let v: i64=ra_reg(s,cur); let im: i64=ra_imm(s,cur); ra_past(s,cur,40); let a: i64=ra_reg(s,cur); return ra_s(0x23,3,a,v,im) } 124 if ra_word_is(s,fp,"beq" as *u8)==1 { let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_b(0,a,b,t-abs) } 125 if ra_word_is(s,fp,"bne" as *u8)==1 { let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_b(1,a,b,t-abs) } 126 if ra_word_is(s,fp,"blt" as *u8)==1 { let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_b(4,a,b,t-abs) } 127 if ra_word_is(s,fp,"bge" as *u8)==1 { let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_b(5,a,b,t-abs) } 128 if ra_word_is(s,fp,"bltu" as *u8)==1 { let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_b(6,a,b,t-abs) } 129 if ra_word_is(s,fp,"bgeu" as *u8)==1 { let a: i64=ra_reg(s,cur); let b: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_b(7,a,b,t-abs) } 130 if ra_word_is(s,fp,"jal" as *u8)==1 { let d: i64=ra_reg(s,cur); let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_j(d,t-abs) } 131 if ra_word_is(s,fp,"j" as *u8)==1 { let t: i64=ra_label_target(s,cur,lst,lln,lab,nl); return ra_j(0,t-abs) } 132 if ra_word_is(s,fp,"mv" as *u8)==1 { let d: i64=ra_reg(s,cur); let a: i64=ra_reg(s,cur); return ra_i(0x13,0,d,a,0) } 133 if ra_word_is(s,fp,"ret" as *u8)==1 { return ra_i(0x67,0,0,1,0) } 134 if ra_word_is(s,fp,"nop" as *u8)==1 { return ra_i(0x13,0,0,0,0) } 135 if ra_word_is(s,fp,"ecall" as *u8)==1 { return ra_i(0x73,0,0,0,0) } 136 return 0-1 137} 138 139const RA_MAXSYM: i64 = 256 140// assemble src -> flat binary in out. returns byte length, or negative on error. 141func rvasm_assemble(s: *u8, n: i64, out: *u8, cap: i64) -> i64 { 142 let lst: *i64=sys_mmap(8*RA_MAXSYM) as *i64; let lln: *i64=sys_mmap(8*RA_MAXSYM) as *i64; let lab: *i64=sys_mmap(8*RA_MAXSYM) as *i64 143 var nl: i64=0 144 // ---- pass 1: collect labels ---- 145 var pos: i64=0; var abs: i64=0 146 while pos<n { 147 var le: i64=pos; var f1: i64=1; while f1==1 { if le>=n { f1=0 } else { if (s[le] as i64)==10 { f1=0 } else { le=le+1 } } } 148 var fp: i64=pos; var f2: i64=1; while f2==1 { if fp>=le { f2=0 } else { if ra_isws(s[fp] as i64)==1 { fp=fp+1 } else { f2=0 } } } 149 if fp<le { let c0: i64=s[fp] as i64 150 if c0==35 { } else { if c0==46 { } else { 151 var q: i64=le-1; var f3: i64=1; while f3==1 { if q<fp { f3=0 } else { if ra_isws(s[q] as i64)==1 { q=q-1 } else { f3=0 } } } 152 if (s[q] as i64)==58 { if nl<RA_MAXSYM { lst[nl]=fp; lln[nl]=q-fp; lab[nl]=abs; nl=nl+1 } } 153 else { abs=abs+4 } 154 } } 155 } 156 pos=le+1 157 } 158 // ---- pass 2: encode ---- 159 pos=0; abs=0 160 while pos<n { 161 var le: i64=pos; var g1: i64=1; while g1==1 { if le>=n { g1=0 } else { if (s[le] as i64)==10 { g1=0 } else { le=le+1 } } } 162 var fp: i64=pos; var g2: i64=1; while g2==1 { if fp>=le { g2=0 } else { if ra_isws(s[fp] as i64)==1 { fp=fp+1 } else { g2=0 } } } 163 if fp<le { let c0: i64=s[fp] as i64 164 if c0==35 { } else { if c0==46 { } else { 165 var q: i64=le-1; var g3: i64=1; while g3==1 { if q<fp { g3=0 } else { if ra_isws(s[q] as i64)==1 { q=q-1 } else { g3=0 } } } 166 if (s[q] as i64)==58 { } else { 167 let w: i64=ra_encode(s, fp, abs, lst, lln, lab, nl) 168 if w==(0-1) { return 0-2 } 169 if abs+4>cap { return 0-3 } 170 ra_put(out, abs, w); abs=abs+4 171 } 172 } } 173 } 174 pos=le+1 175 } 176 return abs 177} 178// convenience: assemble a null-terminated source string (computes length internally). 179func rvasm_assemble_str(s: *u8, out: *u8, cap: i64) -> i64 { var n: i64=0; while (s[n] as i64)!=0 { n=n+1 } return rvasm_assemble(s, n, out, cap) }