Lua Programming and Jazelle: Difference between pages

From Hackspire
(Difference between pages)
Jump to navigation Jump to search
No edit summary
 
No edit summary
 
Line 1: Line 1:
The TI-Nspire allows, since OS v3.0, users to run Lua scripts.
Jazelle is a feature of the TI-Nspire's ARM926EJ-S CPU that implements a subset of the Java bytecode instruction set in hardware.  


==Prerequisites==
The ARMv6 Architecture Reference Manual (DDI 0100I) gives some information about Jazelle, intended for operating system programmers who want to be able to correctly handle exceptions that occurred while in Jazelle state, or manage the configuration registers if two Jazelle JVMs with possibly different configurations could be running. However, most of the details of how to actually write a Jazelle JVM are left "<small>SUBARCHITECTURE DEFINED</small>". These details may be elaborated in the Jazelle v1 Architecture Reference Manual (DDI 0225A), but unfortunately this document is not available to the public.


Lua is only supported starting from OS v3.0.1. You can create Lua applications using the built-in script editor in the TI-Nspire computer software or one of the following third-party tools:
==Configuration registers==


'''For any OS''':
Configuration registers may be read with the instruction <tt>MRC{<cond>} p14, 7, <Rd>, <CRn>, c0</tt>, or written with <tt>MCR{<cond>} p14, 7, <Rd>, <CRn>, c0</tt>. A list of known <tt>CRn</tt> follows:
*[https://github.com/ndless-nspire/Luna Luna] (cross-platform) [[https://www.omnimaga.org/news/'luna'-is-here-and-converts-your-lua-files-into-3-0-2-compatible-tns-files/ forum thread]]
'''For OS < 3.0.1''': these tools won't work with the OS 3.0.2 since the format used is now blocked
*[http://www.ticalc.org/archives/files/fileinfo/437/43704.html LUAtoTNS.sh] (bash script, works on Linux, Mac OS and Unix, or Windows + Cygwin or Windows + MSYS).
*[http://www.mirari.fr/KbOD maketns.py] (Python script, cross-platform)
*[https://www.omnimaga.org/files/User-Contributed-Calculator-Games-amp-Development-Tools/TI-Nspire-amp-TI-Nspire-CAS/TI-Nspire-Programming-Tools/lua2ti.zip lua2ti] (Windows + .NET Framework v4.0)
*[https://www.omnimaga.org/files/User-Contributed-Calculator-Games-amp-Development-Tools/TI-Nspire-amp-TI-Nspire-CAS/TI-Nspire-Programming-Tools/lua2ti_linux.zip lua2ti_linux] (Linux (No longer requires Mono, it is now a native Linux binary!))
You may also want to install Lua [https://www.lua.org/download.html on your computer]: <tt>luac -p</tt> can be used to check the syntax of your script before running it on a TI-Nspire or an emulator.


==API==
* c0: Jazelle Identity register (read-only)
** Bits 0-11: Subarchitecture-defined bits (reads as 4, meaning unknown)
** Bits 12-19: Subarchitecture (reads as 0, Jazelle V1 according to documentation)
** Bits 20-27: Implementor (reads as 0x41, ARM Limited according to documentation)
** Bits 28-31: Architecture (reads as 6, ARMv5TEJ according to documentation)
* c1: Operating System Control register
** Bit 0: Configuration Disabled (CD) (documented)
** Bit 1: Configuration Valid (CV) (documented)
* c2: Main Configuration register
** Bit 0: Jazelle Enable (JE) (documented)
** Bits 26-28: Unknown
** Bit 29: If set, array object contains its elements directly, otherwise it contains a pointer to its elements
** Bit 31: Disable array instructions if set?
* c3: Array object layout register
** Bits 0-7: Unknown
** Bits 8-11: Offset (in words) within array object of first element or of pointer to first element
** Bits 12-15: Offset (in words) within array object of length
** Bit 16: If set, offset to length is subtracted, otherwise added
** Bits 17-19: Array length shift value (number of elements = stored length >> this)
** Bits 20-21: Disable array instructions if set?


The documentation is now maintained in the "[http://wiki.inspired-lua.org Inspired Lua Wiki]".
==Register usage==
Please go there in order to have a full detailed documentation based on TI's information.


==XML==
* r0-r3: Holds up to 4 words of the stack
* r4: Copy of local variable 0. Only valid when local variable 0 is a single word (i.e. int, float, or Object; not long or double)
* r5:
** Bits 0-1: If any of the stack is held in registers, this specifies which of the registers in r0-r3 is currently the top of stack, otherwise this is 0
** Bits 2-4: Number of stack words held in registers
** Bit 5: Seems to get cleared upon entry to Jazelle state, unless a prefetch abort or data abort happens before any bytecode is read
** Bits 6-9: Cleared immediately upon entry to Jazelle state
** Bits 10-31: Pointer to software handler table (must be 1024-byte aligned)
* r6: Pointer to top of stack (Note that the Java stack grows '''up''', not down)
* r7: Pointer to current method's local variables
* r8: Pointer to constant pool? (haven't checked this yet)
* r9-r11: Do not appear to be used; available for the JVM's own use
* r12: Temporary
* sp: Probably not used (the JVM's ARM code needs this for its own stack, after all)
* lr: The <tt>bxj</tt> instruction uses this as the address of the bytecode to jump to, and when an exception handler is called the address of the faulting instruction is stored here. (During actual Jazelle execution this is used as another temporary, but this is not visible to the JVM, so from the JVM's point of view this can be thought of as the Java program counter)


===Basic structure===
==Software handler table==


<syntaxhighlight lang="xml">
This contains routines that Jazelle calls when it encounters a bytecode it doesn't recognize, as well as in some exceptional conditions.
<wdgt
    xmlns:sc="urn:TI.ScriptApp" type="TI.ScriptApp" ver="1.0">


    <sc:mFlags>1024</sc:mFlags>
* +000-3FF: Unhandled bytecodes
    <sc:value>8</sc:value>
** The stack is flushed to memory before calling any of these handlers, so they may modify r0-r3 freely
    <sc:cry>0</sc:cry>
* +400: Null pointer exception
    <sc:legal>none</sc:legal>
* +404: Array index out of bounds exception
    <sc:schk>false</sc:schk>
* +40C: Jazelle mode entered with JE = 0
* +410: Configuration invalid (Jazelle mode entered with CV = 0)
** CV is automatically set to 1 on entering this handler
* +414: Prefetch abort occurred in middle of instruction


    <sc:md>
==Example code==
        <sc:mde name="_VER" prop="134217728">1:1</sc:mde>
        <sc:mde name="TITLE" prop="2147549184">Hello</sc:mde>
        <sc:mde name="TARAL" prop="134217728">2:5</sc:mde>
    </sc:md>


    <sc:script version="33882629" id="1">
The following code adds 2 and 2.
-- Lua script, XML encoded
    </sc:script>


    <sc:state>
<syntaxhighlight lang="asm">
        return {} -- Lua save state
.asciz "PRG"
    </sc:state>
push {r4-r11, lr}
</wdgt></syntaxhighlight>


===Script tags===
msr cpsr_c, #0x13          @ Enable interrupts


====sc:script====
@ Set Configuration Valid and Jazelle Enable bits
mov r0, #2
mcr p14, 7, r0, c1, c0, 0
mov r0, #1
mcr p14, 7, r0, c2, c0, 0


{| class="wikitable"
mov r5, #0x18000000        @ Handler table pointer (must be 1024-byte aligned)
|-
add r6, r5, #0x800          @ Stack pointer
! scope="col"| attribute
add r7, r5, #0x900          @ Local variables pointer
! scope="col"| description
|-
| version
| taral and reqal versions, one byte per digit (for older OSes?)
|-
| id
| 1 = normal script, 2 & 3 = Question and Answer
|}


===Script metadata configuration===
@ Set up handler for ireturn bytecode
adr r0, ireturn
str r0, [r5, #0xAC * 4]


{| class="wikitable"
@ Execute the bytecode
|-
adr r12, jazelle_unavailable
! scope="col"| Name
adr lr, bytecode
! scope="col"| Prop
bxj r12
! scope="col"| Description
 
! scope="col"| Example
bytecode:
|-
.byte 0x05 @ iconst_2
| TARAL
.byte 0x05 @ iconst_2
| 134217728
.byte 0x60 @ iadd
| TARget ApiLevel
.byte 0xAC @ ireturn
| <code><nowiki><sc:mde name="TARAL" prop="134217728">2:2</sc:mde></nowiki></code>
 
|-
ireturn:
| REQAL
@ Get result off the stack
| 134217728
ldr r0, [r6, #-4]!
| REQuired ApiLevel
 
| <code><nowiki><sc:mde name="REQAL" prop="134217728">2:0</sc:mde></nowiki></code>
@ Display it
|-
add r0, #'0'
| _VER
str r0, [sp, #-4]!
| 134217728
mov r0, #0
| TNS Version
add r1, sp, #2
| <code><nowiki><sc:mde name="_VER" prop="134217728">1:1</sc:mde></nowiki></code>
mov r2, sp
|-
swi 30 @ show_dialog_box2
| TITLE
add sp, #4
| 2147549184
 
| ScriptApp title
jazelle_unavailable:
| <code><nowiki><sc:mde name="TITLE" prop="2147549184">Hello</sc:mde></nowiki></code>
@ Restore configuration registers to 0
|-
mov r0, #0
| -
mcr p14, 7, r0, c1, c0, 0
| 270532608
mcr p14, 7, r0, c2, c0, 0
| Lua meta script
 
| <code><nowiki><sc:mde name="TEST" prop="270532608">--lua code</sc:mde></nowiki></code>
pop {r4-r11, pc}
|-
</syntaxhighlight>
| BLERQ
| 134217728
| BLE ReQuire - require ble libs
| <code><nowiki><sc:mde name="BLERQ" prop="134217728">1</sc:mde></nowiki></code>
|-
| _FFunc
| -
| FailMe function (error catching)
| Not known
|-
| _TRACE
| -
| Trace/log?
| Not known
|}

Latest revision as of 14:59, 21 June 2019

Jazelle is a feature of the TI-Nspire's ARM926EJ-S CPU that implements a subset of the Java bytecode instruction set in hardware.

The ARMv6 Architecture Reference Manual (DDI 0100I) gives some information about Jazelle, intended for operating system programmers who want to be able to correctly handle exceptions that occurred while in Jazelle state, or manage the configuration registers if two Jazelle JVMs with possibly different configurations could be running. However, most of the details of how to actually write a Jazelle JVM are left "SUBARCHITECTURE DEFINED". These details may be elaborated in the Jazelle v1 Architecture Reference Manual (DDI 0225A), but unfortunately this document is not available to the public.

Configuration registers

Configuration registers may be read with the instruction MRC{<cond>} p14, 7, <Rd>, <CRn>, c0, or written with MCR{<cond>} p14, 7, <Rd>, <CRn>, c0. A list of known CRn follows:

  • c0: Jazelle Identity register (read-only)
    • Bits 0-11: Subarchitecture-defined bits (reads as 4, meaning unknown)
    • Bits 12-19: Subarchitecture (reads as 0, Jazelle V1 according to documentation)
    • Bits 20-27: Implementor (reads as 0x41, ARM Limited according to documentation)
    • Bits 28-31: Architecture (reads as 6, ARMv5TEJ according to documentation)
  • c1: Operating System Control register
    • Bit 0: Configuration Disabled (CD) (documented)
    • Bit 1: Configuration Valid (CV) (documented)
  • c2: Main Configuration register
    • Bit 0: Jazelle Enable (JE) (documented)
    • Bits 26-28: Unknown
    • Bit 29: If set, array object contains its elements directly, otherwise it contains a pointer to its elements
    • Bit 31: Disable array instructions if set?
  • c3: Array object layout register
    • Bits 0-7: Unknown
    • Bits 8-11: Offset (in words) within array object of first element or of pointer to first element
    • Bits 12-15: Offset (in words) within array object of length
    • Bit 16: If set, offset to length is subtracted, otherwise added
    • Bits 17-19: Array length shift value (number of elements = stored length >> this)
    • Bits 20-21: Disable array instructions if set?

Register usage

  • r0-r3: Holds up to 4 words of the stack
  • r4: Copy of local variable 0. Only valid when local variable 0 is a single word (i.e. int, float, or Object; not long or double)
  • r5:
    • Bits 0-1: If any of the stack is held in registers, this specifies which of the registers in r0-r3 is currently the top of stack, otherwise this is 0
    • Bits 2-4: Number of stack words held in registers
    • Bit 5: Seems to get cleared upon entry to Jazelle state, unless a prefetch abort or data abort happens before any bytecode is read
    • Bits 6-9: Cleared immediately upon entry to Jazelle state
    • Bits 10-31: Pointer to software handler table (must be 1024-byte aligned)
  • r6: Pointer to top of stack (Note that the Java stack grows up, not down)
  • r7: Pointer to current method's local variables
  • r8: Pointer to constant pool? (haven't checked this yet)
  • r9-r11: Do not appear to be used; available for the JVM's own use
  • r12: Temporary
  • sp: Probably not used (the JVM's ARM code needs this for its own stack, after all)
  • lr: The bxj instruction uses this as the address of the bytecode to jump to, and when an exception handler is called the address of the faulting instruction is stored here. (During actual Jazelle execution this is used as another temporary, but this is not visible to the JVM, so from the JVM's point of view this can be thought of as the Java program counter)

Software handler table

This contains routines that Jazelle calls when it encounters a bytecode it doesn't recognize, as well as in some exceptional conditions.

  • +000-3FF: Unhandled bytecodes
    • The stack is flushed to memory before calling any of these handlers, so they may modify r0-r3 freely
  • +400: Null pointer exception
  • +404: Array index out of bounds exception
  • +40C: Jazelle mode entered with JE = 0
  • +410: Configuration invalid (Jazelle mode entered with CV = 0)
    • CV is automatically set to 1 on entering this handler
  • +414: Prefetch abort occurred in middle of instruction

Example code

The following code adds 2 and 2.

	.asciz	"PRG"
	push	{r4-r11, lr}

	msr	cpsr_c, #0x13           @ Enable interrupts

	@ Set Configuration Valid and Jazelle Enable bits
	mov	r0, #2
	mcr	p14, 7, r0, c1, c0, 0
	mov	r0, #1
	mcr	p14, 7, r0, c2, c0, 0

	mov	r5, #0x18000000         @ Handler table pointer (must be 1024-byte aligned)
	add	r6, r5, #0x800          @ Stack pointer
	add	r7, r5, #0x900          @ Local variables pointer

	@ Set up handler for ireturn bytecode
	adr	r0, ireturn
	str	r0, [r5, #0xAC * 4]

	@ Execute the bytecode
	adr	r12, jazelle_unavailable
	adr	lr, bytecode
	bxj	r12

bytecode:
	.byte	0x05	@ iconst_2
	.byte	0x05	@ iconst_2
	.byte	0x60	@ iadd
	.byte	0xAC	@ ireturn

ireturn:
	@ Get result off the stack
	ldr	r0, [r6, #-4]!

	@ Display it
	add	r0, #'0'
	str	r0, [sp, #-4]!
	mov	r0, #0
	add	r1, sp, #2
	mov	r2, sp
	swi	30	@ show_dialog_box2
	add	sp, #4

jazelle_unavailable:
	@ Restore configuration registers to 0
	mov	r0, #0
	mcr	p14, 7, r0, c1, c0, 0
	mcr	p14, 7, r0, c2, c0, 0

	pop	{r4-r11, pc}